diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/rk27xx/i2c-rk27xx.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/firmware/target/arm/rk27xx/i2c-rk27xx.c b/firmware/target/arm/rk27xx/i2c-rk27xx.c index 34a6f49a32..62f6d01c85 100644 --- a/firmware/target/arm/rk27xx/i2c-rk27xx.c +++ b/firmware/target/arm/rk27xx/i2c-rk27xx.c | |||
@@ -40,28 +40,28 @@ static struct mutex i2c_mtx; | |||
40 | 40 | ||
41 | static bool i2c_write_byte(uint8_t data, bool start) | 41 | static bool i2c_write_byte(uint8_t data, bool start) |
42 | { | 42 | { |
43 | long timeout = current_tick + HZ / 50; | 43 | long timeout = current_tick + 50; |
44 | 44 | ||
45 | /* START */ | 45 | /* START */ |
46 | I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */ | 46 | I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */ |
47 | I2C_MTXR = data; | 47 | I2C_MTXR = data; |
48 | 48 | ||
49 | if (start) | 49 | if (start) |
50 | I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */ | 50 | I2C_LCMR = (1<<2) | (1<<0); /* resume op, start bit */ |
51 | else | 51 | else |
52 | I2C_LCMR = (1<<2); /* resume op */ | 52 | I2C_LCMR = (1<<2); /* resume op */ |
53 | 53 | ||
54 | I2C_CONR &= ~(1<<4); /* ACK enable */ | 54 | I2C_CONR &= ~(1<<4); /* ACK enable */ |
55 | 55 | ||
56 | /* wait for ACK from slave */ | 56 | /* wait for ACK from slave */ |
57 | while ( !(I2C_ISR & (1<<0)) || (I2C_LSR & (1<<0)) ) | 57 | while ( (!(I2C_ISR & (1<<0))) || (I2C_LSR & (1<<1)) ) |
58 | if (TIME_AFTER(current_tick, timeout)) | 58 | if (TIME_AFTER(current_tick, timeout)) |
59 | return false; | 59 | return false; |
60 | 60 | ||
61 | /* clear status bit */ | 61 | /* clear status bit */ |
62 | I2C_ISR &= ~(1<<0); | 62 | I2C_ISR &= ~(1<<0); |
63 | 63 | ||
64 | return true; | 64 | return true; |
65 | } | 65 | } |
66 | 66 | ||
67 | static bool i2c_read_byte(unsigned char *data) | 67 | static bool i2c_read_byte(unsigned char *data) |
@@ -70,7 +70,7 @@ static bool i2c_read_byte(unsigned char *data) | |||
70 | 70 | ||
71 | I2C_LCMR = (1<<2); /* resume op */ | 71 | I2C_LCMR = (1<<2); /* resume op */ |
72 | 72 | ||
73 | while (I2C_ISR & (1<<1)) | 73 | while (!(I2C_ISR & (1<<1))) |
74 | if (TIME_AFTER(current_tick, timeout)) | 74 | if (TIME_AFTER(current_tick, timeout)) |
75 | return false; | 75 | return false; |
76 | 76 | ||
@@ -97,7 +97,7 @@ static bool i2c_stop(void) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | /* route i2c bus to internal codec or external bus | 99 | /* route i2c bus to internal codec or external bus |
100 | * internal codec has 0x27 i2c slave address so | 100 | * internal codec has 0x4e i2c slave address so |
101 | * access to this address is routed to internal bus. | 101 | * access to this address is routed to internal bus. |
102 | * All other addresses are routed to external pads | 102 | * All other addresses are routed to external pads |
103 | */ | 103 | */ |
@@ -105,15 +105,15 @@ static void i2c_iomux(unsigned char slave) | |||
105 | { | 105 | { |
106 | unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14); | 106 | unsigned long muxa = SCU_IOMUXA_CON & ~(0x1f<<14); |
107 | 107 | ||
108 | if (slave == (0x27<<1)) | 108 | if ((slave & 0xfe) == (0x27<<1)) |
109 | { | 109 | { |
110 | /* internal codec */ | 110 | /* internal codec */ |
111 | SCU_IOMUXA_CON = muxa | (1<<16) | (1<<14); | 111 | SCU_IOMUXA_CON = (muxa | (1<<16) | (1<<14)); |
112 | } | 112 | } |
113 | else | 113 | else |
114 | { | 114 | { |
115 | /* external I2C bus */ | 115 | /* external I2C bus */ |
116 | SCU_IOMUXA_CON = muxa | (1<<18); | 116 | SCU_IOMUXA_CON = (muxa | (1<<18)); |
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
@@ -131,7 +131,13 @@ void i2c_init(void) | |||
131 | * APBfreq = 50Mhz | 131 | * APBfreq = 50Mhz |
132 | * SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1)) | 132 | * SCLfreq = (APBfreq/5*(I2CCDVR[5:3] + 1) * 2^((I2CCDVR[2:0] + 1)) |
133 | */ | 133 | */ |
134 | I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | 1<<0; | 134 | |
135 | /* we are driving this slightly above specs | ||
136 | * (6<<3) | (1<<0) 416kHz | ||
137 | * (7<<3) | (1<<0) 357kHz | ||
138 | * (6<<3) | (2<<0) 208kHz | ||
139 | */ | ||
140 | I2C_OPR = (I2C_OPR & ~(0x3F)) | (6<<3) | (1<<0); | ||
135 | 141 | ||
136 | I2C_IER = 0x00; | 142 | I2C_IER = 0x00; |
137 | 143 | ||
@@ -145,6 +151,10 @@ int i2c_write(unsigned char slave, int address, int len, | |||
145 | 151 | ||
146 | i2c_iomux(slave); | 152 | i2c_iomux(slave); |
147 | 153 | ||
154 | /* clear all flags */ | ||
155 | I2C_ISR = 0x00 | ||
156 | I2C_IER = 0x00; | ||
157 | |||
148 | /* START */ | 158 | /* START */ |
149 | if (! i2c_write_byte(slave & ~1, true)) | 159 | if (! i2c_write_byte(slave & ~1, true)) |
150 | { | 160 | { |
@@ -188,6 +198,10 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data) | |||
188 | 198 | ||
189 | i2c_iomux(slave); | 199 | i2c_iomux(slave); |
190 | 200 | ||
201 | /* clear all flags */ | ||
202 | I2C_ISR = 0x00; | ||
203 | I2C_IER = 0x00; | ||
204 | |||
191 | if (address >= 0) | 205 | if (address >= 0) |
192 | { | 206 | { |
193 | /* START */ | 207 | /* START */ |