summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/ast_adc.c233
-rw-r--r--drivers/i2c/busses/i2c-ast.c689
-rw-r--r--drivers/i2c/i2c-core.c15
-rw-r--r--drivers/i2c/i2c-dev.c113
-rw-r--r--drivers/net/ftgmac100_26.c1211
-rw-r--r--drivers/net/ftgmac100_26.h67
-rwxr-xr-xdrivers/rtc/rtc-aspeed.c42
-rw-r--r--drivers/serial/8250.c39
-rw-r--r--drivers/watchdog/Kconfig9
-rw-r--r--drivers/watchdog/ast_wdt.c27
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 */