Commit | Line | Data |
---|---|---|
1ab52cf9 | 1 | /* |
a0e06ea6 | 2 | * Synopsys DesignWare I2C adapter driver (master only). |
1ab52cf9 BS |
3 | * |
4 | * Based on the TI DAVINCI I2C adapter driver. | |
5 | * | |
6 | * Copyright (C) 2006 Texas Instruments. | |
7 | * Copyright (C) 2007 MontaVista Software Inc. | |
8 | * Copyright (C) 2009 Provigent Ltd. | |
9 | * | |
10 | * ---------------------------------------------------------------------------- | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or | |
15 | * (at your option) any later version. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; if not, write to the Free Software | |
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 | * ---------------------------------------------------------------------------- | |
26 | * | |
27 | */ | |
1ab52cf9 BS |
28 | #include <linux/clk.h> |
29 | #include <linux/errno.h> | |
1ab52cf9 | 30 | #include <linux/err.h> |
2373f6b9 | 31 | #include <linux/i2c.h> |
1ab52cf9 | 32 | #include <linux/interrupt.h> |
1ab52cf9 | 33 | #include <linux/io.h> |
2373f6b9 DB |
34 | #include <linux/delay.h> |
35 | #include "i2c-designware-core.h" | |
ce6eb574 | 36 | |
1ab52cf9 | 37 | static char *abort_sources[] = { |
a0e06ea6 | 38 | [ABRT_7B_ADDR_NOACK] = |
1ab52cf9 | 39 | "slave address not acknowledged (7bit mode)", |
a0e06ea6 | 40 | [ABRT_10ADDR1_NOACK] = |
1ab52cf9 | 41 | "first address byte not acknowledged (10bit mode)", |
a0e06ea6 | 42 | [ABRT_10ADDR2_NOACK] = |
1ab52cf9 | 43 | "second address byte not acknowledged (10bit mode)", |
a0e06ea6 | 44 | [ABRT_TXDATA_NOACK] = |
1ab52cf9 | 45 | "data not acknowledged", |
a0e06ea6 | 46 | [ABRT_GCALL_NOACK] = |
1ab52cf9 | 47 | "no acknowledgement for a general call", |
a0e06ea6 | 48 | [ABRT_GCALL_READ] = |
1ab52cf9 | 49 | "read after general call", |
a0e06ea6 | 50 | [ABRT_SBYTE_ACKDET] = |
1ab52cf9 | 51 | "start byte acknowledged", |
a0e06ea6 | 52 | [ABRT_SBYTE_NORSTRT] = |
1ab52cf9 | 53 | "trying to send start byte when restart is disabled", |
a0e06ea6 | 54 | [ABRT_10B_RD_NORSTRT] = |
1ab52cf9 | 55 | "trying to read when restart is disabled (10bit mode)", |
a0e06ea6 | 56 | [ABRT_MASTER_DIS] = |
1ab52cf9 | 57 | "trying to use disabled adapter", |
a0e06ea6 | 58 | [ARB_LOST] = |
1ab52cf9 BS |
59 | "lost arbitration", |
60 | }; | |
61 | ||
2373f6b9 | 62 | u32 dw_readl(struct dw_i2c_dev *dev, int offset) |
7f279601 | 63 | { |
18c4089e JHD |
64 | u32 value = readl(dev->base + offset); |
65 | ||
66 | if (dev->swab) | |
67 | return swab32(value); | |
68 | else | |
69 | return value; | |
7f279601 JHD |
70 | } |
71 | ||
2373f6b9 | 72 | void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) |
7f279601 | 73 | { |
18c4089e JHD |
74 | if (dev->swab) |
75 | b = swab32(b); | |
76 | ||
7f279601 JHD |
77 | writel(b, dev->base + offset); |
78 | } | |
79 | ||
d60c7e81 SK |
80 | static u32 |
81 | i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) | |
82 | { | |
83 | /* | |
84 | * DesignWare I2C core doesn't seem to have solid strategy to meet | |
85 | * the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec | |
86 | * will result in violation of the tHD;STA spec. | |
87 | */ | |
88 | if (cond) | |
89 | /* | |
90 | * Conditional expression: | |
91 | * | |
92 | * IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH | |
93 | * | |
94 | * This is based on the DW manuals, and represents an ideal | |
95 | * configuration. The resulting I2C bus speed will be | |
96 | * faster than any of the others. | |
97 | * | |
98 | * If your hardware is free from tHD;STA issue, try this one. | |
99 | */ | |
100 | return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset; | |
101 | else | |
102 | /* | |
103 | * Conditional expression: | |
104 | * | |
105 | * IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf) | |
106 | * | |
107 | * This is just experimental rule; the tHD;STA period turned | |
108 | * out to be proportinal to (_HCNT + 3). With this setting, | |
109 | * we could meet both tHIGH and tHD;STA timing specs. | |
110 | * | |
111 | * If unsure, you'd better to take this alternative. | |
112 | * | |
113 | * The reason why we need to take into account "tf" here, | |
114 | * is the same as described in i2c_dw_scl_lcnt(). | |
115 | */ | |
116 | return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset; | |
117 | } | |
118 | ||
119 | static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) | |
120 | { | |
121 | /* | |
122 | * Conditional expression: | |
123 | * | |
124 | * IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf) | |
125 | * | |
126 | * DW I2C core starts counting the SCL CNTs for the LOW period | |
127 | * of the SCL clock (tLOW) as soon as it pulls the SCL line. | |
128 | * In order to meet the tLOW timing spec, we need to take into | |
129 | * account the fall time of SCL signal (tf). Default tf value | |
130 | * should be 0.3 us, for safety. | |
131 | */ | |
132 | return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset; | |
133 | } | |
134 | ||
1ab52cf9 BS |
135 | /** |
136 | * i2c_dw_init() - initialize the designware i2c master hardware | |
137 | * @dev: device private data | |
138 | * | |
139 | * This functions configures and enables the I2C master. | |
140 | * This function is called during I2C init function, and in case of timeout at | |
141 | * run time. | |
142 | */ | |
2373f6b9 | 143 | int i2c_dw_init(struct dw_i2c_dev *dev) |
1ab52cf9 BS |
144 | { |
145 | u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; | |
d60c7e81 | 146 | u32 ic_con, hcnt, lcnt; |
4a423a8c DB |
147 | u32 reg; |
148 | ||
149 | /* Configure register endianess access */ | |
150 | reg = dw_readl(dev, DW_IC_COMP_TYPE); | |
151 | if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) { | |
152 | dev->swab = 1; | |
153 | reg = DW_IC_COMP_TYPE_VALUE; | |
154 | } | |
155 | ||
156 | if (reg != DW_IC_COMP_TYPE_VALUE) { | |
157 | dev_err(dev->dev, "Unknown Synopsys component type: " | |
158 | "0x%08x\n", reg); | |
159 | return -ENODEV; | |
160 | } | |
1ab52cf9 BS |
161 | |
162 | /* Disable the adapter */ | |
7f279601 | 163 | dw_writel(dev, 0, DW_IC_ENABLE); |
1ab52cf9 BS |
164 | |
165 | /* set standard and fast speed deviders for high/low periods */ | |
d60c7e81 SK |
166 | |
167 | /* Standard-mode */ | |
168 | hcnt = i2c_dw_scl_hcnt(input_clock_khz, | |
169 | 40, /* tHD;STA = tHIGH = 4.0 us */ | |
170 | 3, /* tf = 0.3 us */ | |
171 | 0, /* 0: DW default, 1: Ideal */ | |
172 | 0); /* No offset */ | |
173 | lcnt = i2c_dw_scl_lcnt(input_clock_khz, | |
174 | 47, /* tLOW = 4.7 us */ | |
175 | 3, /* tf = 0.3 us */ | |
176 | 0); /* No offset */ | |
7f279601 JHD |
177 | dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); |
178 | dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); | |
d60c7e81 SK |
179 | dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); |
180 | ||
181 | /* Fast-mode */ | |
182 | hcnt = i2c_dw_scl_hcnt(input_clock_khz, | |
183 | 6, /* tHD;STA = tHIGH = 0.6 us */ | |
184 | 3, /* tf = 0.3 us */ | |
185 | 0, /* 0: DW default, 1: Ideal */ | |
186 | 0); /* No offset */ | |
187 | lcnt = i2c_dw_scl_lcnt(input_clock_khz, | |
188 | 13, /* tLOW = 1.3 us */ | |
189 | 3, /* tf = 0.3 us */ | |
190 | 0); /* No offset */ | |
7f279601 JHD |
191 | dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); |
192 | dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); | |
d60c7e81 | 193 | dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); |
1ab52cf9 | 194 | |
4cb6d1d6 | 195 | /* Configure Tx/Rx FIFO threshold levels */ |
7f279601 JHD |
196 | dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL); |
197 | dw_writel(dev, 0, DW_IC_RX_TL); | |
4cb6d1d6 | 198 | |
1ab52cf9 BS |
199 | /* configure the i2c master */ |
200 | ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | | |
201 | DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; | |
7f279601 | 202 | dw_writel(dev, ic_con, DW_IC_CON); |
4a423a8c | 203 | return 0; |
1ab52cf9 BS |
204 | } |
205 | ||
206 | /* | |
207 | * Waiting for bus not busy | |
208 | */ | |
209 | static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) | |
210 | { | |
211 | int timeout = TIMEOUT; | |
212 | ||
7f279601 | 213 | while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) { |
1ab52cf9 BS |
214 | if (timeout <= 0) { |
215 | dev_warn(dev->dev, "timeout waiting for bus ready\n"); | |
216 | return -ETIMEDOUT; | |
217 | } | |
218 | timeout--; | |
219 | mdelay(1); | |
220 | } | |
221 | ||
222 | return 0; | |
223 | } | |
224 | ||
81e798b7 SK |
225 | static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) |
226 | { | |
227 | struct i2c_msg *msgs = dev->msgs; | |
228 | u32 ic_con; | |
229 | ||
230 | /* Disable the adapter */ | |
7f279601 | 231 | dw_writel(dev, 0, DW_IC_ENABLE); |
81e798b7 SK |
232 | |
233 | /* set the slave (target) address */ | |
7f279601 | 234 | dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR); |
81e798b7 SK |
235 | |
236 | /* if the slave address is ten bit address, enable 10BITADDR */ | |
7f279601 | 237 | ic_con = dw_readl(dev, DW_IC_CON); |
81e798b7 SK |
238 | if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) |
239 | ic_con |= DW_IC_CON_10BITADDR_MASTER; | |
240 | else | |
241 | ic_con &= ~DW_IC_CON_10BITADDR_MASTER; | |
7f279601 | 242 | dw_writel(dev, ic_con, DW_IC_CON); |
81e798b7 SK |
243 | |
244 | /* Enable the adapter */ | |
7f279601 | 245 | dw_writel(dev, 1, DW_IC_ENABLE); |
201d6a70 SK |
246 | |
247 | /* Enable interrupts */ | |
7f279601 | 248 | dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); |
81e798b7 SK |
249 | } |
250 | ||
1ab52cf9 | 251 | /* |
201d6a70 SK |
252 | * Initiate (and continue) low level master read/write transaction. |
253 | * This function is only called from i2c_dw_isr, and pumping i2c_msg | |
254 | * messages into the tx buffer. Even if the size of i2c_msg data is | |
255 | * longer than the size of the tx buffer, it handles everything. | |
1ab52cf9 | 256 | */ |
2373f6b9 | 257 | void |
e77cf232 | 258 | i2c_dw_xfer_msg(struct dw_i2c_dev *dev) |
1ab52cf9 | 259 | { |
1ab52cf9 | 260 | struct i2c_msg *msgs = dev->msgs; |
81e798b7 | 261 | u32 intr_mask; |
ae72222d | 262 | int tx_limit, rx_limit; |
ed5e1dd5 SK |
263 | u32 addr = msgs[dev->msg_write_idx].addr; |
264 | u32 buf_len = dev->tx_buf_len; | |
69932487 | 265 | u8 *buf = dev->tx_buf; |
1ab52cf9 | 266 | |
201d6a70 | 267 | intr_mask = DW_IC_INTR_DEFAULT_MASK; |
c70c5cd3 | 268 | |
6d2ea487 | 269 | for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { |
a0e06ea6 SK |
270 | /* |
271 | * if target address has changed, we need to | |
1ab52cf9 BS |
272 | * reprogram the target address in the i2c |
273 | * adapter when we are done with this transfer | |
274 | */ | |
8f588e40 SK |
275 | if (msgs[dev->msg_write_idx].addr != addr) { |
276 | dev_err(dev->dev, | |
277 | "%s: invalid target address\n", __func__); | |
278 | dev->msg_err = -EINVAL; | |
279 | break; | |
280 | } | |
1ab52cf9 BS |
281 | |
282 | if (msgs[dev->msg_write_idx].len == 0) { | |
283 | dev_err(dev->dev, | |
284 | "%s: invalid message length\n", __func__); | |
285 | dev->msg_err = -EINVAL; | |
8f588e40 | 286 | break; |
1ab52cf9 BS |
287 | } |
288 | ||
289 | if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { | |
290 | /* new i2c_msg */ | |
26ea15b1 | 291 | buf = msgs[dev->msg_write_idx].buf; |
1ab52cf9 BS |
292 | buf_len = msgs[dev->msg_write_idx].len; |
293 | } | |
294 | ||
7f279601 JHD |
295 | tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR); |
296 | rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR); | |
ae72222d | 297 | |
1ab52cf9 BS |
298 | while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { |
299 | if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { | |
7f279601 | 300 | dw_writel(dev, 0x100, DW_IC_DATA_CMD); |
1ab52cf9 BS |
301 | rx_limit--; |
302 | } else | |
7f279601 | 303 | dw_writel(dev, *buf++, DW_IC_DATA_CMD); |
1ab52cf9 BS |
304 | tx_limit--; buf_len--; |
305 | } | |
c70c5cd3 | 306 | |
26ea15b1 | 307 | dev->tx_buf = buf; |
c70c5cd3 SK |
308 | dev->tx_buf_len = buf_len; |
309 | ||
310 | if (buf_len > 0) { | |
311 | /* more bytes to be written */ | |
c70c5cd3 SK |
312 | dev->status |= STATUS_WRITE_IN_PROGRESS; |
313 | break; | |
69151e53 | 314 | } else |
c70c5cd3 | 315 | dev->status &= ~STATUS_WRITE_IN_PROGRESS; |
1ab52cf9 BS |
316 | } |
317 | ||
69151e53 SK |
318 | /* |
319 | * If i2c_msg index search is completed, we don't need TX_EMPTY | |
320 | * interrupt any more. | |
321 | */ | |
322 | if (dev->msg_write_idx == dev->msgs_num) | |
323 | intr_mask &= ~DW_IC_INTR_TX_EMPTY; | |
324 | ||
8f588e40 SK |
325 | if (dev->msg_err) |
326 | intr_mask = 0; | |
327 | ||
2373f6b9 | 328 | dw_writel(dev, intr_mask, DW_IC_INTR_MASK); |
1ab52cf9 BS |
329 | } |
330 | ||
331 | static void | |
78839bd0 | 332 | i2c_dw_read(struct dw_i2c_dev *dev) |
1ab52cf9 | 333 | { |
1ab52cf9 | 334 | struct i2c_msg *msgs = dev->msgs; |
ae72222d | 335 | int rx_valid; |
1ab52cf9 | 336 | |
6d2ea487 | 337 | for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { |
ed5e1dd5 | 338 | u32 len; |
1ab52cf9 BS |
339 | u8 *buf; |
340 | ||
341 | if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) | |
342 | continue; | |
343 | ||
1ab52cf9 BS |
344 | if (!(dev->status & STATUS_READ_IN_PROGRESS)) { |
345 | len = msgs[dev->msg_read_idx].len; | |
346 | buf = msgs[dev->msg_read_idx].buf; | |
347 | } else { | |
348 | len = dev->rx_buf_len; | |
349 | buf = dev->rx_buf; | |
350 | } | |
351 | ||
7f279601 | 352 | rx_valid = dw_readl(dev, DW_IC_RXFLR); |
ae72222d | 353 | |
1ab52cf9 | 354 | for (; len > 0 && rx_valid > 0; len--, rx_valid--) |
7f279601 | 355 | *buf++ = dw_readl(dev, DW_IC_DATA_CMD); |
1ab52cf9 BS |
356 | |
357 | if (len > 0) { | |
358 | dev->status |= STATUS_READ_IN_PROGRESS; | |
359 | dev->rx_buf_len = len; | |
360 | dev->rx_buf = buf; | |
361 | return; | |
362 | } else | |
363 | dev->status &= ~STATUS_READ_IN_PROGRESS; | |
364 | } | |
365 | } | |
366 | ||
ce6eb574 SK |
367 | static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) |
368 | { | |
369 | unsigned long abort_source = dev->abort_source; | |
370 | int i; | |
371 | ||
6d1ea0f6 | 372 | if (abort_source & DW_IC_TX_ABRT_NOACK) { |
984b3f57 | 373 | for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) |
6d1ea0f6 SK |
374 | dev_dbg(dev->dev, |
375 | "%s: %s\n", __func__, abort_sources[i]); | |
376 | return -EREMOTEIO; | |
377 | } | |
378 | ||
984b3f57 | 379 | for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) |
ce6eb574 SK |
380 | dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); |
381 | ||
382 | if (abort_source & DW_IC_TX_ARB_LOST) | |
383 | return -EAGAIN; | |
ce6eb574 SK |
384 | else if (abort_source & DW_IC_TX_ABRT_GCALL_READ) |
385 | return -EINVAL; /* wrong msgs[] data */ | |
386 | else | |
387 | return -EIO; | |
388 | } | |
389 | ||
1ab52cf9 BS |
390 | /* |
391 | * Prepare controller for a transaction and call i2c_dw_xfer_msg | |
392 | */ | |
2373f6b9 | 393 | int |
1ab52cf9 BS |
394 | i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) |
395 | { | |
396 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); | |
397 | int ret; | |
398 | ||
399 | dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); | |
400 | ||
401 | mutex_lock(&dev->lock); | |
402 | ||
403 | INIT_COMPLETION(dev->cmd_complete); | |
404 | dev->msgs = msgs; | |
405 | dev->msgs_num = num; | |
406 | dev->cmd_err = 0; | |
407 | dev->msg_write_idx = 0; | |
408 | dev->msg_read_idx = 0; | |
409 | dev->msg_err = 0; | |
410 | dev->status = STATUS_IDLE; | |
ce6eb574 | 411 | dev->abort_source = 0; |
1ab52cf9 BS |
412 | |
413 | ret = i2c_dw_wait_bus_not_busy(dev); | |
414 | if (ret < 0) | |
415 | goto done; | |
416 | ||
417 | /* start the transfers */ | |
81e798b7 | 418 | i2c_dw_xfer_init(dev); |
1ab52cf9 BS |
419 | |
420 | /* wait for tx to complete */ | |
421 | ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); | |
422 | if (ret == 0) { | |
423 | dev_err(dev->dev, "controller timed out\n"); | |
424 | i2c_dw_init(dev); | |
425 | ret = -ETIMEDOUT; | |
426 | goto done; | |
427 | } else if (ret < 0) | |
428 | goto done; | |
429 | ||
430 | if (dev->msg_err) { | |
431 | ret = dev->msg_err; | |
432 | goto done; | |
433 | } | |
434 | ||
435 | /* no error */ | |
436 | if (likely(!dev->cmd_err)) { | |
07745399 | 437 | /* Disable the adapter */ |
7f279601 | 438 | dw_writel(dev, 0, DW_IC_ENABLE); |
1ab52cf9 BS |
439 | ret = num; |
440 | goto done; | |
441 | } | |
442 | ||
443 | /* We have an error */ | |
444 | if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { | |
ce6eb574 SK |
445 | ret = i2c_dw_handle_tx_abort(dev); |
446 | goto done; | |
1ab52cf9 BS |
447 | } |
448 | ret = -EIO; | |
449 | ||
450 | done: | |
451 | mutex_unlock(&dev->lock); | |
452 | ||
453 | return ret; | |
454 | } | |
455 | ||
2373f6b9 | 456 | u32 i2c_dw_func(struct i2c_adapter *adap) |
1ab52cf9 | 457 | { |
52d7e430 SK |
458 | return I2C_FUNC_I2C | |
459 | I2C_FUNC_10BIT_ADDR | | |
460 | I2C_FUNC_SMBUS_BYTE | | |
461 | I2C_FUNC_SMBUS_BYTE_DATA | | |
462 | I2C_FUNC_SMBUS_WORD_DATA | | |
463 | I2C_FUNC_SMBUS_I2C_BLOCK; | |
1ab52cf9 BS |
464 | } |
465 | ||
e28000a3 SK |
466 | static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) |
467 | { | |
468 | u32 stat; | |
469 | ||
470 | /* | |
471 | * The IC_INTR_STAT register just indicates "enabled" interrupts. | |
472 | * Ths unmasked raw version of interrupt status bits are available | |
473 | * in the IC_RAW_INTR_STAT register. | |
474 | * | |
475 | * That is, | |
2373f6b9 | 476 | * stat = dw_readl(IC_INTR_STAT); |
e28000a3 | 477 | * equals to, |
2373f6b9 | 478 | * stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK); |
e28000a3 SK |
479 | * |
480 | * The raw version might be useful for debugging purposes. | |
481 | */ | |
7f279601 | 482 | stat = dw_readl(dev, DW_IC_INTR_STAT); |
e28000a3 SK |
483 | |
484 | /* | |
485 | * Do not use the IC_CLR_INTR register to clear interrupts, or | |
486 | * you'll miss some interrupts, triggered during the period from | |
2373f6b9 | 487 | * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR). |
e28000a3 SK |
488 | * |
489 | * Instead, use the separately-prepared IC_CLR_* registers. | |
490 | */ | |
491 | if (stat & DW_IC_INTR_RX_UNDER) | |
7f279601 | 492 | dw_readl(dev, DW_IC_CLR_RX_UNDER); |
e28000a3 | 493 | if (stat & DW_IC_INTR_RX_OVER) |
7f279601 | 494 | dw_readl(dev, DW_IC_CLR_RX_OVER); |
e28000a3 | 495 | if (stat & DW_IC_INTR_TX_OVER) |
7f279601 | 496 | dw_readl(dev, DW_IC_CLR_TX_OVER); |
e28000a3 | 497 | if (stat & DW_IC_INTR_RD_REQ) |
7f279601 | 498 | dw_readl(dev, DW_IC_CLR_RD_REQ); |
e28000a3 SK |
499 | if (stat & DW_IC_INTR_TX_ABRT) { |
500 | /* | |
501 | * The IC_TX_ABRT_SOURCE register is cleared whenever | |
502 | * the IC_CLR_TX_ABRT is read. Preserve it beforehand. | |
503 | */ | |
7f279601 JHD |
504 | dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE); |
505 | dw_readl(dev, DW_IC_CLR_TX_ABRT); | |
e28000a3 SK |
506 | } |
507 | if (stat & DW_IC_INTR_RX_DONE) | |
7f279601 | 508 | dw_readl(dev, DW_IC_CLR_RX_DONE); |
e28000a3 | 509 | if (stat & DW_IC_INTR_ACTIVITY) |
7f279601 | 510 | dw_readl(dev, DW_IC_CLR_ACTIVITY); |
e28000a3 | 511 | if (stat & DW_IC_INTR_STOP_DET) |
7f279601 | 512 | dw_readl(dev, DW_IC_CLR_STOP_DET); |
e28000a3 | 513 | if (stat & DW_IC_INTR_START_DET) |
7f279601 | 514 | dw_readl(dev, DW_IC_CLR_START_DET); |
e28000a3 | 515 | if (stat & DW_IC_INTR_GEN_CALL) |
7f279601 | 516 | dw_readl(dev, DW_IC_CLR_GEN_CALL); |
e28000a3 SK |
517 | |
518 | return stat; | |
519 | } | |
520 | ||
1ab52cf9 BS |
521 | /* |
522 | * Interrupt service routine. This gets called whenever an I2C interrupt | |
523 | * occurs. | |
524 | */ | |
2373f6b9 | 525 | irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) |
1ab52cf9 BS |
526 | { |
527 | struct dw_i2c_dev *dev = dev_id; | |
ed5e1dd5 | 528 | u32 stat; |
1ab52cf9 | 529 | |
e28000a3 | 530 | stat = i2c_dw_read_clear_intrbits(dev); |
1ab52cf9 | 531 | dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); |
e28000a3 | 532 | |
1ab52cf9 | 533 | if (stat & DW_IC_INTR_TX_ABRT) { |
1ab52cf9 BS |
534 | dev->cmd_err |= DW_IC_ERR_TX_ABRT; |
535 | dev->status = STATUS_IDLE; | |
597fe310 SK |
536 | |
537 | /* | |
538 | * Anytime TX_ABRT is set, the contents of the tx/rx | |
539 | * buffers are flushed. Make sure to skip them. | |
540 | */ | |
7f279601 | 541 | dw_writel(dev, 0, DW_IC_INTR_MASK); |
597fe310 | 542 | goto tx_aborted; |
07745399 SK |
543 | } |
544 | ||
21a89d41 | 545 | if (stat & DW_IC_INTR_RX_FULL) |
07745399 | 546 | i2c_dw_read(dev); |
21a89d41 SK |
547 | |
548 | if (stat & DW_IC_INTR_TX_EMPTY) | |
07745399 | 549 | i2c_dw_xfer_msg(dev); |
07745399 SK |
550 | |
551 | /* | |
552 | * No need to modify or disable the interrupt mask here. | |
553 | * i2c_dw_xfer_msg() will take care of it according to | |
554 | * the current transmit status. | |
555 | */ | |
1ab52cf9 | 556 | |
597fe310 | 557 | tx_aborted: |
8f588e40 | 558 | if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) |
1ab52cf9 BS |
559 | complete(&dev->cmd_complete); |
560 | ||
561 | return IRQ_HANDLED; | |
562 | } |