summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/rk27xx/i2c-rk27xx.c58
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
41static bool i2c_write_byte(uint8_t data, bool start) 41static 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
67static bool i2c_read_byte(unsigned char *data) 67static 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 */