diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/ast_adc.c | 233 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ast.c | 689 | ||||
-rw-r--r-- | drivers/i2c/i2c-core.c | 15 | ||||
-rw-r--r-- | drivers/i2c/i2c-dev.c | 113 | ||||
-rw-r--r-- | drivers/net/ftgmac100_26.c | 1211 | ||||
-rw-r--r-- | drivers/net/ftgmac100_26.h | 67 | ||||
-rwxr-xr-x | drivers/rtc/rtc-aspeed.c | 42 | ||||
-rw-r--r-- | drivers/serial/8250.c | 39 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 9 | ||||
-rw-r--r-- | drivers/watchdog/ast_wdt.c | 27 |
10 files changed, 1847 insertions, 598 deletions
diff --git a/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c index 3f95dc6f0f06..8f5aa541d12d 100644 --- a/drivers/hwmon/ast_adc.c +++ b/drivers/hwmon/ast_adc.c @@ -13,10 +13,10 @@ * 2012.11.26: Initial version [Ryan Chen] */ -/* attr ADC sysfs 0~max adc channel +/* attr ADC sysfs 0~max adc channel * 0 - show/store enable * 3 - show value -* 1 - show/store alarm_en set enable +* 1 - show/store alarm_en set enable * 2 - show alarm get statuse * 4 - show/store upper * 5 - show/store lower */ @@ -44,13 +44,33 @@ #define REST_DESIGN 5 + +#ifdef CONFIG_YOSEMITE +enum { + ADC_P5V = 0, + ADC_P12V, + ADC_P3V3_STBY, + ADC_P12V_SLOT0, + ADC_P12V_SLOT1, + ADC_P12V_SLOT2, + ADC_P12V_SLOT3, + ADC_P3V3, +}; + +enum { + REST_DESIGN_P3V3 = 6, + REST_DESIGN_P5V = 7, + REST_DESIGN_P12V = 8, +}; +#endif // CONFIG_YOSEMITE + struct adc_vcc_ref_data { int v2; int r1; - int r2; + int r2; }; -static struct adc_vcc_ref_data adc_vcc_ref[6] = { +static struct adc_vcc_ref_data adc_vcc_ref[9] = { [0] = { .v2 = 0, .r1 = 5600, @@ -81,6 +101,24 @@ static struct adc_vcc_ref_data adc_vcc_ref[6] = { .r1 = 1000, .r2 = 1000, }, + // P3V3 + [6] = { + .v2 = 0, + .r1 = 5110, + .r2 = 8250, + }, + // P5V + [7] = { + .v2 = 0, + .r1 = 5110, + .r2 = 3480, + }, + // P12V + [8] = { + .v2 = 0, + .r1 = 5110, + .r2 = 1020, + }, }; /* Divisors for voltage sense; right now adc5 & adc6 divide by 2 */ @@ -93,7 +131,7 @@ static int adc_divisor[] = { 1, 1, 1, 1, struct ast_adc_data { struct device *hwmon_dev; void __iomem *reg_base; /* virtual */ - int irq; //ADC IRQ number + int irq; //ADC IRQ number int compen_value; //Compensating value }; @@ -123,14 +161,14 @@ static void ast_adc_ctrl_init(void) ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); //Set wait a sensing cycle t (s) = 1000 * 12 * (1/PCLK) * 2 * (ADC0c[31:17] + 1) * (ADC0c[9:0] +1) - //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999 + //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999 // --> 0.0325s = 12 * 2 * (0x3e7 + 1) *(64+1) / 48000000 - // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000 - + // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000 + pclk = ast_get_pclk(); #if defined(CONFIG_ARCH_AST2300) - ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK); + ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK); ast_adc_write(ast_adc, AST_ADC_CTRL_CH12_EN | AST_ADC_CTRL_COMPEN_CLR| ast_adc_read(ast_adc, AST_ADC_CTRL), AST_ADC_CTRL); @@ -141,16 +179,16 @@ static void ast_adc_ctrl_init(void) ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK); else ast_adc->compen_value = 0 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK); - - printk("compensating value %d \n",ast_adc->compen_value); - + + // printk("compensating value %d \n",ast_adc->compen_value); + #elif defined(CONFIG_ARCH_AST2400) //For AST2400 A0 workaround ... ADC0c = 1 ; // ast_adc_write(ast_adc, 1, AST_ADC_CLK); // ast_adc_write(ast_adc, (0x3e7<< 17) | 0x40, AST_ADC_CLK); ast_adc_write(ast_adc, 0x40, AST_ADC_CLK); - + ast_adc_write(ast_adc, AST_ADC_CTRL_CH0_EN | AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); ast_adc_read(ast_adc, AST_ADC_CTRL); @@ -159,15 +197,15 @@ static void ast_adc_ctrl_init(void) //compensating value = 0x200 - ADC10[9:0] ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_L_CH_MASK); - printk("compensating value %d \n",ast_adc->compen_value); + // printk("compensating value %d \n",ast_adc->compen_value); #elif defined(CONFIG_ARCH_AST2500) -// TODO ... -// scu read trim +// TODO ... +// scu read trim // write trim 0xc4 [3:0] - + ast_adc_write(ast_adc, 0x40, AST_ADC_CLK); - + ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); while(!ast_adc_read(ast_adc, AST_ADC_CTRL) & 0x100); @@ -175,17 +213,17 @@ static void ast_adc_ctrl_init(void) ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); while(ast_adc_read(ast_adc, AST_ADC_CTRL) & AST_ADC_CTRL_COMPEN); - + //compensating value = 0x200 - ADC10[9:0] ast_adc->compen_value = 0x200 - ((ast_adc_read(ast_adc, AST_ADC_TRIM) >> 16) & 0x3ff); - printk("compensating value %d \n",ast_adc->compen_value); - + // printk("compensating value %d \n",ast_adc->compen_value); + #else #err "No define for ADC " #endif ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); - + } static u16 @@ -203,9 +241,9 @@ ast_get_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch) static void ast_set_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value) { - ast_adc_write(ast_adc, + ast_adc_write(ast_adc, (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) | - value, + value, AST_ADC_HYSTER0 + (adc_ch *4)); } @@ -224,9 +262,9 @@ ast_get_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch) static void ast_set_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) { - ast_adc_write(ast_adc, + ast_adc_write(ast_adc, (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) | - (value << 16), + (value << 16), AST_ADC_HYSTER0 + (adc_ch *4)); } @@ -244,7 +282,7 @@ ast_get_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch) static void ast_set_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) { - //tacho source + //tacho source if(enable == 1) ast_adc_write(ast_adc, ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) | AST_ADC_HYSTER_EN, @@ -270,9 +308,9 @@ ast_get_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch) static void ast_set_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value) { - ast_adc_write(ast_adc, + ast_adc_write(ast_adc, (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) | - value, + value, AST_ADC_BOUND0 + (adc_ch *4)); } @@ -293,9 +331,9 @@ ast_get_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch) static void ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) { - ast_adc_write(ast_adc, + ast_adc_write(ast_adc, (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) | - (value << 16), + (value << 16), AST_ADC_BOUND0 + (adc_ch *4)); } @@ -304,7 +342,7 @@ ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) static u8 ast_get_adc_alarm(struct ast_adc_data *ast_adc, u8 adc_ch) { - //adc ch source + //adc ch source if(ast_adc_read(ast_adc, AST_ADC_IER) & (0x1 << adc_ch)) return 1; else @@ -322,61 +360,61 @@ ast_get_adc_value(struct ast_adc_data *ast_adc, u8 adc_ch) break; case 1: tmp = (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 2: tmp = ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_L_CH_MASK; break; case 3: tmp = (ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 4: tmp = ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_L_CH_MASK; break; case 5: tmp = (ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 6: tmp = ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_L_CH_MASK; break; case 7: tmp = (ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 8: tmp = ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_L_CH_MASK; break; case 9: tmp = (ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 10: tmp = ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_L_CH_MASK; break; case 11: tmp = (ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 12: tmp = ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK; break; case 13: tmp = (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_H_CH_MASK) >> 16; - break; + break; case 14: tmp = ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_L_CH_MASK; break; case 15: tmp = (ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_H_CH_MASK) >> 16; - break; + break; } tmp += ast_adc->compen_value; // printk("voltage = %d \n",tmp); - + return tmp; } -static u8 +static u8 ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch) { u8 tmp=0; @@ -390,7 +428,7 @@ ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch) } -static void +static void ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) { if(enable) @@ -401,7 +439,7 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) /* NAME sysfs */ -static ssize_t +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { @@ -416,38 +454,63 @@ static const struct attribute_group name_attribute_groups = { .attrs = name_attributes, }; -/* attr ADC sysfs 0~max adc channel +/* attr ADC sysfs 0~max adc channel * 0 - show/store channel enable -* 1 - show value +* 1 - show value * 2 - show alarm get statuse * 3 - show/store upper -* 4 - show/store lower -* 5 - show/store hystersis enable -* 6 - show/store hystersis upper -* 7 - show/store hystersis low +* 4 - show/store lower +* 5 - show/store hystersis enable +* 6 - show/store hystersis upper +* 7 - show/store hystersis low */ -static u32 +static u32 ast_get_voltage(int idx) { + u8 rest_design = REST_DESIGN; u16 tmp; u32 voltage, tmp1, tmp2, tmp3; tmp = ast_get_adc_value(ast_adc, idx); + +#ifdef CONFIG_YOSEMITE + switch (idx) { + case ADC_P3V3: + case ADC_P3V3_STBY: + rest_design = REST_DESIGN_P3V3; + break; + case ADC_P5V: + rest_design = REST_DESIGN_P5V; + break; + case ADC_P12V: + case ADC_P12V_SLOT0: + case ADC_P12V_SLOT1: + case ADC_P12V_SLOT2: + case ADC_P12V_SLOT3: + rest_design = REST_DESIGN_P12V; + break; + default: + rest_design = REST_DESIGN; + } +#endif // CONFIG_YOSEMITE + // Voltage Sense Method - tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10; - tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1024 ; - tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2; + tmp1 = (adc_vcc_ref[rest_design].r1 + adc_vcc_ref[rest_design].r2) * tmp * 25 * 10; + tmp2 = adc_vcc_ref[rest_design].r2 * 1024 ; + tmp3 = (adc_vcc_ref[rest_design].r1 * adc_vcc_ref[rest_design].v2) / adc_vcc_ref[rest_design].r2; // printk("tmp3 = %d \n",tmp3); voltage = (tmp1/tmp2) - tmp3; +#ifndef CONFIG_YOSEMITE // Higher voltage inputs require a divisor if (adc_divisor[idx]) voltage /= adc_divisor[idx]; +#endif //CONFIG_YOSEMITE return voltage; } -static ssize_t +static ssize_t ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); @@ -455,7 +518,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) //sensor_attr->index : pwm_ch# //sensor_attr->nr : attr# - switch(sensor_attr->nr) + switch(sensor_attr->nr) { case 0: //channel enable, disable return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_en(ast_adc,sensor_attr->index),ast_get_adc_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); @@ -466,23 +529,23 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) break; case 2: //alarm return sprintf(sysfsbuf, "%d \n", ast_get_adc_alarm(ast_adc,sensor_attr->index)); - break; + break; case 3: //upper return sprintf(sysfsbuf, "%d \n", ast_get_adc_upper(ast_adc,sensor_attr->index)); - break; + break; case 4: //lower return sprintf(sysfsbuf, "%d \n", ast_get_adc_lower(ast_adc,sensor_attr->index)); - break; - case 5: //hystersis enable + break; + case 5: //hystersis enable return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_hyster_en(ast_adc,sensor_attr->index),ast_get_adc_hyster_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); - break; + break; case 6: //hystersis upper return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_upper(ast_adc,sensor_attr->index)); - break; + break; case 7: //hystersis lower return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_lower(ast_adc,sensor_attr->index)); - break; - case 8: + break; + case 8: voltage = ast_get_voltage(sensor_attr->index); return sprintf(sysfsbuf, "%d\n",voltage * 10); @@ -492,7 +555,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) } } -static ssize_t +static ssize_t ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count) { u32 input_val; @@ -503,16 +566,16 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys //sensor_attr->index : pwm_ch# //sensor_attr->nr : attr# - switch(sensor_attr->nr) + switch(sensor_attr->nr) { case 0: //enable, disable ast_set_adc_en(ast_adc, sensor_attr->index, input_val); break; case 1: //value - + break; case 2: //alarm - break; + break; case 3: ast_set_adc_upper(ast_adc, sensor_attr->index, input_val); break; @@ -521,14 +584,14 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys break; case 5: //hystersis ast_set_adc_hyster_en(ast_adc, sensor_attr->index, input_val); - break; + break; case 6: ast_set_adc_hyster_upper(ast_adc, sensor_attr->index, input_val); break; case 7: ast_set_adc_hyster_lower(ast_adc, sensor_attr->index, input_val); break; - + default: return -EINVAL; break; @@ -537,15 +600,15 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys return count; } -/* attr ADC sysfs 0~max adc channel +/* attr ADC sysfs 0~max adc channel * 0 - show/store channel enable -* 1 - show value +* 1 - show value * 2 - show alarm get statuse * 3 - show/store upper -* 4 - show/store lower -* 5 - show/store hystersis enable -* 6 - show/store hystersis upper -* 7 - show/store hystersis low +* 4 - show/store lower +* 5 - show/store hystersis enable +* 6 - show/store hystersis upper +* 7 - show/store hystersis low * 8 - show value as 1000s, expected by lm-sensors */ @@ -624,18 +687,18 @@ static const struct attribute_group adc_attribute_groups[] = { { .attrs = adc7_attributes }, { .attrs = adc8_attributes }, { .attrs = adc9_attributes }, - { .attrs = adc10_attributes }, + { .attrs = adc10_attributes }, { .attrs = adc11_attributes }, #if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST2500) { .attrs = adc12_attributes }, { .attrs = adc13_attributes }, { .attrs = adc14_attributes }, { .attrs = adc15_attributes }, -#endif +#endif }; -static int +static int ast_adc_probe(struct platform_device *pdev) { struct resource *res; @@ -695,7 +758,7 @@ ast_adc_probe(struct platform_device *pdev) } ast_adc_ctrl_init(); - + printk(KERN_INFO "ast_adc: driver successfully loaded.\n"); return 0; @@ -714,7 +777,7 @@ out: return ret; } -static int +static int ast_adc_remove(struct platform_device *pdev) { int i=0; @@ -739,14 +802,14 @@ ast_adc_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int +static int ast_adc_suspend(struct platform_device *pdev, pm_message_t state) { printk("ast_adc_suspend : TODO \n"); return 0; } -static int +static int ast_adc_resume(struct platform_device *pdev) { ast_adc_ctrl_init(); @@ -769,13 +832,13 @@ static struct platform_driver ast_adc_driver = { }, }; -static int __init +static int __init ast_adc_init(void) { return platform_driver_register(&ast_adc_driver); } -static void __exit +static void __exit ast_adc_exit(void) { platform_driver_unregister(&ast_adc_driver); diff --git a/drivers/i2c/busses/i2c-ast.c b/drivers/i2c/busses/i2c-ast.c index 7a083de714df..9bb3154e6bd8 100644 --- a/drivers/i2c/busses/i2c-ast.c +++ b/drivers/i2c/busses/i2c-ast.c @@ -40,63 +40,68 @@ #include <plat/ast_i2c.h> #endif -//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode +//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode /* Use platform_data instead of module parameters */ /* Fast Mode = 400 kHz, Standard = 100 kHz */ //static int clock = 100; /* Default: 100 kHz */ /***************************************************************************/ + +#ifdef CONFIG_AST_I2C_SLAVE_RDWR +#define I2C_S_BUF_SIZE 64 +#define I2C_S_RX_BUF_NUM 4 +#define BUFF_FULL 0xff00 +#define BUFF_ONGOING 1 +#endif + +#define AST_LOCKUP_DETECTED (0x1 << 15) + struct ast_i2c_dev { struct ast_i2c_driver_data *ast_i2c_data; struct device *dev; - void __iomem *reg_base; /* virtual */ - int irq; //I2C IRQ number - u32 bus_id; //for i2c dev# IRQ number check - u32 state; //I2C xfer mode state matchine + void __iomem *reg_base; /* virtual */ + int irq; //I2C IRQ number + u32 bus_id; //for i2c dev# IRQ number check + u32 state; //I2C xfer mode state matchine struct i2c_adapter adap; - struct buf_page *req_page; + struct buf_page *req_page; //dma or buff mode needed unsigned char *dma_buf; dma_addr_t dma_addr; - -//master + +//master int xfer_last; //cur xfer is last msgs for stop msgs struct i2c_msg *master_msgs; //cur xfer msgs - int master_xfer_len; //cur xfer len + int master_xfer_len; //cur xfer len int master_xfer_cnt; //total xfer count u32 master_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx struct completion cmd_complete; int cmd_err; u8 blk_r_flag; //for smbus block read - void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev); -//Slave structure + void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev); + spinlock_t master_lock; +//Slave structure u8 slave_operation; u8 slave_event; struct i2c_msg *slave_msgs; //cur slave xfer msgs - int slave_xfer_len; - int slave_xfer_cnt; - u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx + int slave_xfer_len; + int slave_xfer_cnt; + u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx void (*do_slave_xfer)(struct ast_i2c_dev *i2c_dev); -}; - #ifdef CONFIG_AST_I2C_SLAVE_RDWR -#define I2C_S_BUF_SIZE 64 -#define I2C_S_RX_BUF_NUM 4 -#define BUFF_FULL 0xff00 -#define BUFF_ONGOING 1 - -struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; -struct i2c_msg slave_tx_msg; -static spinlock_t slave_rx_lock = SPIN_LOCK_UNLOCKED; + struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; + struct i2c_msg slave_tx_msg; + spinlock_t slave_rx_lock; #endif +}; + -static spinlock_t g_master_lock = SPIN_LOCK_UNLOCKED; static inline void ast_i2c_write(struct ast_i2c_dev *i2c_dev, u32 val, u32 reg) { -// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg); +// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg); writel(val, i2c_dev->reg_base+ reg); } @@ -107,7 +112,7 @@ ast_i2c_read(struct ast_i2c_dev *i2c_dev, u32 reg) u32 val = readl(i2c_dev->reg_base + reg); printk("R : reg %x , val: %x \n",reg, val); return val; -#else +#else return readl(i2c_dev->reg_base + reg); #endif } @@ -152,7 +157,7 @@ static void ast_slave_issue_alert(struct ast_i2c_dev *i2c_dev, u8 enable) static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs) { if(msgs->buf[0] == 1) { - ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG); + ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG); ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) | AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); } else ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) & ~AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); @@ -162,12 +167,14 @@ static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *m static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) { - //I2CG Reset + //I2CG Reset ast_i2c_write(i2c_dev, 0, I2C_FUN_CTRL_REG); -#ifdef CONFIG_AST_I2C_SLAVE_EEPROM +#ifdef CONFIG_AST_I2C_SLAVE_EEPROM i2c_dev->ast_i2c_data->slave_init(&(i2c_dev->slave_msgs)); ast_slave_mode_enable(i2c_dev, i2c_dev->slave_msgs); +#else + i2c_dev->slave_msgs = i2c_dev->slave_rx_msg; #endif //Enable Master Mode @@ -177,20 +184,20 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) /* Set AC Timing */ #if defined(CONFIG_ARCH_AST2400) if(i2c_dev->ast_i2c_data->bus_clk/1000 > 400) { - printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000); + printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000); ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) | AST_I2CD_M_HIGH_SPEED_EN | AST_I2CD_M_SDA_DRIVE_1T_EN | - AST_I2CD_SDA_DRIVE_1T_EN + AST_I2CD_SDA_DRIVE_1T_EN , I2C_FUN_CTRL_REG); - + /* Set AC Timing */ ast_i2c_write(i2c_dev, 0x3, I2C_AC_TIMING_REG2); - ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); + ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); }else { - /* target apeed is xxKhz*/ + /* target apeed is xxKhz*/ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); - ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); + ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); } #else /* target apeed is xxKhz*/ @@ -206,12 +213,12 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) //TODO // ast_i2c_write(i2c_dev, 0xAF, I2C_INTR_CTRL_REG); - //Enable Interrupt, STOP Interrupt has bug in AST2000 - + //Enable Interrupt, STOP Interrupt has bug in AST2000 + /* Set interrupt generation of I2C controller */ ast_i2c_write(i2c_dev, - AST_I2CD_SDA_DL_TO_INTR_EN | - AST_I2CD_BUS_RECOVER_INTR_EN | + AST_I2CD_SDA_DL_TO_INTR_EN | + AST_I2CD_BUS_RECOVER_INTR_EN | AST_I2CD_SMBUS_ALT_INTR_EN | // AST_I2CD_SLAVE_MATCH_INTR_EN | AST_I2CD_SCL_TO_INTR_EN | @@ -230,16 +237,16 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev) { int i; - //Tx buf 1 - slave_tx_msg.len = I2C_S_BUF_SIZE; - slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); + //Tx buf 1 + i2c_dev->slave_tx_msg.len = I2C_S_BUF_SIZE; + i2c_dev->slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); //Rx buf 4 for(i=0; i<I2C_S_RX_BUF_NUM+1; i++) { - slave_rx_msg[i].addr = ~BUFF_ONGOING; - slave_rx_msg[i].flags = 0; //mean empty buffer - slave_rx_msg[i].len = I2C_S_BUF_SIZE; - slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); - } + i2c_dev->slave_rx_msg[i].addr = ~BUFF_ONGOING; + i2c_dev->slave_rx_msg[i].flags = 0; //mean empty buffer + i2c_dev->slave_rx_msg[i].len = I2C_S_BUF_SIZE; + i2c_dev->slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); + } } static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) @@ -247,13 +254,13 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) int i; unsigned long flags; - spin_lock_irqsave(&slave_rx_lock, flags); - + spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); + switch(i2c_dev->slave_event) { case I2C_SLAVE_EVENT_START_WRITE: for(i=0; i<I2C_S_RX_BUF_NUM; i++) { - if((slave_rx_msg[i].flags == 0) && (slave_rx_msg[i].addr != BUFF_ONGOING)) { - slave_rx_msg[i].addr = BUFF_ONGOING; + if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr != BUFF_ONGOING)) { + i2c_dev->slave_rx_msg[i].addr = BUFF_ONGOING; break; } } @@ -261,40 +268,40 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) printk("RX buffer full ........use tmp msgs buff \n"); //TODO... } - printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); + //printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); - i2c_dev->slave_msgs = &slave_rx_msg[i]; + i2c_dev->slave_msgs = &i2c_dev->slave_rx_msg[i]; break; case I2C_SLAVE_EVENT_START_READ: - printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); - i2c_dev->slave_msgs = &slave_tx_msg; + //printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); + i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; break; case I2C_SLAVE_EVENT_WRITE: - printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); - i2c_dev->slave_msgs = &slave_tx_msg; + //printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); + i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; break; case I2C_SLAVE_EVENT_READ: - printk("I2C_SLAVE_EVENT_READ ERROR ... \n"); - i2c_dev->slave_msgs = &slave_tx_msg; + printk("I2C_SLAVE_EVENT_READ ERROR ... \n"); + i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; break; case I2C_SLAVE_EVENT_NACK: - printk("I2C_SLAVE_EVENT_NACK ERROR ... \n"); - i2c_dev->slave_msgs = &slave_tx_msg; + //printk("I2C_SLAVE_EVENT_NACK ERROR ... \n"); + i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; break; case I2C_SLAVE_EVENT_STOP: - printk("I2C_SLAVE_EVENT_STOP \n"); + //printk("I2C_SLAVE_EVENT_STOP \n"); for(i=0; i<I2C_S_RX_BUF_NUM; i++) { - if(slave_rx_msg[i].addr == BUFF_ONGOING) { - slave_rx_msg[i].flags = BUFF_FULL; - slave_rx_msg[i].addr = 0; + if(i2c_dev->slave_rx_msg[i].addr == BUFF_ONGOING) { + i2c_dev->slave_rx_msg[i].flags = BUFF_FULL; + i2c_dev->slave_rx_msg[i].addr = 0; break; } } - - i2c_dev->slave_msgs = &slave_tx_msg; + + i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; break; } - spin_unlock_irqrestore(&slave_rx_lock, flags); + spin_unlock_irqrestore(&i2c_dev->slave_rx_lock, flags); } @@ -308,29 +315,29 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) case 0: // printk("slave read \n"); //cur_msg = get_free_msg; - spin_lock_irqsave(&slave_rx_lock, flags); + spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); for(i=0; i<I2C_S_RX_BUF_NUM; i++) { - if((slave_rx_msg[i].addr == 0) && (slave_rx_msg[i].flags == BUFF_FULL)) { - memcpy(msgs->buf, slave_rx_msg[i].buf, slave_rx_msg[i].len); - msgs->len = slave_rx_msg[i].len; - slave_rx_msg[i].flags = 0; - slave_rx_msg[i].len = 0; + if((i2c_dev->slave_rx_msg[i].addr == 0) && (i2c_dev->slave_rx_msg[i].flags == BUFF_FULL)) { + memcpy(msgs->buf, i2c_dev->slave_rx_msg[i].buf, i2c_dev->slave_rx_msg[i].len); + msgs->len = i2c_dev->slave_rx_msg[i].len; + i2c_dev->slave_rx_msg[i].flags = 0; + i2c_dev->slave_rx_msg[i].len = 0; break; } } - spin_unlock_irqrestore(&slave_rx_lock, flags); - + spin_unlock_irqrestore(&i2c_dev->slave_rx_lock, flags); + if(i == I2C_S_RX_BUF_NUM) { - printk("No buffer ........ \n"); + //printk("No buffer ........ \n"); msgs->len = 0; ret = -1; } break; case I2C_M_RD: //slave write // printk("slave write \n"); - memcpy(msgs->buf, slave_tx_msg.buf, I2C_S_BUF_SIZE); - break; + memcpy(msgs->buf, i2c_dev->slave_tx_msg.buf, I2C_S_BUF_SIZE); + break; case I2C_S_EN: if((msgs->addr < 0x1) || (msgs->addr > 0xff)) { ret = -1; @@ -352,7 +359,7 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) default: printk("slave xfer error \n"); break; - + } return ret; } @@ -360,16 +367,16 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) #endif -static u8 +static u8 ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) { u32 sts; - int r; + int r; u32 i = 0; - + //Check 0x14's SDA and SCL status sts = ast_i2c_read(i2c_dev,I2C_CMD_REG); - + if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) { //Means bus is idle. dev_dbg(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); @@ -377,11 +384,11 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) } dev_dbg(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id); - - + + if ((sts & AST_I2CD_SDA_LINE_STS) && !(sts & AST_I2CD_SCL_LINE_STS)) { //if SDA == 1 and SCL == 0, it means the master is locking the bus. - //Send a stop command to unlock the bus. + //Send a stop command to unlock the bus. dev_dbg(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); // init_completion(&i2c_dev->cmd_complete); @@ -397,12 +404,12 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) dev_dbg(i2c_dev->dev, "recovery error \n"); return -1; } - + if (r == 0) { dev_dbg(i2c_dev->dev, "recovery timed out\n"); return -1; } else { - dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + dev_dbg(i2c_dev->dev, "Recovery successfully\n"); return 0; } @@ -415,11 +422,11 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) for (i = 0; i < 10; i++) { ast_i2c_dev_init(i2c_dev); //Do the recovery command BIT11 - init_completion(&i2c_dev->cmd_complete); + init_completion(&i2c_dev->cmd_complete); ast_i2c_write(i2c_dev, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG); - + r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, - i2c_dev->adap.timeout*HZ); + i2c_dev->adap.timeout*HZ); if (i2c_dev->cmd_err != 0 && i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); @@ -438,31 +445,56 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) dev_dbg(i2c_dev->dev, "Don't know how to handle this case?!\n"); return -1; } - dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + dev_dbg(i2c_dev->dev, "Recovery successfully\n"); return 0; } -static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev) +static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev) { printk("ast_master_alert_recv bus id %d, Disable Alt, Please Imple \n",i2c_dev->bus_id); } static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) { - int timeout = 32; //TODO number + int timeout = 10; //TODO number + volatile u8 mode = 0; // printk("ast_i2c_wait_bus_not_busy \n"); + + // Wait for slave transfer to finish + mode = i2c_dev->slave_operation; + while (mode == 1) { + if (timeout <= 0) { + break; + } + mode = i2c_dev->slave_operation; + timeout--; + msleep(1); + } + + if (timeout <= 0) { + return -EAGAIN; + } + + // Wait for Bus to go IDLE + timeout = 10; while (ast_i2c_read(i2c_dev,I2C_CMD_REG) & AST_I2CD_BUS_BUSY_STS) { - ast_i2c_bus_error_recover(i2c_dev); - if(timeout<=0) + if(timeout<=0) { break; + } + timeout--; - msleep(2); + msleep(1); } - return timeout <= 0 ? EAGAIN : 0; + if (timeout <=0) { + ast_i2c_bus_error_recover(i2c_dev); + return 0; + } + + return 0; } -static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) +static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) { u32 cmd = 0; int i; @@ -470,49 +502,49 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) i2c_dev->master_xfer_mode = DMA_XFER; i2c_dev->slave_xfer_mode = DMA_XFER; - if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_operation == 1) { if(i2c_dev->slave_msgs->flags & I2C_M_RD) { //DMA tx mode if(i2c_dev->slave_msgs->len > AST_I2C_DMA_SIZE) i2c_dev->slave_xfer_len = AST_I2C_DMA_SIZE; - else + else i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len; - + dev_dbg(i2c_dev->dev, "(<--) slave tx DMA \n"); for(i=0; i<i2c_dev->slave_xfer_len; i++) i2c_dev->dma_buf[i] = i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt + i]; - + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); ast_i2c_write(i2c_dev, (i2c_dev->slave_xfer_len-1), I2C_DMA_LEN_REG); - ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG); + ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG); } else { //DMA prepare rx dev_dbg(i2c_dev->dev, "(-->) slave rx DMA \n"); ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); ast_i2c_write(i2c_dev, (AST_I2C_DMA_SIZE-1), I2C_DMA_LEN_REG); - ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG); + ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG); } } else { dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); if(i2c_dev->master_xfer_cnt == -1) { - //send start + //send start dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); if(i2c_dev->master_msgs->flags & I2C_M_RD) { - //workaround .. HW can;t send start read addr with buff mode + //workaround .. HW can;t send start read addr with buff mode cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD; ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); // tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 i2c_dev->master_xfer_len = 1; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } else { //tx - cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE; + cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE; i2c_dev->dma_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 //next data write @@ -520,44 +552,44 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; else i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1; - + for(i = 1; i < i2c_dev->master_xfer_len; i++) i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt+i]; - + if (i2c_dev->xfer_last == 1) { dev_dbg(i2c_dev->dev, "last stop \n"); cmd |= AST_I2CD_M_STOP_CMD; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & - ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); ast_i2c_write(i2c_dev, (i2c_dev->master_xfer_len-1), I2C_DMA_LEN_REG); - + } - ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){ - //Next send + //Next send if(i2c_dev->master_msgs->flags & I2C_M_RD) { //Rx data cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_DMA_ENABLE; - + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) { i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); - + } else { i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else { #ifdef CONFIG_AST1010 //Workaround for ast1010 can't send NACK @@ -568,7 +600,7 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) i2c_dev->master_xfer_mode = BYTE_XFER; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); - + } else if (i2c_dev->master_xfer_len > 1) { i2c_dev->master_xfer_len -=1; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | @@ -578,8 +610,8 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) } #else if(i2c_dev->xfer_last == 1) { - dev_dbg(i2c_dev->dev, "last stop \n"); - cmd |= AST_I2CD_M_STOP_CMD; + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else { @@ -588,9 +620,9 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) } //TODO check.... cmd |= AST_I2CD_M_S_RX_CMD_LAST; -#endif +#endif } - + } ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); ast_i2c_write(i2c_dev, i2c_dev->master_xfer_len-1, I2C_DMA_LEN_REG); @@ -603,23 +635,23 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) { i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; if(i2c_dev->xfer_last == 1) { dev_dbg(i2c_dev->dev, "last stop \n"); cmd |= AST_I2CD_M_STOP_CMD; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & - ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } } - for(i = 0; i < i2c_dev->master_xfer_len; i++) + for(i = 0; i < i2c_dev->master_xfer_len; i++) i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i]; ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); @@ -627,33 +659,33 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG); dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); - } + } }else { - //should send next msg + //should send next msg if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n", i2c_dev->bus_id, i2c_dev->master_msgs->addr, i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); - + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); i2c_dev->cmd_err = 0; - complete(&i2c_dev->cmd_complete); + complete(&i2c_dev->cmd_complete); } - + } - + } -static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) +static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) { u32 cmd = 0; int i; u32 *tx_buf; i2c_dev->master_xfer_mode = BUFF_XFER; - i2c_dev->slave_xfer_mode = BUFF_XFER; - + i2c_dev->slave_xfer_mode = BUFF_XFER; + #if defined(CONFIG_ARCH_AST2400) ast_i2c_write(i2c_dev, (ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) & @@ -665,15 +697,15 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) tx_buf = (u32 *) i2c_dev->req_page->page_addr; - if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_operation == 1) { if(i2c_dev->slave_msgs->flags & I2C_M_RD) { dev_dbg(i2c_dev->dev, "(<--) slave tx buf \n"); - + if(i2c_dev->slave_msgs->len > i2c_dev->req_page->page_size) i2c_dev->slave_xfer_len = i2c_dev->req_page->page_size; else i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len; - + for(i = 0; i< i2c_dev->slave_xfer_len; i++) { if(i%4 == 0) tx_buf[i/4] = 0; @@ -681,80 +713,80 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) dev_dbg(i2c_dev->dev, "[%x] ",tx_buf[i/4]); } dev_dbg(i2c_dev->dev, "\n"); - - ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) | - AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), + + ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) | + AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), I2C_BUF_CTRL_REG); - + ast_i2c_write(i2c_dev, AST_I2CD_TX_BUFF_ENABLE | AST_I2CD_S_TX_CMD, I2C_CMD_REG); } else { //prepare for new rx dev_dbg(i2c_dev->dev, "(-->) slave prepare rx buf \n"); - ast_i2c_write(i2c_dev, + ast_i2c_write(i2c_dev, AST_I2CD_RX_BUF_END_ADDR_SET((i2c_dev->req_page->page_size-1)) | AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), I2C_BUF_CTRL_REG); - ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG); - + ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG); + } } else { dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); if(i2c_dev->master_xfer_cnt == -1) { - //send start + //send start dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); if(i2c_dev->master_msgs->flags & I2C_M_RD) { -//workaround .. HW can;t send start read addr with buff mode +//workaround .. HW can;t send start read addr with buff mode cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD; ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); // tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 i2c_dev->master_xfer_len = 1; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } else { - cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE; + cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE; tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 //next data write if((i2c_dev->master_msgs->len + 1) > i2c_dev->req_page->page_size) i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; else i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1; - + for(i = 1; i < i2c_dev->master_xfer_len; i++) { if(i%4 == 0) tx_buf[i/4] = 0; tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ; } - + if (i2c_dev->xfer_last == 1) { dev_dbg(i2c_dev->dev, "last stop \n"); cmd |= AST_I2CD_M_STOP_CMD; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & - ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } - ast_i2c_write(i2c_dev, + ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) | AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point), I2C_BUF_CTRL_REG); } - ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){ - //Next send + //Next send if(i2c_dev->master_msgs->flags & I2C_M_RD) { //Rx data cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_BUFF_ENABLE; - + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) { i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | @@ -764,11 +796,11 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else { if(i2c_dev->xfer_last == 1) { - dev_dbg(i2c_dev->dev, "last stop \n"); - cmd |= AST_I2CD_M_STOP_CMD; + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else { @@ -791,46 +823,46 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) { i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; if(i2c_dev->xfer_last == 1) { dev_dbg(i2c_dev->dev, "last stop \n"); cmd |= AST_I2CD_M_STOP_CMD; ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & - ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); } } - + for(i = 0; i < i2c_dev->master_xfer_len; i++) { if(i%4 == 0) tx_buf[i/4] = 0; tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ; } -// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG)); - ast_i2c_write(i2c_dev, +// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG)); + ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) | AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point), I2C_BUF_CTRL_REG); - + ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG); dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); } } else { - //should send next msg + //should send next msg if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n", i2c_dev->bus_id, i2c_dev->master_msgs->addr, i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); - + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); i2c_dev->cmd_err = 0; - complete(&i2c_dev->cmd_complete); + complete(&i2c_dev->cmd_complete); } } @@ -843,16 +875,16 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) i2c_dev->master_xfer_mode = BYTE_XFER; i2c_dev->master_xfer_len = 1; - i2c_dev->slave_xfer_mode = BYTE_XFER; + i2c_dev->slave_xfer_mode = BYTE_XFER; i2c_dev->slave_xfer_len = 1; - - if(i2c_dev->slave_operation == 1) { + + if(i2c_dev->slave_operation == 1) { dev_dbg(i2c_dev->dev,"S cnt %d, xf len %d \n",i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->len); if(i2c_dev->slave_msgs->flags & I2C_M_RD) { //READ <-- TX dev_dbg(i2c_dev->dev, "(<--) slave(tx) buf %d [%x]\n", i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]); ast_i2c_write(i2c_dev, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt], I2C_BYTE_BUF_REG); - ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG); + ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG); } else { // Write -->Rx //no need to handle in byte mode @@ -862,21 +894,21 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) } else { dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); if(i2c_dev->master_xfer_cnt == -1) { - //first start + //first start dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); - - - if(i2c_dev->master_msgs->flags & I2C_M_RD) + + + if(i2c_dev->master_msgs->flags & I2C_M_RD) ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); else ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1), I2C_BYTE_BUF_REG); ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); - + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD, I2C_CMD_REG); @@ -888,7 +920,7 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->master_xfer_cnt == 0)) { dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) { cmd |= AST_I2CD_M_S_RX_CMD_LAST | AST_I2CD_M_STOP_CMD; @@ -897,11 +929,11 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } else { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); } dev_dbg(i2c_dev->dev, "(<--) rx byte, cmd = %x \n",cmd); - + ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); @@ -911,29 +943,29 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) ast_i2c_write(i2c_dev, *(xfer_buf + i2c_dev->master_xfer_cnt), I2C_BYTE_BUF_REG); if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & - ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_STOP_CMD, I2C_CMD_REG); } else { ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD, I2C_CMD_REG); } } - + } else { - //should send next msg + //should send next msg if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) printk("CNT ERROR bus=%d addr=0x%x (%d vs. %d)\n", i2c_dev->bus_id, i2c_dev->master_msgs->addr, i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); - + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); i2c_dev->cmd_err = 0; - complete(&i2c_dev->cmd_complete); - + complete(&i2c_dev->cmd_complete); + } } - + } static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) @@ -941,8 +973,8 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) u32 xfer_len; int i; u8 *rx_buf; - - dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); + + dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); if (i2c_dev->slave_msgs->flags & I2C_M_RD) { //tx done , only check tx count ... @@ -979,16 +1011,16 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); if(xfer_len == 0) xfer_len = AST_I2C_PAGE_SIZE; - + dev_dbg(i2c_dev->dev,"rx buff done len %d \n",xfer_len); - + rx_buf = (u8 *)i2c_dev->req_page->page_addr; - + for(i=0;i<xfer_len;i++) { i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = rx_buf[i]; dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]); } - + } else { //RX DMA DOWN xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG); @@ -996,15 +1028,15 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) xfer_len = i2c_dev->slave_xfer_len; else xfer_len = i2c_dev->slave_xfer_len - xfer_len - 1; - + dev_dbg(i2c_dev->dev, " rx dma done len %d \n", xfer_len); - + for(i=0;i<xfer_len;i++) { i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = i2c_dev->dma_buf[i]; dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]); } } - + } if(xfer_len !=i2c_dev->slave_xfer_len) { @@ -1012,7 +1044,7 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) printk(" **slave xfer error ====\n"); //should goto stop.... } else - i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len; + i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len; if((i2c_dev->slave_event == I2C_SLAVE_EVENT_NACK) || (i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP)) { @@ -1020,33 +1052,33 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) ast_i2c_slave_rdwr_xfer(i2c_dev); #else i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); -#endif +#endif i2c_dev->slave_xfer_cnt = 0; } else { if(i2c_dev->slave_xfer_cnt == i2c_dev->slave_msgs->len) { - dev_dbg(i2c_dev->dev,"slave next msgs \n"); + dev_dbg(i2c_dev->dev,"slave next msgs \n"); #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_rdwr_xfer(i2c_dev); #else i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); -#endif +#endif i2c_dev->slave_xfer_cnt = 0; - } + } i2c_dev->do_slave_xfer(i2c_dev); } if(AST_I2CD_IDLE == i2c_dev->state) { - dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); + dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); i2c_dev->slave_operation = 0; - + if(i2c_dev->slave_xfer_mode == BUFF_XFER) { i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); - } - - } - + } + + } + } //TX/Rx Done @@ -1057,7 +1089,7 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) u8 *pool_buf; unsigned long flags; - spin_lock_irqsave(&g_master_lock, flags); + spin_lock_irqsave(&i2c_dev->master_lock, flags); /* * This function shall be involked during interrupt handling. @@ -1068,8 +1100,8 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) goto unlock_out; } - dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode); - + dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode); + if (i2c_dev->master_msgs->flags & I2C_M_RD) { if(i2c_dev->master_xfer_cnt == -1) { xfer_len = 1; @@ -1077,16 +1109,16 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) } if(i2c_dev->master_xfer_mode == BYTE_XFER) { if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { - i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; + i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; i2c_dev->blk_r_flag = 1; - dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); } xfer_len = 1; i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt] = (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { pool_buf = (u8 *)i2c_dev->req_page->page_addr; xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); - + if(xfer_len == 0) xfer_len = AST_I2C_PAGE_SIZE; @@ -1098,7 +1130,7 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { i2c_dev->master_msgs->len += pool_buf[0]; i2c_dev->blk_r_flag = 1; - dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); } } else { //DMA Mode @@ -1114,13 +1146,13 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i]); dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i+1]); } - + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { i2c_dev->master_msgs->len += i2c_dev->dma_buf[0]; i2c_dev->blk_r_flag = 1; - dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); } - + } }else { @@ -1153,28 +1185,28 @@ next_xfer: i2c_dev->cmd_err = 1; goto done_out; } else - i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len; + i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len; if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) { dev_dbg(i2c_dev->dev,"do next cnt \n"); i2c_dev->do_master_xfer(i2c_dev); } else { -#if 0 - int i; +#if 0 + int i; printk(" ===== \n"); for(i=0;i<i2c_dev->master_msgs->len;i++) printk("rx buf i,[%x]\n",i,i2c_dev->master_msgs->buf[i]); - printk(" ===== \n"); -#endif + printk(" ===== \n"); +#endif i2c_dev->cmd_err = 0; done_out: dev_dbg(i2c_dev->dev,"msgs complete \n"); - complete(&i2c_dev->cmd_complete); + complete(&i2c_dev->cmd_complete); } unlock_out: - spin_unlock_irqrestore(&g_master_lock, flags); + spin_unlock_irqrestore(&i2c_dev->master_lock, flags); } static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) @@ -1187,7 +1219,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) i2c_dev->slave_msgs->buf[0] = match; dev_dbg(i2c_dev->dev, "S Start Addr match [%x] \n",match); - + if(match & 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_START_READ; } else { @@ -1201,7 +1233,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) #else i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); i2c_dev->slave_xfer_cnt = 0; -#endif +#endif //request if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) @@ -1211,7 +1243,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) else { if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) i2c_dev->do_slave_xfer = ast_i2c_do_pool_xfer; - else + else i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; } @@ -1221,7 +1253,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) { - u32 sts; + u32 sts; struct ast_i2c_dev *i2c_dev = dev_id; u32 isr_sts = readl(i2c_dev->ast_i2c_data->reg_gr); @@ -1231,7 +1263,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; sts = ast_i2c_read(i2c_dev,I2C_INTR_STS_REG); -// printk("ISR : %x , sts [%x]\n",sts , xfer_sts); +// printk("ISR : %x , sts [%x]\n",sts , xfer_sts); // dev_dbg(i2c_dev->dev,"ISR : %x , sts [%x]\n",sts , xfer_sts); // dev_dbg(i2c_dev->dev,"sts machine %x, slave_op %d \n", xfer_sts,i2c_dev->slave_operation); @@ -1244,9 +1276,9 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) I2C_INTR_CTRL_REG); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SMBUS_ALT, I2C_INTR_STS_REG); ast_master_alert_recv(i2c_dev); - sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; + sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; } - + if(AST_I2CD_INTR_STS_ABNORMAL & sts) { i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; // Turn off interrupts for further abnormal @@ -1257,6 +1289,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) I2C_INTR_CTRL_REG); complete(&i2c_dev->cmd_complete); sts &= ~AST_I2CD_INTR_STS_ABNORMAL; + // Need to clear the interrupt + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ABNORMAL, I2C_INTR_STS_REG); } switch(sts) { @@ -1265,7 +1299,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) i2c_dev->slave_event = I2C_SLAVE_EVENT_READ; ast_i2c_slave_xfer_done(i2c_dev); dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); - ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); @@ -1280,9 +1314,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_master_xfer_done(i2c_dev); - + } else { - printk("TODO ...\n"); + printk("ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_NORMAL_STOP_INTR_EN | + AST_I2CD_TX_ACK_INTR_EN; + ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); + //take care + i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; + complete(&i2c_dev->cmd_complete); } break; @@ -1291,8 +1333,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; ast_i2c_slave_xfer_done(i2c_dev); dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); - ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); - + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); + } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); @@ -1310,7 +1352,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP: if(i2c_dev->slave_operation == 1) { printk("SLAVE TODO .... \n"); - + } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); @@ -1320,47 +1362,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) } break; - //Issue : Workaround for I2C slave mode + //Issue : Workaround for I2C slave mode case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH: if(i2c_dev->slave_operation == 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; ast_i2c_slave_xfer_done(i2c_dev); ast_i2c_slave_addr_match(i2c_dev); - ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); } else { printk("ERROR !!!!\n"); } break; case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH: ast_i2c_slave_addr_match(i2c_dev); - dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); break; - + case AST_I2CD_INTR_STS_RX_DOWN: if(i2c_dev->slave_operation == 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_WRITE; ast_i2c_slave_xfer_done(i2c_dev); dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); - ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); ast_i2c_master_xfer_done(i2c_dev); - + } break; - + case AST_I2CD_INTR_STS_NORMAL_STOP: if(i2c_dev->slave_operation == 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; ast_i2c_slave_xfer_done(i2c_dev); dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); - ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); dev_dbg(i2c_dev->dev, "state [%x] \n",i2c_dev->state); - } else { + } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); - ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); i2c_dev->cmd_err |= AST_I2CD_INTR_STS_NORMAL_STOP; complete(&i2c_dev->cmd_complete); } @@ -1380,24 +1422,24 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; - complete(&i2c_dev->cmd_complete); + complete(&i2c_dev->cmd_complete); break; case AST_I2CD_INTR_STS_SCL_TO: i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; - complete(&i2c_dev->cmd_complete); - + complete(&i2c_dev->cmd_complete); + break; case AST_I2CD_INTR_STS_GCALL_ADDR: i2c_dev->cmd_err |= AST_I2CD_INTR_STS_GCALL_ADDR; - complete(&i2c_dev->cmd_complete); + complete(&i2c_dev->cmd_complete); break; case AST_I2CD_INTR_STS_SMBUS_DEF_ADDR: break; case AST_I2CD_INTR_STS_SMBUS_DEV_ALT: - + break; - + case AST_I2CD_INTR_STS_SMBUS_ARP_ADDR: break; case AST_I2CD_INTR_STS_SDA_DL_TO: @@ -1405,25 +1447,50 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) case AST_I2CD_INTR_STS_BUS_RECOVER: dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG); - complete(&i2c_dev->cmd_complete); + complete(&i2c_dev->cmd_complete); break; default: - if(sts) - printk("GR %x : No one care : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); - return IRQ_NONE; + //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function + ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); + + // Handle Arbitration Loss + if (sts & AST_I2CD_INTR_STS_ARBIT_LOSS) { + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; + complete(&i2c_dev->cmd_complete); + sts &= (~AST_I2CD_INTR_STS_ARBIT_LOSS); + } + + // Handle the write transaction ACK + if (sts & AST_I2CD_INTR_STS_TX_ACK) { + ast_i2c_master_xfer_done(i2c_dev); + complete(&i2c_dev->cmd_complete); + sts &= (~AST_I2CD_INTR_STS_TX_ACK); + } + + // Handle the Slave address match + if (sts & AST_I2CD_INTR_STS_SLAVE_MATCH) { + ast_i2c_slave_addr_match(i2c_dev); + sts &= (~AST_I2CD_INTR_STS_SLAVE_MATCH); + } + + // TODO: Debug print for any unhandled condition + if(sts) { + printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); + } + + return IRQ_HANDLED; } return IRQ_HANDLED; - } static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs, int num) { int i; - int ret = 1; + int ret = 1; unsigned long flags; - spin_lock_irqsave(&g_master_lock, flags); + spin_lock_irqsave(&i2c_dev->master_lock, flags); //request if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) @@ -1433,7 +1500,7 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg else { if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) i2c_dev->do_master_xfer = ast_i2c_do_pool_xfer; - else + else i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; } @@ -1458,12 +1525,12 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg i2c_dev->do_master_xfer(i2c_dev); - spin_unlock_irqrestore(&g_master_lock, flags); + spin_unlock_irqrestore(&i2c_dev->master_lock, flags); ret = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, i2c_dev->adap.timeout*HZ); - - spin_lock_irqsave(&g_master_lock, flags); + + spin_lock_irqsave(&i2c_dev->master_lock, flags); i2c_dev->master_msgs = NULL; if (ret == 0) { @@ -1471,25 +1538,30 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; // printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG)); ret = -ETIMEDOUT; - spin_unlock_irqrestore(&g_master_lock, flags); + spin_unlock_irqrestore(&i2c_dev->master_lock, flags); goto stop; } - + if(i2c_dev->cmd_err != 0 && i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { + if (i2c_dev->cmd_err & AST_LOCKUP_DETECTED) { + printk("ast-i2c: error got unexpected STOP\n"); + // reset the bus + ast_i2c_bus_error_recover(i2c_dev); + } ret = -EAGAIN; - spin_unlock_irqrestore(&g_master_lock, flags); + spin_unlock_irqrestore(&i2c_dev->master_lock, flags); goto stop; } } - spin_unlock_irqrestore(&g_master_lock, flags); + spin_unlock_irqrestore(&i2c_dev->master_lock, flags); if(i2c_dev->cmd_err == 0 || i2c_dev->cmd_err == AST_I2CD_INTR_STS_NORMAL_STOP) { ret = num; goto out; - + } stop: init_completion(&i2c_dev->cmd_complete); @@ -1503,8 +1575,8 @@ out: //Free .. if(i2c_dev->master_xfer_mode == BUFF_XFER) { i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); - - } + + } dev_dbg(i2c_dev->dev, "end xfer ret = %d, xfer mode[%d]\n",ret, i2c_dev->master_xfer_mode); return ret; @@ -1521,7 +1593,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) /* * Wait for the bus to become free. */ - + ret = ast_i2c_wait_bus_not_busy(i2c_dev); if (ret) { dev_err(&i2c_dev->adap.dev, "i2c_ast: timeout waiting for bus free\n"); @@ -1536,7 +1608,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) dev_dbg(&adap->dev, "Retrying transmission [%d]\n",i); udelay(100); } - + ret = -EREMOTEIO; out: @@ -1550,9 +1622,9 @@ static u32 ast_i2c_functionality(struct i2c_adapter *adap) static const struct i2c_algorithm i2c_ast_algorithm = { .master_xfer = ast_i2c_xfer, -#ifdef CONFIG_AST_I2C_SLAVE_RDWR +#ifdef CONFIG_AST_I2C_SLAVE_RDWR .slave_xfer = ast_i2c_slave_xfer, -#endif +#endif .functionality = ast_i2c_functionality, }; @@ -1572,23 +1644,23 @@ static int ast_i2c_probe(struct platform_device *pdev) i2c_dev->ast_i2c_data = pdev->dev.platform_data; if(i2c_dev->ast_i2c_data->master_dma == BUFF_MODE) { - dev_dbg(&pdev->dev, "use buffer pool mode 256\n"); - + dev_dbg(&pdev->dev, "use buffer pool mode 256\n"); + } else if ((i2c_dev->ast_i2c_data->master_dma == DMA_MODE) || (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE)) { - dev_dbg(&pdev->dev, "use dma mode \n"); + dev_dbg(&pdev->dev, "use dma mode \n"); if (!i2c_dev->dma_buf) { i2c_dev->dma_buf = dma_alloc_coherent(NULL, AST_I2C_DMA_SIZE, &i2c_dev->dma_addr, GFP_KERNEL); if (!i2c_dev->dma_buf) { printk("unable to allocate tx Buffer memory\n"); ret = -ENOMEM; - goto err_no_dma; + goto err_no_dma; } if(i2c_dev->dma_addr%4 !=0) { printk("not 4 byte boundary \n"); ret = -ENOMEM; - goto err_no_dma; - } -// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr); + goto err_no_dma; + } +// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr); memset (i2c_dev->dma_buf, 0, AST_I2C_DMA_SIZE); } @@ -1596,7 +1668,7 @@ static int ast_i2c_probe(struct platform_device *pdev) //master_mode 0: use byte mode dev_dbg(&pdev->dev, "use default byte mode \n"); } - + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (NULL == res) { dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n"); @@ -1628,11 +1700,11 @@ static int ast_i2c_probe(struct platform_device *pdev) if(i2c_dev->irq == IRQ_C0_I2C) { i2c_dev->bus_id = pdev->id - NUM_BUS; dev_dbg(&pdev->dev, "C0 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); -#if (CONFIG_AST1070_NR >= 2) +#if (CONFIG_AST1070_NR >= 2) } else if(i2c_dev->irq == IRQ_C1_I2C) { i2c_dev->bus_id = pdev->id - (NUM_BUS + 8); - dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); -#endif + dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +#endif } else { i2c_dev->bus_id = pdev->id; dev_dbg(&pdev->dev, "AST pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); @@ -1644,13 +1716,13 @@ static int ast_i2c_probe(struct platform_device *pdev) /* Initialize the I2C adapter */ i2c_dev->adap.owner = THIS_MODULE; //TODO - i2c_dev->adap.retries = 0; + i2c_dev->adap.retries = 0; -// i2c_dev->adap.retries = 3; +// i2c_dev->adap.retries = 3; - i2c_dev->adap.timeout = 5; + i2c_dev->adap.timeout = 5; - i2c_dev->master_xfer_mode = BYTE_XFER; + i2c_dev->master_xfer_mode = BYTE_XFER; /* * If "pdev->id" is negative we consider it as zero. @@ -1662,7 +1734,7 @@ static int ast_i2c_probe(struct platform_device *pdev) i2c_dev->adap.nr); i2c_dev->slave_operation = 0; - i2c_dev->blk_r_flag = 0; + i2c_dev->blk_r_flag = 0; i2c_dev->adap.algo = &i2c_ast_algorithm; ast_i2c_dev_init(i2c_dev); @@ -1674,8 +1746,11 @@ static int ast_i2c_probe(struct platform_device *pdev) goto ereqirq; } + spin_lock_init(&i2c_dev->master_lock); + #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_buff_init(i2c_dev); + spin_lock_init(&i2c_dev->slave_rx_lock); #endif i2c_dev->adap.algo_data = i2c_dev; @@ -1718,7 +1793,7 @@ static int ast_i2c_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); i2c_del_adapter(&i2c_dev->adap); - + free_irq(i2c_dev->irq, i2c_dev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1742,7 +1817,7 @@ static int ast_i2c_resume(struct platform_device *pdev) { //TODO // struct ast_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - //Should reset i2c ??? + //Should reset i2c ??? return 0; } #else diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index c8e3cf6606fe..06d9042f5721 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1064,7 +1064,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) EXPORT_SYMBOL(i2c_transfer); #ifdef CONFIG_AST_I2C_SLAVE_RDWR -int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs) +int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { unsigned long orig_jiffies; int ret, try; @@ -1075,9 +1075,18 @@ int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs) "len=%d\n", (msgs->flags & I2C_S_RD) ? 'R' : 'W', msgs->addr, msgs->len); #endif - i2c_lock_adapter(adap); + if (in_atomic() || irqs_disabled()) { + ret = mutex_trylock(&adap->bus_lock); + if (!ret) + /* I2C activity is ongoing. */ + return -EAGAIN; + } else { + mutex_lock_nested(&adap->bus_lock, adap->level); + } + ret = adap->algo->slave_xfer(adap, msgs); - i2c_unlock_adapter(adap); + + mutex_unlock(&adap->bus_lock); return ret; } else { diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 07f393ddaa42..82f2c7cb67df 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -38,7 +38,7 @@ #include <asm/uaccess.h> #ifdef CONFIG_AST_I2C_SLAVE_RDWR -#include <asm/arch/ast_i2c.h> +#include <plat/ast_i2c.h> #endif static struct i2c_driver i2cdev_driver; @@ -310,6 +310,113 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, return res; } +static noinline int i2cdev_ioctl_slave_rdrw(struct i2c_client *client, + unsigned long arg) +{ + struct i2c_rdwr_ioctl_data rdwr_arg; + struct i2c_msg *rdwr_pa; + u8 __user **data_ptrs; + int i, res; + + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data __user *)arg, + sizeof(rdwr_arg))) + return -EFAULT; + + /* Put an arbitrary limit on the number of messages that can + * be sent at once */ + if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) + return -EINVAL; + + rdwr_pa = (struct i2c_msg *) + kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), + GFP_KERNEL); + if (!rdwr_pa) + return -ENOMEM; + + if (copy_from_user(rdwr_pa, rdwr_arg.msgs, + rdwr_arg.nmsgs * sizeof(struct i2c_msg))) { + kfree(rdwr_pa); + return -EFAULT; + } + + data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); + if (data_ptrs == NULL) { + kfree(rdwr_pa); + return -ENOMEM; + } + + res = 0; + for (i = 0; i < rdwr_arg.nmsgs; i++) { + /* Limit the size of the message to a sane amount; + * and don't let length change either. */ + if (rdwr_pa[i].len > 8192) { + res = -EINVAL; + break; + } + data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; + rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); + if (rdwr_pa[i].buf == NULL) { + res = -ENOMEM; + break; + } + if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], + rdwr_pa[i].len)) { + ++i; /* Needs to be kfreed too */ + res = -EFAULT; + break; + } + + /* From Linux 3.5: */ + /* + * If the message length is received from the slave (similar + * to SMBus block read), we must ensure that the buffer will + * be large enough to cope with a message length of + * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus + * drivers allow. The first byte in the buffer must be + * pre-filled with the number of extra bytes, which must be + * at least one to hold the message length, but can be + * greater (for example to account for a checksum byte at + * the end of the message.) + */ + if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { + if (!(rdwr_pa[i].flags & I2C_M_RD) || + rdwr_pa[i].buf[0] < 1 || + rdwr_pa[i].len < rdwr_pa[i].buf[0] + + I2C_SMBUS_BLOCK_MAX) { + res = -EINVAL; + break; + } + + rdwr_pa[i].len = rdwr_pa[i].buf[0]; + } + + } + if (res < 0) { + int j; + for (j = 0; j < i; ++j) + kfree(rdwr_pa[j].buf); + kfree(data_ptrs); + kfree(rdwr_pa); + return res; + } + + res = i2c_slave_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); + while (i-- > 0) { + if (res >= 0 ) { + if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, + rdwr_pa[i].len)) + res = -EFAULT; + + rdwr_arg.msgs[i].len = rdwr_pa[i].len; + } + kfree(rdwr_pa[i].buf); + } + kfree(data_ptrs); + kfree(rdwr_pa); + return res; +} + static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, unsigned long arg) { @@ -448,8 +555,8 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_AST_I2C_SLAVE_RDWR case I2C_SLAVE_RDWR: - return i2cdev_ioctl_slave_rdrw(client->adapter, (struct i2c_msg __user *)arg); -#endif + return i2cdev_ioctl_slave_rdrw(client, arg); +#endif case I2C_SMBUS: return i2cdev_ioctl_smbus(client, arg); diff --git a/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c index fdc77fca1b5d..3a5d7969278a 100644 --- a/drivers/net/ftgmac100_26.c +++ b/drivers/net/ftgmac100_26.c @@ -1,16 +1,16 @@ /******************************************************************************** * File Name : ftgmac100_26.c -* +* * Copyright (C) 2012-2020 ASPEED Technology Inc. -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by the Free Software Foundation; -* either version 2 of the License, or (at your option) any later version. -* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by the Free Software Foundation; +* either version 2 of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ********************************************************************************/ //----------------------------------------------------------------------------- // "ASPEED MAC Driver, (Linux Kernel 2.6.15.7) 10/02/07 - by ASPEED\n" @@ -76,7 +76,7 @@ //AST2300 SDK 0.14 //19.09/13/2010 - by river@aspeed // Support Realtek RTL8201EL 10/100M PHY -//AST2400 +//AST2400 //20.06/25/2013 - by CC@aspeed // Support BCM54612E 10/100/1000M PHY //----------------------------------------------------------------------------- @@ -120,7 +120,12 @@ #err "Not define include for GMAC" #endif +#ifdef CONFIG_WEDGE100 +#define PHY_DEFAULT_ADDR 0x18 +#else +/* wedge */ #define PHY_DEFAULT_ADDR 0x1F +#endif /*------------------------------------------------------------------------ . @@ -172,7 +177,6 @@ static int ftgmac100_wait_to_send_packet(struct sk_buff * skb, struct net_device static volatile int trans_busy = 0; - void ftgmac100_phy_rw_waiting(unsigned int ioaddr) { unsigned int tmp; @@ -255,6 +259,7 @@ static void getMacHwConfig( struct net_device* dev, struct AstMacHwConfig* out ) // out->macId = dev->dev_id; //.. getMacAndPhy(dev, out); + out->phyAddr = PHY_DEFAULT_ADDR; out->miiPhyId = 0; // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock @@ -272,7 +277,7 @@ no_phy_access: out->phyAddr = 1; } #if 0 - if (out->miiPhyId == 0x0362) { + if (out->miiPhyId == 0x0362) { out->phyAddr = 1; } #endif @@ -297,6 +302,902 @@ no_phy_access: return; } +// -------------------------------------------------------------------- +// NCSI function +// -------------------------------------------------------------------- +void NCSI_Struct_Initialize(struct net_device *dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long i; + + for (i = 0; i < 6; i++) { + lp->NCSI_Request.DA[i] = 0xFF; + lp->NCSI_Respond.DA[i] = 0xFF; + lp->NCSI_Respond.SA[i] = 0xFF; + lp->NCSI_Request.SA[i] = dev->dev_addr[i]; + } + lp->NCSI_Request.EtherType = 0xF888; + lp->NCSI_Request.MC_ID = 0; + lp->NCSI_Request.Header_Revision = 0x01; + lp->NCSI_Request.Reserved_1 = 0; + lp->NCSI_Request.Reserved_2 = 0; + lp->NCSI_Request.Reserved_3 = 0; + lp->NCSI_Respond.EtherType = 0xF888; + lp->NCSI_Respond.MC_ID = 0; + lp->NCSI_Respond.Header_Revision = 0x01; + lp->NCSI_Respond.Reserved_1 = 0; + lp->NCSI_Respond.Reserved_2 = 0; + lp->NCSI_Respond.Reserved_3 = 0; + + lp->InstanceID = 0; + lp->Payload_Checksum = 0; + for (i = 0; i < 4; i++) { + lp->Payload_Pad[i] = 0; + } + for (i = 0; i < 64; i++) { + lp->Payload_Data[i] = 0; + } +} + +void Calculate_Checksum(struct net_device * dev, unsigned char *buffer_base, int Length) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned int i, CheckSum = 0; + unsigned int Data, Data1; + + for (i = 0; i < ((Length - 14) / 2); i++) { + Data = buffer_base[i * 2]; + Data1 = buffer_base[i * 2 + 1]; + CheckSum += ((Data << 8) + Data1); + } + lp->Payload_Checksum = (~(CheckSum) + 1); //2's complement +//Inverse for insert into buffer + Data = (lp->Payload_Checksum & 0xFF000000) >> 24; + Data1 = (lp->Payload_Checksum & 0x000000FF) << 24; + lp->Payload_Checksum = (lp->Payload_Checksum & 0x00FFFF00) + Data + Data1; + Data = (lp->Payload_Checksum & 0x00FF0000) >> 8; + Data1 = (lp->Payload_Checksum & 0x0000FF00) << 8; + lp->Payload_Checksum = (lp->Payload_Checksum & 0xFF0000FF) + Data + Data1; +} + +void copy_data (struct net_device * dev, struct sk_buff * skb, int Length) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + + memcpy ((unsigned char *)(skb->data + 30), &lp->Payload_Data, Length); + Calculate_Checksum(dev, skb->data + 14, 30 + Length); + memcpy ((unsigned char *)(skb->data + 30 + Length), &lp->Payload_Checksum, 4); +} + +void NCSI_Rx (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long status, length, i = 0; + volatile RX_DESC *cur_desc; + +ncsi_rx: + i = 0; + cur_desc = &lp->rx_descs[lp->rx_idx]; + do { + status = cur_desc->RXPKT_RDY; + i++; + } while (!(((status & RX_OWNBY_SOFTWARE) != 0) || (i >= NCSI_LOOP))); + + if (i < NCSI_LOOP) { + if (cur_desc->LRS) { + length = cur_desc->VDBC; + unsigned char *tbuf = (unsigned char *)phys_to_virt(cur_desc->RXBUF_BADR); + if (length <= 128 && tbuf[12] == 0x88 && tbuf[13] == 0xF8) { + memcpy (&lp->NCSI_Respond, (unsigned char *)phys_to_virt(cur_desc->RXBUF_BADR), length); + } else { + printk("NCSI_RX: Skip len: %d, proto: %x:%x\n", length, tbuf[12], tbuf[13]); + lp->rx_descs[lp->rx_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100; + lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM; + goto ncsi_rx; + } + + } + lp->rx_descs[lp->rx_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100; + lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM; + } else { + printk("NCSI_Rx: Failed\n"); + } +} + +void DeSelect_Package (struct net_device * dev, int Package_ID) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = DESELECT_PACKAGE; + Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +int Select_Package (struct net_device * dev, int Package_ID) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID, Found = 0; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = SELECT_PACKAGE; + Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (4 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 4; + memset ((void *)lp->Payload_Data, 0, 4); + lp->Payload_Data[3] = 1; //Arbitration Disable + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + Found = 0; + lp->InstanceID--; + } + else { + lp->Retry = 0; + Found = 1; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; + + return Found; +} + + +void DeSelect_Active_Package (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = DESELECT_PACKAGE; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + + +int Select_Active_Package (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID, Found = 0; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = SELECT_PACKAGE; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (4 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 4; + memset ((void *)lp->Payload_Data, 0, 4); + lp->Payload_Data[3] = 1; //Arbitration Disable + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + Found = 0; + } + else { + lp->Retry = 0; + Found = 1; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; + + return Found; +} + +int Clear_Initial_State (struct net_device * dev, int Channel_ID) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID, Found = 0; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = CLEAR_INITIAL_STATE; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + Channel_ID; //Internal Channel ID = 0 + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (CLEAR_INITIAL_STATE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + Found = 0; + } + else { + lp->Retry = 0; + Found = 1; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; + + return Found; +} + +void Get_Version_ID (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = GET_VERSION_ID; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_VERSION_ID | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Get_Capabilities (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = GET_CAPABILITIES; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_CAPABILITIES | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + lp->NCSI_Cap.Capabilities_Flags = lp->NCSI_Respond.Payload_Data[0]; + lp->NCSI_Cap.Broadcast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[1]; + lp->NCSI_Cap.Multicast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[2]; + lp->NCSI_Cap.Buffering_Capabilities = lp->NCSI_Respond.Payload_Data[3]; + lp->NCSI_Cap.AEN_Control_Support = lp->NCSI_Respond.Payload_Data[4]; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Enable_AEN (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = AEN_ENABLE; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (8 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 8; + lp->Payload_Data[3] = 0; //MC ID + lp->Payload_Data[7] = 1; //Link Status Change AEN + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (AEN_ENABLE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Get_MAC_Address (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID, i; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = 0x50; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (8 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 8; + lp->Payload_Data[0] = 0x00; + lp->Payload_Data[1] = 0x00; + lp->Payload_Data[2] = 0x81; + lp->Payload_Data[3] = 0x19; + + lp->Payload_Data[4] = 0x00; + lp->Payload_Data[5] = 0x00; + lp->Payload_Data[6] = 0x1B; + lp->Payload_Data[7] = 0x00; + + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (0x50 | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; + + // Update MAC Address +printk("NCSI: MAC "); +for (i = 0; i < 6; i++) + printk("%02X:", lp->NCSI_Respond.Payload_Data[12+i]); +printk("\n"); + memcpy(lp->NCSI_Request.SA, &lp->NCSI_Respond.Payload_Data[12], 6); + memcpy(dev->dev_addr, &lp->NCSI_Respond.Payload_Data[12], 6); + + /* Update the MAC address */ + ast_gmac_set_mac(lp, dev->dev_addr); +} + +void Set_MAC_Affinity (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID, i; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = 0x50; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (60 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + + lp->NCSI_Request.Payload_Length = 60; + memset(lp->Payload_Data, 0x00, 60); + lp->Payload_Data[0] = 0x00; + lp->Payload_Data[1] = 0x00; + lp->Payload_Data[2] = 0x81; + lp->Payload_Data[3] = 0x19; + + lp->Payload_Data[4] = 0x00; + lp->Payload_Data[5] = 0x01; + lp->Payload_Data[6] = 0x07; + lp->Payload_Data[7] = 0x00; + + for (i = 0; i < 6; i++) { + lp->Payload_Data[8+i] = lp->NCSI_Request.SA[i]; + } + + lp->Payload_Data[14] = 0x09; + + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (0x50 | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Enable_Set_MAC_Address (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID, i; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = SET_MAC_ADDRESS; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (8 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 8; + for (i = 0; i < 6; i++) { + lp->Payload_Data[i] = lp->NCSI_Request.SA[i]; + } + lp->Payload_Data[6] = 1; //MAC Address Num = 1 --> address filter 1, fixed in sample code + lp->Payload_Data[7] = UNICAST + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SET_MAC_ADDRESS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Enable_Broadcast_Filter (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = ENABLE_BROADCAST_FILTERING; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (4 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 4; + memset ((void *)lp->Payload_Data, 0, 4); + lp->Payload_Data[3] = 0x1; //ARP, DHCP, NetBIOS + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_BROADCAST_FILTERING | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Disable_VLAN (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = DISABLE_VLAN; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_VLAN | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Get_Parameters (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = GET_PARAMETERS; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_PARAMETERS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { +// printk ("Retry: Command = %x, Response_Code = %x, Resonpd.Command = %x, IID = %x, lp->InstanceID = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code, lp->NCSI_Respond.Command, lp->NCSI_Respond.IID, lp->InstanceID); + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + lp->NCSI_Cap.Capabilities_Flags = lp->NCSI_Respond.Payload_Data[0]; + lp->NCSI_Cap.Broadcast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[1]; + lp->NCSI_Cap.Multicast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[2]; + lp->NCSI_Cap.Buffering_Capabilities = lp->NCSI_Respond.Payload_Data[3]; + lp->NCSI_Cap.AEN_Control_Support = lp->NCSI_Respond.Payload_Data[4]; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Enable_Network_TX (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = ENABLE_CHANNEL_NETWORK_TX; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_CHANNEL_NETWORK_TX | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Disable_Network_TX (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = DISABLE_CHANNEL_NETWORK_TX; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + (lp->NCSI_Request.Payload_Length % 4) + 8; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_CHANNEL_NETWORK_TX | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Enable_Channel (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = ENABLE_CHANNEL; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_CHANNEL | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +void Disable_Channel (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = DISABLE_CHANNEL; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (4 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 4; + memset ((void *)lp->Payload_Data, 0, 4); + lp->Payload_Data[3] = 0x1; //ALD + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_CHANNEL | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + +int Get_Link_Status (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = GET_LINK_STATUS; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_LINK_STATUS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; + if (lp->NCSI_Respond.Payload_Data[3] & 0x40) { + return (lp->NCSI_Respond.Payload_Data[3] & 0x01); //Link Up or Not + } + else { + return 0; //Auto Negotiate did not finish + } +} + +void Set_Link (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = SET_LINK; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = (8 << 8); + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + lp->NCSI_Request.Payload_Length = 8; + memset ((void *)lp->Payload_Data, 0, 8); + lp->Payload_Data[2] = 0x02; //full duplex + lp->Payload_Data[3] = 0x04; //100M, auto-disable + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SET_LINK | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} static void ftgmac100_reset( struct net_device* dev ) { @@ -308,64 +1209,71 @@ static void ftgmac100_reset( struct net_device* dev ) PRINTK("%s:ftgmac100_reset, phyAddr=0x%x, miiPhyId=0x%04x_%04x\n", dev->name, ids->phyAddr, (ids->miiPhyId >> 16), (ids->miiPhyId & 0xffff)); - if (ids->miiPhyId < 1) - return; // Cannot access MAC registers - - // Check the link speed and duplex. - // They are not valid until auto-neg is resolved, which is reg.1 bit[5], - // or the link is up, which is reg.1 bit[2]. - - if (ids->phyAddr < 0xff) - tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1); - else tmp = 0; - - if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) { - // No PHY chip, or link has not negotiated. - speed = PHY_SPEED_100M; - duplex = 1; - netif_carrier_off(dev); - } - else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) { - tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00); - duplex = (tmp & 0x0100) ? 1 : 0; - speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M; - } - else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || - ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { - // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}. - tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11); - duplex = (tmp & PHY_DUPLEX_mask)>>13; - speed = (tmp & PHY_SPEED_mask)>>14; - netif_carrier_on(dev); - } - else if (priv->ids.miiPhyId == PHYID_BCM54612E - || priv->ids.miiPhyId == PHYID_BCM54616S) { - // Get link status - // First Switch shadow register selector - ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); - tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C); - if ( (tmp & 0x0080) == 0x0080 ) - duplex = 0; - else - duplex = 1; - - switch(tmp & 0x0018) { - case 0x0000: - speed = PHY_SPEED_1G; break; - case 0x0008: - speed = PHY_SPEED_100M; break; - case 0x0010: - speed = PHY_SPEED_10M; break; - default: - speed = PHY_SPEED_100M; - } + if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) { + ids->miiPhyId = 0xFFFF; + // NCSI mode always is 100M and full duplex + duplex = 1; + speed = PHY_SPEED_100M; + } else { + if (ids->miiPhyId < 1) + return; // Cannot access MAC registers + + // Check the link speed and duplex. + // They are not valid until auto-neg is resolved, which is reg.1 bit[5], + // or the link is up, which is reg.1 bit[2]. + + if (ids->phyAddr < 0xff) + tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1); + else tmp = 0; + + if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) { + // No PHY chip, or link has not negotiated. + speed = PHY_SPEED_100M; + duplex = 1; + netif_carrier_off(dev); } - else { - // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}. - tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18); - duplex = (tmp & 0x0001); - speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M; - } + else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) { + tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00); + duplex = (tmp & 0x0100) ? 1 : 0; + speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M; + } + else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || + ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { + // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}. + tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11); + duplex = (tmp & PHY_DUPLEX_mask)>>13; + speed = (tmp & PHY_SPEED_mask)>>14; + netif_carrier_on(dev); + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E + || priv->ids.miiPhyId == PHYID_BCM54616S) { + // Get link status + // First Switch shadow register selector + ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); + tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C); + if ( (tmp & 0x0080) == 0x0080 ) + duplex = 0; + else + duplex = 1; + + switch(tmp & 0x0018) { + case 0x0000: + speed = PHY_SPEED_1G; break; + case 0x0008: + speed = PHY_SPEED_100M; break; + case 0x0010: + speed = PHY_SPEED_10M; break; + default: + speed = PHY_SPEED_100M; + } + } + else { + // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}. + tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18); + duplex = (tmp & 0x0001); + speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M; + } + }// NCSI_Check if (speed == PHY_SPEED_1G) { // Set SPEED_100_bit too, for consistency. @@ -385,9 +1293,9 @@ static void ftgmac100_reset( struct net_device* dev ) } if (duplex) priv->maccr_val |= FULLDUP_bit; - else + else priv->maccr_val &= ~FULLDUP_bit; - + outl( SW_RST_bit, dev->base_addr + MACCR_REG ); #ifdef not_complete_yet @@ -419,6 +1327,7 @@ static void ftgmac100_enable( struct net_device *dev ) unsigned int rfifo_rsize; //Richard unsigned int tfifo_rsize; //Richard unsigned int rxbuf_size; + unsigned long Package_Found = 0, Channel_Found = 0, Re_Send = 0, Link_Status; rxbuf_size = RX_BUF_SIZE & 0x3fff; outl( rxbuf_size , dev->base_addr + RBSR_REG); //for NC Body @@ -475,7 +1384,7 @@ static void ftgmac100_enable( struct net_device *dev ) /// enable trans/recv,... outl(priv->maccr_val, dev->base_addr + MACCR_REG ); -#if 0 + //NCSI Start //DeSelect Package/ Select Package if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) { @@ -491,16 +1400,18 @@ static void ftgmac100_enable( struct net_device *dev ) } if (Package_Found != 0) { //Initiali State - for (i = 0; i < 2; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels - Channel_Found = Clear_Initial_State(dev, i); + for (i = 0; i < 1; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels + //Channel_Found = Clear_Initial_State(dev, i); + Channel_Found = 1; if (Channel_Found == 1) { priv->NCSI_Cap.Channel_ID = i; printk ("Found NCSI Network Controller at (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID); + Get_MAC_Address(dev); + Set_MAC_Affinity(dev); + Clear_Initial_State(dev, i); //Get Version and Capabilities Get_Version_ID(dev); Get_Capabilities(dev); -//Configuration - Select_Active_Package(dev); //Set MAC Address Enable_Set_MAC_Address(dev); //Enable Broadcast Filter @@ -508,16 +1419,18 @@ static void ftgmac100_enable( struct net_device *dev ) //Disable VLAN Disable_VLAN(dev); //Enable AEN - Enable_AEN(dev); + //Enable_AEN(dev); //Get Parameters Get_Parameters(dev); -//Enable TX +//Enable TX Enable_Network_TX(dev); //Enable Channel Enable_Channel(dev); //Get Link Status Re_Get_Link_Status: - Link_Status = Get_Link_Status(dev); + //TODO: Workaround for CX4 Link status issue + //Link_Status = Get_Link_Status(dev); + Link_Status = LINK_UP; if (Link_Status == LINK_UP) { printk ("Using NCSI Network Controller (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID); netif_carrier_on(dev); @@ -528,7 +1441,7 @@ Re_Get_Link_Status: netif_carrier_off(dev); goto Re_Get_Link_Status; } -//Disable TX +//Disable TX Disable_Network_TX(dev); //Disable Channel // Disable_Channel(dev); @@ -537,9 +1450,19 @@ Re_Get_Link_Status: } } } + // Enable Interrupts + outl( + AHB_ERR_bit | + TPKT_LOST_bit | + TPKT2E_bit | + RXBUF_UNAVA_bit | + RPKT2B_bit + ,dev->base_addr + IER_REG + ); + + return; } /* now, enable interrupts */ -#endif if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { outl( @@ -564,7 +1487,7 @@ Re_Get_Link_Status: ); } else if (priv->ids.miiPhyId == PHYID_BCM54612E - || priv->ids.miiPhyId == PHYID_BCM54616S) { + || priv->ids.miiPhyId == PHYID_BCM54616S) { outl( // no link PHY link status pin PHYSTS_CHG_bit | AHB_ERR_bit | @@ -583,7 +1506,7 @@ Re_Get_Link_Status: RXBUF_UNAVA_bit | RPKT2B_bit ,dev->base_addr + IER_REG - ); + ); } } @@ -619,7 +1542,7 @@ static void aspeed_mac_timer(unsigned long data) speed = (tmp & PHY_SPEED_mask)>>14; } else if (priv->ids.miiPhyId == PHYID_BCM54612E - || priv->ids.miiPhyId == PHYID_BCM54616S) { + || priv->ids.miiPhyId == PHYID_BCM54616S) { // Get link status // First Switch shadow register selector ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); @@ -628,23 +1551,23 @@ static void aspeed_mac_timer(unsigned long data) duplex = 0; else duplex = 1; - + switch(tmp & 0x0018) { case 0x0000: - speed = PHY_SPEED_1G; - + speed = PHY_SPEED_1G; + break; - case 0x0008: - speed = PHY_SPEED_100M; - + case 0x0008: + speed = PHY_SPEED_100M; + break; - case 0x0010: - speed = PHY_SPEED_10M; - + case 0x0010: + speed = PHY_SPEED_10M; + break; default: speed = PHY_SPEED_100M; - } + } } else { duplex = 1; speed = PHY_SPEED_100M; @@ -730,27 +1653,26 @@ static int ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct net_devic PRINTK3("%s:ftgmac100_wait_to_send_packet, skb=%x\n", dev->name, skb); cur_desc = &priv->tx_descs[priv->tx_idx]; -#ifdef not_complete_yet - if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor +#ifdef not_complete_yet + if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor { DO_PRINT("no empty transmit descriptor\n"); DO_PRINT("jiffies = %d\n", jiffies); priv->stats.tx_dropped++; - netif_stop_queue(dev); /// waiting to do: + netif_stop_queue(dev); /// waiting to do: spin_unlock_irqrestore(&priv->tx_lock, flags); return 1; } #endif /* end_of_not */ - if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor + if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor { DO_PRINT("no empty TX descriptor:0x%x:0x%x\n", (unsigned int)cur_desc,((unsigned int *)cur_desc)[0]); priv->stats.tx_dropped++; - netif_stop_queue(dev); /// waiting to do: + netif_stop_queue(dev); /// waiting to do: spin_unlock_irqrestore(&priv->tx_lock, flags); - return 1; } priv->tx_skbuff[priv->tx_idx] = skb; @@ -803,18 +1725,18 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) int i; struct sk_buff *skb; - priv->rx_descs = dma_alloc_coherent(priv->dev, - sizeof(RX_DESC)*RXDES_NUM, + priv->rx_descs = dma_alloc_coherent(priv->dev, + sizeof(RX_DESC)*RXDES_NUM, &priv->rx_descs_dma, GFP_KERNEL); if(!priv->rx_descs) return -ENOMEM; - + memset(priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM); priv->rx_descs[RXDES_NUM-1].EDORR = 1; for (i=0; i<RXDES_NUM; i++) { - dma_addr_t mapping; + dma_addr_t mapping; skb = dev_alloc_skb(RX_BUF_SIZE + NET_IP_ALIGN); skb_reserve(skb, NET_IP_ALIGN); @@ -829,8 +1751,8 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) priv->rx_descs[i].VIR_RXBUF_BADR = skb->data; } - priv->tx_descs = dma_alloc_coherent(priv->dev, - sizeof(TX_DESC)*TXDES_NUM, + priv->tx_descs = dma_alloc_coherent(priv->dev, + sizeof(TX_DESC)*TXDES_NUM, &priv->tx_descs_dma ,GFP_KERNEL); if(!priv->tx_descs) @@ -838,7 +1760,7 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) memset((void*)priv->tx_descs, 0, sizeof(TX_DESC)*TXDES_NUM); priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor - + } #if FTMAC100_DEBUG > 2 @@ -918,20 +1840,14 @@ static void ftgmac100_phy_configure(struct net_device* dev) } break; case PHYID_VENDOR_BROADCOM: - switch (priv->ids.miiPhyId) { - case PHYID_BCM54612E: - case PHYID_BCM54616S: - ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable - ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew - break; - case PHYID_BCM5221A4: - default: - tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b); - tmp |= 0x0004; - ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp); - break; - } - break; + tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b); + tmp |= 0x0004; + ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp); + break; + case PHYID_VENDOR_BCM5461X: + ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable + ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew + break; } } @@ -960,26 +1876,26 @@ static void ftgmac100_timeout (struct net_device *dev) } -static void ftgmac100_free_tx (struct net_device *dev) +static void ftgmac100_free_tx (struct net_device *dev) { struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv; - int entry = priv->old_tx % TXDES_NUM; + int entry = priv->old_tx % TXDES_NUM; unsigned long flags = 0; - + spin_lock_irqsave(&priv->tx_lock,flags); - + /* Free used tx skbuffs */ while ((priv->tx_descs[entry].TXDMA_OWN == TX_OWNBY_SOFTWARE) && (priv->tx_skbuff[entry] != NULL)) { struct sk_buff *skb; - + skb = priv->tx_skbuff[entry]; dev_kfree_skb_any (skb); priv->tx_skbuff[entry] = 0; entry = (entry + 1) % TXDES_NUM; priv->tx_free++; } - + spin_unlock_irqrestore(&priv->tx_lock, flags); priv->old_tx = entry; if ((netif_queue_stopped(dev)) && (priv->tx_free > 0)) { @@ -1295,7 +2211,7 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * DO_PRINT("PHYSTS_CHG \n"); // Is this interrupt for changes of the PHYLINK pin? // Note: PHYLINK is optional; not all boards connect it. - if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || + if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13); @@ -1312,7 +2228,7 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * tmp &= 0x000e; } else if (priv->ids.miiPhyId == PHYID_BCM54612E - || priv->ids.miiPhyId == PHYID_BCM54616S) { + || priv->ids.miiPhyId == PHYID_BCM54616S) { tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1A); PRINTK("%s: PHY interrupt status, read_phy_reg(0x1A) = 0x%04x\n", dev->name, tmp); @@ -1403,10 +2319,10 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * . Get the current statistics. . This may be called with the card open or closed. .-------------------------------------------------------------*/ -static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev) +static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev) { struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv; - + return &priv->stats; } @@ -1416,7 +2332,7 @@ static struct net_device_stats* ftgmac100_query_statistics(struct net_device *de // Finds the CRC32 of a set of bytes. // Again, from Peter Cammaert's code. // -------------------------------------------------------------------- -static int crc32( char * s, int length ) +static int crc32( char * s, int length ) { /* indices */ int perByte; @@ -1446,7 +2362,7 @@ static int crc32( char * s, int length ) . packets before they take up memory. */ -static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs ) +static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs ) { struct dev_mc_list * cur_addr; int crc_val; @@ -1455,12 +2371,12 @@ static void ftgmac100_setmulticast( struct net_device *dev, int count, struct de struct AstMacHwConfig* ids = &priv->ids; unsigned long Combined_Channel_ID, i; struct sk_buff * skb; - cur_addr = addrs; + cur_addr = addrs; //TX -#if 0 +#if 1 if (priv->NCSI_support == 1) { - skb = dev_alloc_skb (TX_BUF_SIZE + 16); + skb = dev_alloc_skb (TX_BUF_SIZE + 16); priv->InstanceID++; priv->NCSI_Request.IID = priv->InstanceID; priv->NCSI_Request.Command = SET_MAC_ADDRESS; @@ -1597,7 +2513,7 @@ static int ast_gmac_stop(struct net_device *dev) priv->rx_descs = NULL; priv->rx_descs_dma = 0; priv->tx_descs = NULL; priv->tx_descs_dma = 0; priv->tx_buf = NULL; priv->tx_buf_dma = 0; - + return 0; } @@ -1651,10 +2567,10 @@ static int ftgmac100_open(struct net_device *netdev) ftgmac100_reset(netdev); ftgmac100_enable(netdev); - if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) || + if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) || ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) || (priv->ids.miiPhyId == PHYID_BCM54612E) || - (priv->ids.miiPhyId == PHYID_BCM54616S)) { + (priv->ids.miiPhyId == PHYID_BCM54616S)) { init_timer(&priv->timer); priv->timer.data = (unsigned long)netdev; @@ -1702,7 +2618,7 @@ static int __init ast_gmac_probe(struct platform_device *pdev) // SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops); - + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) netdev->netdev_ops = &ftgmac100_netdev_ops; #else @@ -1715,13 +2631,12 @@ static int __init ast_gmac_probe(struct platform_device *pdev) netdev->hard_start_xmit = ftgmac100_wait_to_send_packet; netdev->tx_timeout = ftgmac100_timeout; netdev->get_stats = ftgmac100_query_statistics; -//#ifdef HAVE_MULTICAST -#if 0 +#ifdef HAVE_MULTICAST netdev->set_multicast_list = &ftgmac100_set_multicast_list; #endif #endif - + #ifdef CONFIG_AST_NPAI // netdev->features = NETIF_F_GRO; @@ -1734,12 +2649,12 @@ static int __init ast_gmac_probe(struct platform_device *pdev) priv = netdev_priv(netdev); priv->netdev = netdev; priv->dev = &pdev->dev; - + priv->ids.macId = pdev->id; - + priv->NCSI_support = ast_eth_data->NCSI_support; - priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support; + priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support; spin_lock_init(&priv->tx_lock); #if 0 @@ -1833,7 +2748,7 @@ err_ioremap: err_req_mem: // netif_napi_del(&priv->napi); platform_set_drvdata(pdev, NULL); -err_netdev: +err_netdev: free_netdev(netdev); err_alloc_etherdev: return err; diff --git a/drivers/net/ftgmac100_26.h b/drivers/net/ftgmac100_26.h index 0d470244ca51..24931110be87 100644 --- a/drivers/net/ftgmac100_26.h +++ b/drivers/net/ftgmac100_26.h @@ -1,16 +1,16 @@ /******************************************************************************** * File Name : ftgmac100_26.h -* +* * Copyright (C) 2012-2020 ASPEED Technology Inc. -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by the Free Software Foundation; -* either version 2 of the License, or (at your option) any later version. -* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by the Free Software Foundation; +* either version 2 of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +* without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ********************************************************************************/ // -------------------------------------------------------------------- @@ -78,7 +78,7 @@ // -------------------------------------------------------------------- -// APTC_REG +// APTC_REG // -------------------------------------------------------------------- @@ -99,18 +99,18 @@ typedef struct #define PHY_READ_bit (1UL<<26) #define PHY_WRITE_bit (1UL<<27) // -------------------------------------------------------------------- -// PHYCR_REG +// PHYCR_REG // -------------------------------------------------------------------- #define PHY_AUTO_OK_bit (1UL<<5) // -------------------------------------------------------------------- -// PHY INT_STAT_REG +// PHY INT_STAT_REG // -------------------------------------------------------------------- #define PHY_SPEED_CHG_bit (1UL<<14) #define PHY_DUPLEX_CHG_bit (1UL<<13) #define PHY_LINK_CHG_bit (1UL<<10) #define PHY_AUTO_COMP_bit (1UL<<11) // -------------------------------------------------------------------- -// PHY SPE_STAT_REG +// PHY SPE_STAT_REG // -------------------------------------------------------------------- #define PHY_RESOLVED_bit (1UL<<11) #define PHY_SPEED_mask 0xC000 @@ -269,7 +269,7 @@ typedef struct { unsigned short Reserved_5; unsigned short Response_Code; unsigned short Reason_Code; - unsigned char Payload_Data[64]; + unsigned char Payload_Data[128]; } NCSI_Response_Packet; //Standard Response Code @@ -365,30 +365,30 @@ typedef struct u32 FRS:1; u32 EDORR:1; u32 RXPKT_RDY:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software - + // RXDES1 u32 VLAN_TAGC:16; u32 Reserved4:4; u32 PROTL_TYPE:2; u32 LLC_PKT:1; u32 DF:1; - u32 VLAN_AVA:1; + u32 VLAN_AVA:1; u32 TCPCS_FAIL:1; u32 UDPCS_FAIL:1; u32 IPCS_FAIL:1; u32 Reserved5:4; - + // RXDES2 u32 Reserved6:32; - + // RXDES3 u32 RXBUF_BADR; - + u32 VIR_RXBUF_BADR; // not defined, the virtual address of receive buffer is placed here - - u32 RESERVED; - u32 RESERVED1; - u32 RESERVED2; + + u32 RESERVED; + u32 RESERVED1; + u32 RESERVED2; }RX_DESC; @@ -405,7 +405,7 @@ typedef struct u32 FTS:1; u32 EDOTR:1; u32 TXDMA_OWN:1; - + // TXDES1 u32 VLAN_TAGC:16; u32 INS_VLAN:1; @@ -416,8 +416,8 @@ typedef struct u32 LLC_PKT:1; u32 Reserved6:7; u32 TX2FIC:1; - u32 TXIC:1; - + u32 TXIC:1; + // TXDES2 u32 Reserved7:32; @@ -427,8 +427,8 @@ typedef struct u32 VIR_TXBUF_BADR; // Reserve, the virtual address of transmit buffer is placed here u32 RESERVED; - u32 RESERVED1; - u32 RESERVED2; + u32 RESERVED1; + u32 RESERVED2; }TX_DESC; @@ -450,7 +450,7 @@ typedef struct // -------------------------------------------------------------------- -//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue +//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue #define RXDES_NUM 32 #define RX_BUF_SIZE 1536 @@ -464,6 +464,7 @@ typedef struct #define PHYID_REVISION_MASK 0x0000000f #define PHYID_VENDOR_MARVELL 0x01410c00 #define PHYID_VENDOR_BROADCOM 0x00406000 +#define PHYID_VENDOR_BCM5461X 0x03625c00 #define PHYID_VENDOR_REALTEK 0x001cc800 #define PHYID_BCM5221A4 0x004061e4 @@ -521,7 +522,7 @@ struct ftgmac100_priv { int tx_idx; int old_tx; struct sk_buff *tx_skbuff[TXDES_NUM]; - + int maccr_val; struct timer_list timer; u32 GigaBit_MAHT0; @@ -533,7 +534,7 @@ struct ftgmac100_priv { NCSI_Capability NCSI_Cap; unsigned int InstanceID; unsigned int Retry; - unsigned char Payload_Data[16]; + unsigned char Payload_Data[64]; unsigned char Payload_Pad[4]; unsigned long Payload_Checksum; int tx_free; @@ -575,7 +576,7 @@ struct ftgmac100_priv { #define STOP_DONE (1 << 4) - + #endif /* _SMC_91111_H_ */ diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c index 477032e986ce..de9e99517884 100755 --- a/drivers/rtc/rtc-aspeed.c +++ b/drivers/rtc/rtc-aspeed.c @@ -7,11 +7,11 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the Free Software Foundation; * either version 2 of the License, or (at your option) any later version. -* +* * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -67,8 +67,16 @@ ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct ast_rtc *ast_rtc = dev_get_drvdata(dev); pr_debug("cmd = 0x%08x, arg = 0x%08lx\n", cmd, arg); - + switch (cmd) { + case RTC_SET_TIME: + case RTC_RD_TIME: + case RTC_ALM_READ: + case RTC_ALM_SET: + { + // use rtc-dev.c fallback + return -ENOIOCTLCMD; + } case RTC_AIE_ON: /* alarm on */ { rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) | ENABLE_ALL_ALARM, RTC_CONTROL); @@ -105,7 +113,7 @@ ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) default: return -ENOTTY; } - + return 0; } @@ -122,7 +130,7 @@ ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) reg_time = rtc_read(ast_rtc->base, RTC_CNTR_STS_1); reg_date = rtc_read(ast_rtc->base, RTC_CNTR_STS_2); - + spin_unlock_irqrestore(&ast_rtc->lock, flags); rtc_tm->tm_year = GET_CENT_VAL(reg_date)*1000 | GET_YEAR_VAL(reg_date); @@ -132,7 +140,7 @@ ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_hour = GET_HOUR_VAL(reg_time); rtc_tm->tm_min = GET_MIN_VAL(reg_time); rtc_tm->tm_sec = GET_SEC_VAL(reg_time); - + pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); @@ -155,7 +163,7 @@ ast_rtc_set_time(struct device *dev, struct rtc_time *tm) /* set hours */ reg_time = SET_DAY_VAL(tm->tm_mday) | SET_HOUR_VAL(tm->tm_hour) | SET_MIN_VAL(tm->tm_min) | SET_SEC_VAL(tm->tm_sec); - + /* set century */ /* set mon */ reg_date = SET_CENT_VAL(tm->tm_year / 1000) | SET_YEAR_VAL(tm->tm_year % 1000) | SET_MON_VAL(tm->tm_mon); @@ -166,10 +174,10 @@ ast_rtc_set_time(struct device *dev, struct rtc_time *tm) rtc_write(ast_rtc->base, reg_date, RTC_CNTR_STS_2); rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) &~RTC_LOCK , RTC_CONTROL); - + spin_unlock_irqrestore(&ast_rtc->lock, flags); - return 0; + return 0; } static int ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) @@ -183,7 +191,7 @@ ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) alarm_reg = rtc_read(ast_rtc->base, RTC_ALARM); spin_unlock_irqrestore(&ast_rtc->lock, flags); -//DAY +//DAY alm_tm->tm_mday = GET_DAY_VAL(alarm_reg); //HR @@ -221,7 +229,7 @@ ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) if (tm->tm_mday <= 31 && tm->tm_mday >= 1) { reg_alarm |= SET_DAY_VAL(tm->tm_mday); } - + //HR /* set ten hours */ if (tm->tm_hour <= 23 && tm->tm_hour >= 0) { @@ -245,8 +253,8 @@ ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) spin_lock_irqsave(&ast_rtc->lock, flags); rtc_write(ast_rtc->base, reg_alarm, RTC_ALARM); - - if(alarm->enabled) + + if(alarm->enabled) rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL); else rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL); @@ -366,14 +374,14 @@ static int __init ast_rtc_probe(struct platform_device *pdev) ret = -EBUSY; goto free_rtc; } - + ast_rtc->base = ioremap(res->start, resource_size(res)); if (!ast_rtc->base) { dev_err(&pdev->dev, "cannot map SocleDev registers\n"); ret = -ENOMEM; goto release_mem; } - + pr_debug("base = 0x%p, irq = %d\n", ast_rtc->base, ast_rtc->irq); rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &ast_rtcops, THIS_MODULE); @@ -381,7 +389,7 @@ static int __init ast_rtc_probe(struct platform_device *pdev) ret = PTR_ERR(rtc_dev); goto unmap; } - + ast_rtc->res = res; ast_rtc->rtc_dev = rtc_dev; spin_lock_init(&ast_rtc->lock); @@ -406,7 +414,7 @@ static int __init ast_rtc_probe(struct platform_device *pdev) printk("no need to enable RTC \n"); spin_unlock_irq(&ast_rtc->lock); - + /* register ISR */ ret = request_irq(ast_rtc->irq, ast_rtc_interrupt, IRQF_DISABLED, dev_name(&rtc_dev->dev), ast_rtc); if (ret) { diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index a181ccf46281..f16da5982358 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -38,6 +38,7 @@ #include <linux/serial_8250.h> #include <linux/nmi.h> #include <linux/mutex.h> +#include <linux/gpio.h> #include <asm/io.h> #include <asm/irq.h> @@ -59,6 +60,8 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; static struct uart_driver serial8250_reg; +DECLARE_WAIT_QUEUE_HEAD(thre_wait); + static int serial_index(struct uart_port *port) { return (serial8250_reg.minor - 64) + port->line; @@ -1225,7 +1228,10 @@ static void autoconfig_irq(struct uart_8250_port *up) static inline void __stop_tx(struct uart_8250_port *p) { - if (p->ier & UART_IER_THRI) { + int status = serial_in(p, UART_LSR); + // only turn off THRE interrupt if THRE is *currently* asserted + // (we still want to catch it a final time after the FIFO empties) + if ((p->ier & UART_IER_THRI) && (status & UART_LSR_THRE)) { p->ier &= ~UART_IER_THRI; serial_out(p, UART_IER, p->ier); } @@ -1527,6 +1533,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) DEBUG_INTR("end.\n"); + wake_up(&thre_wait); return IRQ_RETVAL(handled); } @@ -2526,6 +2533,35 @@ serial8250_type(struct uart_port *port) return uart_config[type].name; } +static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) { + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + int ret = -ENOIOCTLCMD; + // kernel-space RS485 drain-and-switch hack + if (cmd == TIOCSERWAITTEMT) { + // wait for kernel buffers and UART FIFO to both empty + struct circ_buf *xmit = &up->port.info->xmit; + wait_event_interruptible( + thre_wait, + uart_circ_empty(xmit) && + (serial_in(up, UART_LSR) & UART_LSR_THRE)); + // spin until TEMT (transmit shift register empty) + spin_lock_irqsave(&up->port.lock, flags); + wait_for_xmitr(up, BOTH_EMPTY); + if (arg != 0) { + // turn off RS485 DE pin + gpio_set_value(arg, 0); + } + // grab any phantom char seen on RX when transceiver switches + (void) serial_inp(up, UART_RX); + // enable read + up->port.ignore_status_mask &= ~UART_LSR_DR; + spin_unlock_irqrestore(&up->port.lock, flags); + return 0; + } + return ret; +} + static struct uart_ops serial8250_pops = { .tx_empty = serial8250_tx_empty, .set_mctrl = serial8250_set_mctrl, @@ -2544,6 +2580,7 @@ static struct uart_ops serial8250_pops = { .request_port = serial8250_request_port, .config_port = serial8250_config_port, .verify_port = serial8250_verify_port, + .ioctl = serial8250_ioctl, #ifdef CONFIG_CONSOLE_POLL .poll_get_char = serial8250_get_poll_char, .poll_put_char = serial8250_put_poll_char, diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 57021458abf4..0b01ba85e92e 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -235,10 +235,17 @@ config ORION5X_WATCHDOG config AST_WATCHDOG tristate "ASPEED GUC watchdog" - depends on WATCHDOG + depends on WATCHDOG help Watchdog timer for ASPEED chips. +config AST_WATCHDOG_REARM_DUAL_BOOT + bool "Rearm dual boot watchdog" + default n + depends on AST_WATCHDOG + help + Rearm dual boot watchdog or not during boot + # ARM26 Architecture # AVR32 Architecture diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c index 9e7e84fb8740..e599a557076f 100644 --- a/drivers/watchdog/ast_wdt.c +++ b/drivers/watchdog/ast_wdt.c @@ -68,6 +68,7 @@ typedef unsigned char bool_T; #else #define WDT_BASE_VA (IO_ADDRESS(AST_WDT_BASE)) +#define WDT2_BASE_VA (IO_ADDRESS(AST_WDT_BASE + 20)) #endif #define WDT_CntSts (WDT_BASE_VA+0x00) @@ -78,6 +79,14 @@ typedef unsigned char bool_T; #define WDT_Clr (WDT_BASE_VA+0x14) #define WDT_RstWd (WDT_BASE_VA+0x18) +#define WDT2_CntSts (WDT2_BASE_VA+0x00) +#define WDT2_Reload (WDT2_BASE_VA+0x04) +#define WDT2_Restart (WDT2_BASE_VA+0x08) +#define WDT2_Ctrl (WDT2_BASE_VA+0x0C) +#define WDT2_TimeOut (WDT2_BASE_VA+0x10) +#define WDT2_Clr (WDT2_BASE_VA+0x14) +#define WDT2_RstWd (WDT2_BASE_VA+0x18) + #define WDT_CTRL_B_SECOND_BOOT (0x1 << 7) #define WDT_CTRL_B_RESET_SOC (0x00 << 5) /* yes, 0x00 */ #define WDT_CTRL_B_RESET_FULL (0x01 << 5) @@ -101,6 +110,11 @@ typedef unsigned char bool_T; #define WDT_TIMO 30 /* Default heartbeat = 30 seconds */ #define WDT_INITIAL_TIMO (8*60) /* Initial timeout, 8m */ +/* + * Dual boot watchdog is 5s shorter so that dual boot watchdog + * will kick in first. + */ +#define WDT_DUAL_BOOT_TIMO (WDT_INITIAL_TIMO - 5) #define WDT_TIMO2TICKS(t) (TICKS_PER_uSEC * 1000000 * (t)) static int heartbeat = WDT_TIMO; @@ -233,6 +247,14 @@ bool_T wdt_is_enabled(void) return reg & WDT_CTRL_B_ENABLE; } +#ifdef CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT +void wdt_dual_boot_restart(unsigned int timeo) +{ + AST_WRITE_REG(WDT2_Reload, WDT_TIMO2TICKS(timeo)); + AST_WRITE_REG(WDT2_Restart, 0x4755); /* reload! */ + printk(KERN_INFO "Re-arm the dual boot watchdog for %u seconds\n", timeo); +} +#endif void wdt_restart_new(unsigned int nPeriod, int sourceClk, bool_T bResetOut, bool_T bIntrSys, bool_T bClrAfter, bool_T bResetARMOnly) @@ -542,6 +564,11 @@ static int ast_wdt_probe(struct platform_device *pdev) return ret; } +#ifdef CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT + /* re-arm dual boot watchdog */ + wdt_dual_boot_restart(WDT_DUAL_BOOT_TIMO); +#endif + /* interrupt the system while WDT timeout */ wdt_restart_new(WDT_TIMO2TICKS(WDT_INITIAL_TIMO), WDT_CLK_SRC_EXT, /* No Ext, No intr, Self clear, Full chip reset */ |