diff options
author | Marcin Bukat <marcin.bukat@gmail.com> | 2013-04-09 09:29:50 +0200 |
---|---|---|
committer | Marcin Bukat <marcin.bukat@gmail.com> | 2013-04-09 09:31:40 +0200 |
commit | e6c0bd035046e6b97f408fcff14879a2fba6c9e6 (patch) | |
tree | 534e838013410da96c6462cfede911571924a5e2 | |
parent | dcba74155e96ef8e6da757cba239241469b5859a (diff) | |
download | rockbox-e6c0bd035046e6b97f408fcff14879a2fba6c9e6.tar.gz rockbox-e6c0bd035046e6b97f408fcff14879a2fba6c9e6.zip |
rk27xx: fix i2c driver
Change-Id: I205cc92f452c1990c64da7e91b2baf00b920c922
-rw-r--r-- | firmware/target/arm/rk27xx/i2c-rk27xx.c | 52 |
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 | ||
39 | static struct mutex i2c_mtx; | 37 | static struct mutex i2c_mtx; |
40 | 38 | ||
39 | static 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 | |||
41 | static bool i2c_write_byte(uint8_t data, bool start) | 53 | static 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 | ||
85 | static 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, | |||
202 | end: | 212 | end: |
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) | |||
272 | end: | 283 | end: |
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 | } |