summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/rk27xx/i2c-rk27xx.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/firmware/target/arm/rk27xx/i2c-rk27xx.c b/firmware/target/arm/rk27xx/i2c-rk27xx.c
index f9f20930cc..cc2319ab45 100644
--- a/firmware/target/arm/rk27xx/i2c-rk27xx.c
+++ b/firmware/target/arm/rk27xx/i2c-rk27xx.c
@@ -24,8 +24,6 @@
24#include "kernel.h" 24#include "kernel.h"
25#include "i2c-rk27xx.h" 25#include "i2c-rk27xx.h"
26 26
27/* NOT TESTED YET */
28
29/* Driver for the rockchip rk27xx built-in I2C controller in master mode 27/* Driver for the rockchip rk27xx built-in I2C controller in master mode
30 28
31 Both the i2c_read and i2c_write function take the following arguments: 29 Both the i2c_read and i2c_write function take the following arguments:
@@ -38,12 +36,26 @@
38 36
39static struct mutex i2c_mtx; 37static struct mutex i2c_mtx;
40 38
39static bool i2c_stop(void)
40{
41 long timeout = current_tick + HZ/50;
42
43 I2C_CONR |= (1<<4); /* NACK */
44 I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
45
46 while (I2C_LCMR & (1<<1))
47 if (TIME_AFTER(current_tick, timeout))
48 return false;
49
50 return true;
51}
52
41static bool i2c_write_byte(uint8_t data, bool start) 53static bool i2c_write_byte(uint8_t data, bool start)
42{ 54{
43 long timeout = current_tick + HZ/50; 55 long timeout = current_tick + HZ/50;
56 unsigned int isr_status;
44 57
45 /* START */ 58 I2C_CONR = (1<<3) | (1<<2); /* master port enable, MTX mode, ACK enable */
46 I2C_CONR |= (1<<3) | (1<<2); /* master port enable, transmit bit */
47 I2C_MTXR = data; 59 I2C_MTXR = data;
48 60
49 if (start) 61 if (start)
@@ -51,13 +63,23 @@ static bool i2c_write_byte(uint8_t data, bool start)
51 else 63 else
52 I2C_LCMR = (1<<2); /* resume op */ 64 I2C_LCMR = (1<<2); /* resume op */
53 65
54 I2C_CONR &= ~(1<<4); /* ACK enable */
55
56 /* wait for ACK from slave */ 66 /* wait for ACK from slave */
57 while ( (!(I2C_ISR & (1<<0))) || (I2C_LSR & (1<<1)) ) 67 do
68 {
69 isr_status = I2C_ISR;
70
71 if (isr_status & (1<<7))
72 {
73 i2c_stop();
74 I2C_ISR = 0;
75 return false;
76 }
77
58 if (TIME_AFTER(current_tick, timeout)) 78 if (TIME_AFTER(current_tick, timeout))
59 return false; 79 return false;
60 80
81 } while ((isr_status & (1<<0)) == 0);
82
61 /* clear status bit */ 83 /* clear status bit */
62 I2C_ISR &= ~(1<<0); 84 I2C_ISR &= ~(1<<0);
63 85
@@ -82,19 +104,7 @@ static bool i2c_read_byte(unsigned char *data)
82 return true; 104 return true;
83} 105}
84 106
85static bool i2c_stop(void)
86{
87 long timeout = current_tick + HZ/50;
88
89 I2C_CONR &= ~(1<<4);
90 I2C_LCMR |= (1<<2) | (1<<1); /* resume op, stop */
91 107
92 while (I2C_LCMR & (1<<1))
93 if (TIME_AFTER(current_tick, timeout))
94 return false;
95
96 return true;
97}
98 108
99/* route i2c bus to internal codec or external bus 109/* route i2c bus to internal codec or external bus
100 * internal codec has 0x4e i2c slave address so 110 * internal codec has 0x4e i2c slave address so
@@ -202,6 +212,7 @@ int i2c_write(unsigned char slave, int address, int len,
202end: 212end:
203 mutex_unlock(&i2c_mtx); 213 mutex_unlock(&i2c_mtx);
204 SCU_CLKCFG |= CLKCFG_I2C; 214 SCU_CLKCFG |= CLKCFG_I2C;
215
205 return ret; 216 return ret;
206} 217}
207 218
@@ -244,7 +255,7 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
244 goto end; 255 goto end;
245 } 256 }
246 257
247 I2C_CONR &= ~(1<<3); /* clear transmit bit (switch to receive mode) */ 258 I2C_CONR = (1<<2); /* master port enable, MRX mode, ACK enable */
248 259
249 while (len) 260 while (len)
250 { 261 {
@@ -272,5 +283,6 @@ int i2c_read(unsigned char slave, int address, int len, unsigned char *data)
272end: 283end:
273 mutex_unlock(&i2c_mtx); 284 mutex_unlock(&i2c_mtx);
274 SCU_CLKCFG |= CLKCFG_I2C; 285 SCU_CLKCFG |= CLKCFG_I2C;
286
275 return ret; 287 return ret;
276} 288}