diff options
-rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 37 |
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 0279a7a6b86c..ff61c4b22095 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 | ||
84 | static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | 84 | static 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 | } |