]>
Commit | Line | Data |
---|---|---|
1ab52cf9 BS |
1 | /* |
2 | * Synopsys Designware I2C adapter driver (master only). | |
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 | */ | |
28 | #include <linux/kernel.h> | |
29 | #include <linux/module.h> | |
30 | #include <linux/delay.h> | |
31 | #include <linux/i2c.h> | |
32 | #include <linux/clk.h> | |
33 | #include <linux/errno.h> | |
34 | #include <linux/sched.h> | |
35 | #include <linux/err.h> | |
36 | #include <linux/interrupt.h> | |
37 | #include <linux/platform_device.h> | |
38 | #include <linux/io.h> | |
39 | ||
40 | /* | |
41 | * Registers offset | |
42 | */ | |
43 | #define DW_IC_CON 0x0 | |
44 | #define DW_IC_TAR 0x4 | |
45 | #define DW_IC_DATA_CMD 0x10 | |
46 | #define DW_IC_SS_SCL_HCNT 0x14 | |
47 | #define DW_IC_SS_SCL_LCNT 0x18 | |
48 | #define DW_IC_FS_SCL_HCNT 0x1c | |
49 | #define DW_IC_FS_SCL_LCNT 0x20 | |
50 | #define DW_IC_INTR_STAT 0x2c | |
51 | #define DW_IC_INTR_MASK 0x30 | |
e28000a3 | 52 | #define DW_IC_RAW_INTR_STAT 0x34 |
1ab52cf9 | 53 | #define DW_IC_CLR_INTR 0x40 |
e28000a3 SK |
54 | #define DW_IC_CLR_RX_UNDER 0x44 |
55 | #define DW_IC_CLR_RX_OVER 0x48 | |
56 | #define DW_IC_CLR_TX_OVER 0x4c | |
57 | #define DW_IC_CLR_RD_REQ 0x50 | |
58 | #define DW_IC_CLR_TX_ABRT 0x54 | |
59 | #define DW_IC_CLR_RX_DONE 0x58 | |
60 | #define DW_IC_CLR_ACTIVITY 0x5c | |
61 | #define DW_IC_CLR_STOP_DET 0x60 | |
62 | #define DW_IC_CLR_START_DET 0x64 | |
63 | #define DW_IC_CLR_GEN_CALL 0x68 | |
1ab52cf9 BS |
64 | #define DW_IC_ENABLE 0x6c |
65 | #define DW_IC_STATUS 0x70 | |
66 | #define DW_IC_TXFLR 0x74 | |
67 | #define DW_IC_RXFLR 0x78 | |
68 | #define DW_IC_COMP_PARAM_1 0xf4 | |
69 | #define DW_IC_TX_ABRT_SOURCE 0x80 | |
70 | ||
71 | #define DW_IC_CON_MASTER 0x1 | |
72 | #define DW_IC_CON_SPEED_STD 0x2 | |
73 | #define DW_IC_CON_SPEED_FAST 0x4 | |
74 | #define DW_IC_CON_10BITADDR_MASTER 0x10 | |
75 | #define DW_IC_CON_RESTART_EN 0x20 | |
76 | #define DW_IC_CON_SLAVE_DISABLE 0x40 | |
77 | ||
e28000a3 SK |
78 | #define DW_IC_INTR_RX_UNDER 0x001 |
79 | #define DW_IC_INTR_RX_OVER 0x002 | |
80 | #define DW_IC_INTR_RX_FULL 0x004 | |
81 | #define DW_IC_INTR_TX_OVER 0x008 | |
82 | #define DW_IC_INTR_TX_EMPTY 0x010 | |
83 | #define DW_IC_INTR_RD_REQ 0x020 | |
84 | #define DW_IC_INTR_TX_ABRT 0x040 | |
85 | #define DW_IC_INTR_RX_DONE 0x080 | |
86 | #define DW_IC_INTR_ACTIVITY 0x100 | |
1ab52cf9 | 87 | #define DW_IC_INTR_STOP_DET 0x200 |
e28000a3 SK |
88 | #define DW_IC_INTR_START_DET 0x400 |
89 | #define DW_IC_INTR_GEN_CALL 0x800 | |
1ab52cf9 BS |
90 | |
91 | #define DW_IC_STATUS_ACTIVITY 0x1 | |
92 | ||
93 | #define DW_IC_ERR_TX_ABRT 0x1 | |
94 | ||
95 | /* | |
96 | * status codes | |
97 | */ | |
98 | #define STATUS_IDLE 0x0 | |
99 | #define STATUS_WRITE_IN_PROGRESS 0x1 | |
100 | #define STATUS_READ_IN_PROGRESS 0x2 | |
101 | ||
102 | #define TIMEOUT 20 /* ms */ | |
103 | ||
104 | /* | |
105 | * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register | |
106 | * | |
107 | * only expected abort codes are listed here | |
108 | * refer to the datasheet for the full list | |
109 | */ | |
110 | #define ABRT_7B_ADDR_NOACK 0 | |
111 | #define ABRT_10ADDR1_NOACK 1 | |
112 | #define ABRT_10ADDR2_NOACK 2 | |
113 | #define ABRT_TXDATA_NOACK 3 | |
114 | #define ABRT_GCALL_NOACK 4 | |
115 | #define ABRT_GCALL_READ 5 | |
116 | #define ABRT_SBYTE_ACKDET 7 | |
117 | #define ABRT_SBYTE_NORSTRT 9 | |
118 | #define ABRT_10B_RD_NORSTRT 10 | |
119 | #define ARB_MASTER_DIS 11 | |
120 | #define ARB_LOST 12 | |
121 | ||
122 | static char *abort_sources[] = { | |
123 | [ABRT_7B_ADDR_NOACK] = | |
124 | "slave address not acknowledged (7bit mode)", | |
125 | [ABRT_10ADDR1_NOACK] = | |
126 | "first address byte not acknowledged (10bit mode)", | |
127 | [ABRT_10ADDR2_NOACK] = | |
128 | "second address byte not acknowledged (10bit mode)", | |
129 | [ABRT_TXDATA_NOACK] = | |
130 | "data not acknowledged", | |
131 | [ABRT_GCALL_NOACK] = | |
132 | "no acknowledgement for a general call", | |
133 | [ABRT_GCALL_READ] = | |
134 | "read after general call", | |
135 | [ABRT_SBYTE_ACKDET] = | |
136 | "start byte acknowledged", | |
137 | [ABRT_SBYTE_NORSTRT] = | |
138 | "trying to send start byte when restart is disabled", | |
139 | [ABRT_10B_RD_NORSTRT] = | |
140 | "trying to read when restart is disabled (10bit mode)", | |
141 | [ARB_MASTER_DIS] = | |
142 | "trying to use disabled adapter", | |
143 | [ARB_LOST] = | |
144 | "lost arbitration", | |
145 | }; | |
146 | ||
147 | /** | |
148 | * struct dw_i2c_dev - private i2c-designware data | |
149 | * @dev: driver model device node | |
150 | * @base: IO registers pointer | |
151 | * @cmd_complete: tx completion indicator | |
152 | * @pump_msg: continue in progress transfers | |
153 | * @lock: protect this struct and IO registers | |
154 | * @clk: input reference clock | |
155 | * @cmd_err: run time hadware error code | |
156 | * @msgs: points to an array of messages currently being transfered | |
157 | * @msgs_num: the number of elements in msgs | |
158 | * @msg_write_idx: the element index of the current tx message in the msgs | |
159 | * array | |
160 | * @tx_buf_len: the length of the current tx buffer | |
161 | * @tx_buf: the current tx buffer | |
162 | * @msg_read_idx: the element index of the current rx message in the msgs | |
163 | * array | |
164 | * @rx_buf_len: the length of the current rx buffer | |
165 | * @rx_buf: the current rx buffer | |
166 | * @msg_err: error status of the current transfer | |
167 | * @status: i2c master status, one of STATUS_* | |
168 | * @abort_source: copy of the TX_ABRT_SOURCE register | |
169 | * @irq: interrupt number for the i2c master | |
170 | * @adapter: i2c subsystem adapter node | |
171 | * @tx_fifo_depth: depth of the hardware tx fifo | |
172 | * @rx_fifo_depth: depth of the hardware rx fifo | |
173 | */ | |
174 | struct dw_i2c_dev { | |
175 | struct device *dev; | |
176 | void __iomem *base; | |
177 | struct completion cmd_complete; | |
178 | struct tasklet_struct pump_msg; | |
179 | struct mutex lock; | |
180 | struct clk *clk; | |
181 | int cmd_err; | |
182 | struct i2c_msg *msgs; | |
183 | int msgs_num; | |
184 | int msg_write_idx; | |
ed5e1dd5 | 185 | u32 tx_buf_len; |
1ab52cf9 BS |
186 | u8 *tx_buf; |
187 | int msg_read_idx; | |
ed5e1dd5 | 188 | u32 rx_buf_len; |
1ab52cf9 BS |
189 | u8 *rx_buf; |
190 | int msg_err; | |
191 | unsigned int status; | |
ed5e1dd5 | 192 | u32 abort_source; |
1ab52cf9 BS |
193 | int irq; |
194 | struct i2c_adapter adapter; | |
195 | unsigned int tx_fifo_depth; | |
196 | unsigned int rx_fifo_depth; | |
197 | }; | |
198 | ||
199 | /** | |
200 | * i2c_dw_init() - initialize the designware i2c master hardware | |
201 | * @dev: device private data | |
202 | * | |
203 | * This functions configures and enables the I2C master. | |
204 | * This function is called during I2C init function, and in case of timeout at | |
205 | * run time. | |
206 | */ | |
207 | static void i2c_dw_init(struct dw_i2c_dev *dev) | |
208 | { | |
209 | u32 input_clock_khz = clk_get_rate(dev->clk) / 1000; | |
ed5e1dd5 | 210 | u32 ic_con; |
1ab52cf9 BS |
211 | |
212 | /* Disable the adapter */ | |
ed5e1dd5 | 213 | writel(0, dev->base + DW_IC_ENABLE); |
1ab52cf9 BS |
214 | |
215 | /* set standard and fast speed deviders for high/low periods */ | |
ed5e1dd5 | 216 | writel((input_clock_khz * 40 / 10000)+1, /* std speed high, 4us */ |
1ab52cf9 | 217 | dev->base + DW_IC_SS_SCL_HCNT); |
ed5e1dd5 | 218 | writel((input_clock_khz * 47 / 10000)+1, /* std speed low, 4.7us */ |
1ab52cf9 | 219 | dev->base + DW_IC_SS_SCL_LCNT); |
ed5e1dd5 | 220 | writel((input_clock_khz * 6 / 10000)+1, /* fast speed high, 0.6us */ |
1ab52cf9 | 221 | dev->base + DW_IC_FS_SCL_HCNT); |
ed5e1dd5 | 222 | writel((input_clock_khz * 13 / 10000)+1, /* fast speed low, 1.3us */ |
1ab52cf9 BS |
223 | dev->base + DW_IC_FS_SCL_LCNT); |
224 | ||
225 | /* configure the i2c master */ | |
226 | ic_con = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | | |
227 | DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; | |
ed5e1dd5 | 228 | writel(ic_con, dev->base + DW_IC_CON); |
1ab52cf9 BS |
229 | } |
230 | ||
231 | /* | |
232 | * Waiting for bus not busy | |
233 | */ | |
234 | static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) | |
235 | { | |
236 | int timeout = TIMEOUT; | |
237 | ||
ed5e1dd5 | 238 | while (readl(dev->base + DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) { |
1ab52cf9 BS |
239 | if (timeout <= 0) { |
240 | dev_warn(dev->dev, "timeout waiting for bus ready\n"); | |
241 | return -ETIMEDOUT; | |
242 | } | |
243 | timeout--; | |
244 | mdelay(1); | |
245 | } | |
246 | ||
247 | return 0; | |
248 | } | |
249 | ||
250 | /* | |
251 | * Initiate low level master read/write transaction. | |
252 | * This function is called from i2c_dw_xfer when starting a transfer. | |
253 | * This function is also called from dw_i2c_pump_msg to continue a transfer | |
254 | * that is longer than the size of the TX FIFO. | |
255 | */ | |
256 | static void | |
e77cf232 | 257 | i2c_dw_xfer_msg(struct dw_i2c_dev *dev) |
1ab52cf9 | 258 | { |
1ab52cf9 | 259 | struct i2c_msg *msgs = dev->msgs; |
ed5e1dd5 SK |
260 | u32 ic_con, intr_mask; |
261 | int tx_limit = dev->tx_fifo_depth - readl(dev->base + DW_IC_TXFLR); | |
262 | int rx_limit = dev->rx_fifo_depth - readl(dev->base + DW_IC_RXFLR); | |
263 | u32 addr = msgs[dev->msg_write_idx].addr; | |
264 | u32 buf_len = dev->tx_buf_len; | |
1ab52cf9 BS |
265 | |
266 | if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { | |
267 | /* Disable the adapter */ | |
ed5e1dd5 | 268 | writel(0, dev->base + DW_IC_ENABLE); |
1ab52cf9 BS |
269 | |
270 | /* set the slave (target) address */ | |
ed5e1dd5 | 271 | writel(msgs[dev->msg_write_idx].addr, dev->base + DW_IC_TAR); |
1ab52cf9 BS |
272 | |
273 | /* if the slave address is ten bit address, enable 10BITADDR */ | |
ed5e1dd5 | 274 | ic_con = readl(dev->base + DW_IC_CON); |
1ab52cf9 BS |
275 | if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) |
276 | ic_con |= DW_IC_CON_10BITADDR_MASTER; | |
277 | else | |
278 | ic_con &= ~DW_IC_CON_10BITADDR_MASTER; | |
ed5e1dd5 | 279 | writel(ic_con, dev->base + DW_IC_CON); |
1ab52cf9 BS |
280 | |
281 | /* Enable the adapter */ | |
ed5e1dd5 | 282 | writel(1, dev->base + DW_IC_ENABLE); |
1ab52cf9 BS |
283 | } |
284 | ||
6d2ea487 | 285 | for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { |
1ab52cf9 BS |
286 | /* if target address has changed, we need to |
287 | * reprogram the target address in the i2c | |
288 | * adapter when we are done with this transfer | |
289 | */ | |
290 | if (msgs[dev->msg_write_idx].addr != addr) | |
291 | return; | |
292 | ||
293 | if (msgs[dev->msg_write_idx].len == 0) { | |
294 | dev_err(dev->dev, | |
295 | "%s: invalid message length\n", __func__); | |
296 | dev->msg_err = -EINVAL; | |
297 | return; | |
298 | } | |
299 | ||
300 | if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { | |
301 | /* new i2c_msg */ | |
302 | dev->tx_buf = msgs[dev->msg_write_idx].buf; | |
303 | buf_len = msgs[dev->msg_write_idx].len; | |
304 | } | |
305 | ||
306 | while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { | |
307 | if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { | |
ed5e1dd5 | 308 | writel(0x100, dev->base + DW_IC_DATA_CMD); |
1ab52cf9 BS |
309 | rx_limit--; |
310 | } else | |
ed5e1dd5 | 311 | writel(*(dev->tx_buf++), |
1ab52cf9 BS |
312 | dev->base + DW_IC_DATA_CMD); |
313 | tx_limit--; buf_len--; | |
314 | } | |
315 | } | |
316 | ||
317 | intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT; | |
318 | if (buf_len > 0) { /* more bytes to be written */ | |
319 | intr_mask |= DW_IC_INTR_TX_EMPTY; | |
320 | dev->status |= STATUS_WRITE_IN_PROGRESS; | |
321 | } else | |
322 | dev->status &= ~STATUS_WRITE_IN_PROGRESS; | |
ed5e1dd5 | 323 | writel(intr_mask, dev->base + DW_IC_INTR_MASK); |
1ab52cf9 BS |
324 | |
325 | dev->tx_buf_len = buf_len; | |
326 | } | |
327 | ||
328 | static void | |
78839bd0 | 329 | i2c_dw_read(struct dw_i2c_dev *dev) |
1ab52cf9 | 330 | { |
1ab52cf9 | 331 | struct i2c_msg *msgs = dev->msgs; |
ed5e1dd5 SK |
332 | u32 addr = msgs[dev->msg_read_idx].addr; |
333 | int rx_valid = readl(dev->base + DW_IC_RXFLR); | |
1ab52cf9 | 334 | |
6d2ea487 | 335 | for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { |
ed5e1dd5 | 336 | u32 len; |
1ab52cf9 BS |
337 | u8 *buf; |
338 | ||
339 | if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) | |
340 | continue; | |
341 | ||
342 | /* different i2c client, reprogram the i2c adapter */ | |
343 | if (msgs[dev->msg_read_idx].addr != addr) | |
344 | return; | |
345 | ||
346 | if (!(dev->status & STATUS_READ_IN_PROGRESS)) { | |
347 | len = msgs[dev->msg_read_idx].len; | |
348 | buf = msgs[dev->msg_read_idx].buf; | |
349 | } else { | |
350 | len = dev->rx_buf_len; | |
351 | buf = dev->rx_buf; | |
352 | } | |
353 | ||
354 | for (; len > 0 && rx_valid > 0; len--, rx_valid--) | |
ed5e1dd5 | 355 | *buf++ = readl(dev->base + 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 | ||
367 | /* | |
368 | * Prepare controller for a transaction and call i2c_dw_xfer_msg | |
369 | */ | |
370 | static int | |
371 | i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |
372 | { | |
373 | struct dw_i2c_dev *dev = i2c_get_adapdata(adap); | |
374 | int ret; | |
375 | ||
376 | dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); | |
377 | ||
378 | mutex_lock(&dev->lock); | |
379 | ||
380 | INIT_COMPLETION(dev->cmd_complete); | |
381 | dev->msgs = msgs; | |
382 | dev->msgs_num = num; | |
383 | dev->cmd_err = 0; | |
384 | dev->msg_write_idx = 0; | |
385 | dev->msg_read_idx = 0; | |
386 | dev->msg_err = 0; | |
387 | dev->status = STATUS_IDLE; | |
388 | ||
389 | ret = i2c_dw_wait_bus_not_busy(dev); | |
390 | if (ret < 0) | |
391 | goto done; | |
392 | ||
393 | /* start the transfers */ | |
e77cf232 | 394 | i2c_dw_xfer_msg(dev); |
1ab52cf9 BS |
395 | |
396 | /* wait for tx to complete */ | |
397 | ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); | |
398 | if (ret == 0) { | |
399 | dev_err(dev->dev, "controller timed out\n"); | |
400 | i2c_dw_init(dev); | |
401 | ret = -ETIMEDOUT; | |
402 | goto done; | |
403 | } else if (ret < 0) | |
404 | goto done; | |
405 | ||
406 | if (dev->msg_err) { | |
407 | ret = dev->msg_err; | |
408 | goto done; | |
409 | } | |
410 | ||
411 | /* no error */ | |
412 | if (likely(!dev->cmd_err)) { | |
413 | /* read rx fifo, and disable the adapter */ | |
414 | do { | |
78839bd0 | 415 | i2c_dw_read(dev); |
1ab52cf9 | 416 | } while (dev->status & STATUS_READ_IN_PROGRESS); |
ed5e1dd5 | 417 | writel(0, dev->base + DW_IC_ENABLE); |
1ab52cf9 BS |
418 | ret = num; |
419 | goto done; | |
420 | } | |
421 | ||
422 | /* We have an error */ | |
423 | if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { | |
424 | unsigned long abort_source = dev->abort_source; | |
425 | int i; | |
426 | ||
427 | for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) { | |
428 | dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); | |
429 | } | |
430 | } | |
431 | ret = -EIO; | |
432 | ||
433 | done: | |
434 | mutex_unlock(&dev->lock); | |
435 | ||
436 | return ret; | |
437 | } | |
438 | ||
439 | static u32 i2c_dw_func(struct i2c_adapter *adap) | |
440 | { | |
441 | return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; | |
442 | } | |
443 | ||
444 | static void dw_i2c_pump_msg(unsigned long data) | |
445 | { | |
446 | struct dw_i2c_dev *dev = (struct dw_i2c_dev *) data; | |
ed5e1dd5 | 447 | u32 intr_mask; |
1ab52cf9 | 448 | |
78839bd0 | 449 | i2c_dw_read(dev); |
e77cf232 | 450 | i2c_dw_xfer_msg(dev); |
1ab52cf9 BS |
451 | |
452 | intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT; | |
453 | if (dev->status & STATUS_WRITE_IN_PROGRESS) | |
454 | intr_mask |= DW_IC_INTR_TX_EMPTY; | |
ed5e1dd5 | 455 | writel(intr_mask, dev->base + DW_IC_INTR_MASK); |
1ab52cf9 BS |
456 | } |
457 | ||
e28000a3 SK |
458 | static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) |
459 | { | |
460 | u32 stat; | |
461 | ||
462 | /* | |
463 | * The IC_INTR_STAT register just indicates "enabled" interrupts. | |
464 | * Ths unmasked raw version of interrupt status bits are available | |
465 | * in the IC_RAW_INTR_STAT register. | |
466 | * | |
467 | * That is, | |
468 | * stat = readl(IC_INTR_STAT); | |
469 | * equals to, | |
470 | * stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK); | |
471 | * | |
472 | * The raw version might be useful for debugging purposes. | |
473 | */ | |
474 | stat = readl(dev->base + DW_IC_INTR_STAT); | |
475 | ||
476 | /* | |
477 | * Do not use the IC_CLR_INTR register to clear interrupts, or | |
478 | * you'll miss some interrupts, triggered during the period from | |
479 | * readl(IC_INTR_STAT) to readl(IC_CLR_INTR). | |
480 | * | |
481 | * Instead, use the separately-prepared IC_CLR_* registers. | |
482 | */ | |
483 | if (stat & DW_IC_INTR_RX_UNDER) | |
484 | readl(dev->base + DW_IC_CLR_RX_UNDER); | |
485 | if (stat & DW_IC_INTR_RX_OVER) | |
486 | readl(dev->base + DW_IC_CLR_RX_OVER); | |
487 | if (stat & DW_IC_INTR_TX_OVER) | |
488 | readl(dev->base + DW_IC_CLR_TX_OVER); | |
489 | if (stat & DW_IC_INTR_RD_REQ) | |
490 | readl(dev->base + DW_IC_CLR_RD_REQ); | |
491 | if (stat & DW_IC_INTR_TX_ABRT) { | |
492 | /* | |
493 | * The IC_TX_ABRT_SOURCE register is cleared whenever | |
494 | * the IC_CLR_TX_ABRT is read. Preserve it beforehand. | |
495 | */ | |
496 | dev->abort_source = readl(dev->base + DW_IC_TX_ABRT_SOURCE); | |
497 | readl(dev->base + DW_IC_CLR_TX_ABRT); | |
498 | } | |
499 | if (stat & DW_IC_INTR_RX_DONE) | |
500 | readl(dev->base + DW_IC_CLR_RX_DONE); | |
501 | if (stat & DW_IC_INTR_ACTIVITY) | |
502 | readl(dev->base + DW_IC_CLR_ACTIVITY); | |
503 | if (stat & DW_IC_INTR_STOP_DET) | |
504 | readl(dev->base + DW_IC_CLR_STOP_DET); | |
505 | if (stat & DW_IC_INTR_START_DET) | |
506 | readl(dev->base + DW_IC_CLR_START_DET); | |
507 | if (stat & DW_IC_INTR_GEN_CALL) | |
508 | readl(dev->base + DW_IC_CLR_GEN_CALL); | |
509 | ||
510 | return stat; | |
511 | } | |
512 | ||
1ab52cf9 BS |
513 | /* |
514 | * Interrupt service routine. This gets called whenever an I2C interrupt | |
515 | * occurs. | |
516 | */ | |
517 | static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) | |
518 | { | |
519 | struct dw_i2c_dev *dev = dev_id; | |
ed5e1dd5 | 520 | u32 stat; |
1ab52cf9 | 521 | |
e28000a3 | 522 | stat = i2c_dw_read_clear_intrbits(dev); |
1ab52cf9 | 523 | dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); |
e28000a3 | 524 | |
1ab52cf9 | 525 | if (stat & DW_IC_INTR_TX_ABRT) { |
1ab52cf9 BS |
526 | dev->cmd_err |= DW_IC_ERR_TX_ABRT; |
527 | dev->status = STATUS_IDLE; | |
528 | } else if (stat & DW_IC_INTR_TX_EMPTY) | |
529 | tasklet_schedule(&dev->pump_msg); | |
530 | ||
ed5e1dd5 | 531 | writel(0, dev->base + DW_IC_INTR_MASK); /* disable interrupts */ |
1ab52cf9 BS |
532 | if (stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) |
533 | complete(&dev->cmd_complete); | |
534 | ||
535 | return IRQ_HANDLED; | |
536 | } | |
537 | ||
538 | static struct i2c_algorithm i2c_dw_algo = { | |
539 | .master_xfer = i2c_dw_xfer, | |
540 | .functionality = i2c_dw_func, | |
541 | }; | |
542 | ||
543 | static int __devinit dw_i2c_probe(struct platform_device *pdev) | |
544 | { | |
545 | struct dw_i2c_dev *dev; | |
546 | struct i2c_adapter *adap; | |
91b52cae SK |
547 | struct resource *mem, *ioarea; |
548 | int irq, r; | |
1ab52cf9 BS |
549 | |
550 | /* NOTE: driver uses the static register mapping */ | |
551 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
552 | if (!mem) { | |
553 | dev_err(&pdev->dev, "no mem resource?\n"); | |
554 | return -EINVAL; | |
555 | } | |
556 | ||
91b52cae SK |
557 | irq = platform_get_irq(pdev, 0); |
558 | if (irq < 0) { | |
1ab52cf9 | 559 | dev_err(&pdev->dev, "no irq resource?\n"); |
91b52cae | 560 | return irq; /* -ENXIO */ |
1ab52cf9 BS |
561 | } |
562 | ||
563 | ioarea = request_mem_region(mem->start, resource_size(mem), | |
564 | pdev->name); | |
565 | if (!ioarea) { | |
566 | dev_err(&pdev->dev, "I2C region already claimed\n"); | |
567 | return -EBUSY; | |
568 | } | |
569 | ||
570 | dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); | |
571 | if (!dev) { | |
572 | r = -ENOMEM; | |
573 | goto err_release_region; | |
574 | } | |
575 | ||
576 | init_completion(&dev->cmd_complete); | |
577 | tasklet_init(&dev->pump_msg, dw_i2c_pump_msg, (unsigned long) dev); | |
578 | mutex_init(&dev->lock); | |
579 | dev->dev = get_device(&pdev->dev); | |
91b52cae | 580 | dev->irq = irq; |
1ab52cf9 BS |
581 | platform_set_drvdata(pdev, dev); |
582 | ||
583 | dev->clk = clk_get(&pdev->dev, NULL); | |
584 | if (IS_ERR(dev->clk)) { | |
585 | r = -ENODEV; | |
586 | goto err_free_mem; | |
587 | } | |
588 | clk_enable(dev->clk); | |
589 | ||
590 | dev->base = ioremap(mem->start, resource_size(mem)); | |
591 | if (dev->base == NULL) { | |
592 | dev_err(&pdev->dev, "failure mapping io resources\n"); | |
593 | r = -EBUSY; | |
594 | goto err_unuse_clocks; | |
595 | } | |
596 | { | |
597 | u32 param1 = readl(dev->base + DW_IC_COMP_PARAM_1); | |
598 | ||
599 | dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; | |
600 | dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; | |
601 | } | |
602 | i2c_dw_init(dev); | |
603 | ||
ed5e1dd5 | 604 | writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */ |
1ab52cf9 BS |
605 | r = request_irq(dev->irq, i2c_dw_isr, 0, pdev->name, dev); |
606 | if (r) { | |
607 | dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); | |
608 | goto err_iounmap; | |
609 | } | |
610 | ||
611 | adap = &dev->adapter; | |
612 | i2c_set_adapdata(adap, dev); | |
613 | adap->owner = THIS_MODULE; | |
614 | adap->class = I2C_CLASS_HWMON; | |
615 | strlcpy(adap->name, "Synopsys DesignWare I2C adapter", | |
616 | sizeof(adap->name)); | |
617 | adap->algo = &i2c_dw_algo; | |
618 | adap->dev.parent = &pdev->dev; | |
619 | ||
620 | adap->nr = pdev->id; | |
621 | r = i2c_add_numbered_adapter(adap); | |
622 | if (r) { | |
623 | dev_err(&pdev->dev, "failure adding adapter\n"); | |
624 | goto err_free_irq; | |
625 | } | |
626 | ||
627 | return 0; | |
628 | ||
629 | err_free_irq: | |
630 | free_irq(dev->irq, dev); | |
631 | err_iounmap: | |
632 | iounmap(dev->base); | |
633 | err_unuse_clocks: | |
634 | clk_disable(dev->clk); | |
635 | clk_put(dev->clk); | |
636 | dev->clk = NULL; | |
637 | err_free_mem: | |
638 | platform_set_drvdata(pdev, NULL); | |
639 | put_device(&pdev->dev); | |
640 | kfree(dev); | |
641 | err_release_region: | |
642 | release_mem_region(mem->start, resource_size(mem)); | |
643 | ||
644 | return r; | |
645 | } | |
646 | ||
647 | static int __devexit dw_i2c_remove(struct platform_device *pdev) | |
648 | { | |
649 | struct dw_i2c_dev *dev = platform_get_drvdata(pdev); | |
650 | struct resource *mem; | |
651 | ||
652 | platform_set_drvdata(pdev, NULL); | |
653 | i2c_del_adapter(&dev->adapter); | |
654 | put_device(&pdev->dev); | |
655 | ||
656 | clk_disable(dev->clk); | |
657 | clk_put(dev->clk); | |
658 | dev->clk = NULL; | |
659 | ||
ed5e1dd5 | 660 | writel(0, dev->base + DW_IC_ENABLE); |
1ab52cf9 BS |
661 | free_irq(dev->irq, dev); |
662 | kfree(dev); | |
663 | ||
664 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
665 | release_mem_region(mem->start, resource_size(mem)); | |
666 | return 0; | |
667 | } | |
668 | ||
669 | /* work with hotplug and coldplug */ | |
670 | MODULE_ALIAS("platform:i2c_designware"); | |
671 | ||
672 | static struct platform_driver dw_i2c_driver = { | |
673 | .remove = __devexit_p(dw_i2c_remove), | |
674 | .driver = { | |
675 | .name = "i2c_designware", | |
676 | .owner = THIS_MODULE, | |
677 | }, | |
678 | }; | |
679 | ||
680 | static int __init dw_i2c_init_driver(void) | |
681 | { | |
682 | return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); | |
683 | } | |
684 | module_init(dw_i2c_init_driver); | |
685 | ||
686 | static void __exit dw_i2c_exit_driver(void) | |
687 | { | |
688 | platform_driver_unregister(&dw_i2c_driver); | |
689 | } | |
690 | module_exit(dw_i2c_exit_driver); | |
691 | ||
692 | MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); | |
693 | MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter"); | |
694 | MODULE_LICENSE("GPL"); |