aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-bfin-twi.c37
1 files changed, 13 insertions, 24 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index 0279a7a6b86..ff61c4b2209 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -81,14 +81,15 @@ static const u16 pin_req[2][3] = {
81 {P_TWI1_SCL, P_TWI1_SDA, 0}, 81 {P_TWI1_SCL, P_TWI1_SDA, 0},
82}; 82};
83 83
84static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) 84static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface,
85 unsigned short twi_int_status)
85{ 86{
86 unsigned short twi_int_status = read_INT_STAT(iface);
87 unsigned short mast_stat = read_MASTER_STAT(iface); 87 unsigned short mast_stat = read_MASTER_STAT(iface);
88 88
89 if (twi_int_status & XMTSERV) { 89 if (twi_int_status & XMTSERV) {
90 /* Transmit next data */ 90 /* Transmit next data */
91 if (iface->writeNum > 0) { 91 if (iface->writeNum > 0) {
92 SSYNC();
92 write_XMT_DATA8(iface, *(iface->transPtr++)); 93 write_XMT_DATA8(iface, *(iface->transPtr++));
93 iface->writeNum--; 94 iface->writeNum--;
94 } 95 }
@@ -110,10 +111,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
110 write_MASTER_CTL(iface, 111 write_MASTER_CTL(iface,
111 (read_MASTER_CTL(iface) | RSTART) & ~MDIR); 112 (read_MASTER_CTL(iface) | RSTART) & ~MDIR);
112 } 113 }
113 SSYNC();
114 /* Clear status */
115 write_INT_STAT(iface, XMTSERV);
116 SSYNC();
117 } 114 }
118 if (twi_int_status & RCVSERV) { 115 if (twi_int_status & RCVSERV) {
119 if (iface->readNum > 0) { 116 if (iface->readNum > 0) {
@@ -135,7 +132,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
135 } else if (iface->manual_stop) { 132 } else if (iface->manual_stop) {
136 write_MASTER_CTL(iface, 133 write_MASTER_CTL(iface,
137 read_MASTER_CTL(iface) | STOP); 134 read_MASTER_CTL(iface) | STOP);
138 SSYNC();
139 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && 135 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
140 iface->cur_msg + 1 < iface->msg_num) { 136 iface->cur_msg + 1 < iface->msg_num) {
141 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) 137 if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD)
@@ -144,18 +140,12 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
144 else 140 else
145 write_MASTER_CTL(iface, 141 write_MASTER_CTL(iface,
146 (read_MASTER_CTL(iface) | RSTART) & ~MDIR); 142 (read_MASTER_CTL(iface) | RSTART) & ~MDIR);
147 SSYNC();
148 } 143 }
149 /* Clear interrupt source */
150 write_INT_STAT(iface, RCVSERV);
151 SSYNC();
152 } 144 }
153 if (twi_int_status & MERR) { 145 if (twi_int_status & MERR) {
154 write_INT_STAT(iface, MERR);
155 write_INT_MASK(iface, 0); 146 write_INT_MASK(iface, 0);
156 write_MASTER_STAT(iface, 0x3e); 147 write_MASTER_STAT(iface, 0x3e);
157 write_MASTER_CTL(iface, 0); 148 write_MASTER_CTL(iface, 0);
158 SSYNC();
159 iface->result = -EIO; 149 iface->result = -EIO;
160 150
161 if (mast_stat & LOSTARB) 151 if (mast_stat & LOSTARB)
@@ -173,10 +163,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
173 * results. 163 * results.
174 */ 164 */
175 if (twi_int_status & MCOMP) { 165 if (twi_int_status & MCOMP) {
176 write_INT_STAT(iface, MCOMP);
177 write_INT_MASK(iface, 0);
178 write_MASTER_CTL(iface, 0);
179 SSYNC();
180 /* If it is a quick transfer, only address without data, 166 /* If it is a quick transfer, only address without data,
181 * not an err, return 1. 167 * not an err, return 1.
182 * If address is acknowledged return 1. 168 * If address is acknowledged return 1.
@@ -189,8 +175,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
189 return; 175 return;
190 } 176 }
191 if (twi_int_status & MCOMP) { 177 if (twi_int_status & MCOMP) {
192 write_INT_STAT(iface, MCOMP);
193 SSYNC();
194 if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { 178 if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
195 if (iface->readNum == 0) { 179 if (iface->readNum == 0) {
196 /* set the read number to 1 and ask for manual 180 /* set the read number to 1 and ask for manual
@@ -212,7 +196,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
212 /* remove restart bit and enable master receive */ 196 /* remove restart bit and enable master receive */
213 write_MASTER_CTL(iface, 197 write_MASTER_CTL(iface,
214 read_MASTER_CTL(iface) & ~RSTART); 198 read_MASTER_CTL(iface) & ~RSTART);
215 SSYNC();
216 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && 199 } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
217 iface->cur_msg+1 < iface->msg_num) { 200 iface->cur_msg+1 < iface->msg_num) {
218 iface->cur_msg++; 201 iface->cur_msg++;
@@ -231,7 +214,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
231 write_XMT_DATA8(iface, 214 write_XMT_DATA8(iface,
232 *(iface->transPtr++)); 215 *(iface->transPtr++));
233 iface->writeNum--; 216 iface->writeNum--;
234 SSYNC();
235 } 217 }
236 } 218 }
237 219
@@ -249,12 +231,10 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
249 /* remove restart bit and enable master receive */ 231 /* remove restart bit and enable master receive */
250 write_MASTER_CTL(iface, 232 write_MASTER_CTL(iface,
251 read_MASTER_CTL(iface) & ~RSTART); 233 read_MASTER_CTL(iface) & ~RSTART);
252 SSYNC();
253 } else { 234 } else {
254 iface->result = 1; 235 iface->result = 1;
255 write_INT_MASK(iface, 0); 236 write_INT_MASK(iface, 0);
256 write_MASTER_CTL(iface, 0); 237 write_MASTER_CTL(iface, 0);
257 SSYNC();
258 } 238 }
259 } 239 }
260 complete(&iface->complete); 240 complete(&iface->complete);
@@ -265,9 +245,18 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id)
265{ 245{
266 struct bfin_twi_iface *iface = dev_id; 246 struct bfin_twi_iface *iface = dev_id;
267 unsigned long flags; 247 unsigned long flags;
248 unsigned short twi_int_status;
268 249
269 spin_lock_irqsave(&iface->lock, flags); 250 spin_lock_irqsave(&iface->lock, flags);
270 bfin_twi_handle_interrupt(iface); 251 while (1) {
252 twi_int_status = read_INT_STAT(iface);
253 if (!twi_int_status)
254 break;
255 /* Clear interrupt status */
256 write_INT_STAT(iface, twi_int_status);
257 bfin_twi_handle_interrupt(iface, twi_int_status);
258 SSYNC();
259 }
271 spin_unlock_irqrestore(&iface->lock, flags); 260 spin_unlock_irqrestore(&iface->lock, flags);
272 return IRQ_HANDLED; 261 return IRQ_HANDLED;
273} 262}