Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
a0832798 TP |
2 | * Driver for the i2c controller on the Marvell line of host bridges |
3 | * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family). | |
1da177e4 LT |
4 | * |
5 | * Author: Mark A. Greer <mgreer@mvista.com> | |
6 | * | |
7 | * 2005 (c) MontaVista, Software, Inc. This file is licensed under | |
8 | * the terms of the GNU General Public License version 2. This program | |
9 | * is licensed "as is" without any warranty of any kind, whether express | |
10 | * or implied. | |
11 | */ | |
12 | #include <linux/kernel.h> | |
5a0e3ad6 | 13 | #include <linux/slab.h> |
1da177e4 LT |
14 | #include <linux/module.h> |
15 | #include <linux/spinlock.h> | |
16 | #include <linux/i2c.h> | |
17 | #include <linux/interrupt.h> | |
a0832798 | 18 | #include <linux/mv643xx_i2c.h> |
d052d1be | 19 | #include <linux/platform_device.h> |
21782180 | 20 | #include <linux/io.h> |
b61d1575 | 21 | #include <linux/of.h> |
004e8ed7 | 22 | #include <linux/of_device.h> |
b61d1575 AL |
23 | #include <linux/of_irq.h> |
24 | #include <linux/of_i2c.h> | |
25 | #include <linux/clk.h> | |
26 | #include <linux/err.h> | |
1da177e4 | 27 | |
683e69b8 MR |
28 | #define MV64XXX_I2C_ADDR_ADDR(val) ((val & 0x7f) << 1) |
29 | #define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7) | |
30 | #define MV64XXX_I2C_BAUD_DIV_M(val) ((val & 0xf) << 3) | |
31 | ||
1da177e4 LT |
32 | #define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 |
33 | #define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 | |
34 | #define MV64XXX_I2C_REG_CONTROL_STOP 0x00000010 | |
35 | #define MV64XXX_I2C_REG_CONTROL_START 0x00000020 | |
36 | #define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x00000040 | |
37 | #define MV64XXX_I2C_REG_CONTROL_INTEN 0x00000080 | |
38 | ||
39 | /* Ctlr status values */ | |
40 | #define MV64XXX_I2C_STATUS_BUS_ERR 0x00 | |
41 | #define MV64XXX_I2C_STATUS_MAST_START 0x08 | |
42 | #define MV64XXX_I2C_STATUS_MAST_REPEAT_START 0x10 | |
43 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK 0x18 | |
44 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20 | |
45 | #define MV64XXX_I2C_STATUS_MAST_WR_ACK 0x28 | |
46 | #define MV64XXX_I2C_STATUS_MAST_WR_NO_ACK 0x30 | |
47 | #define MV64XXX_I2C_STATUS_MAST_LOST_ARB 0x38 | |
48 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK 0x40 | |
49 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48 | |
50 | #define MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK 0x50 | |
51 | #define MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58 | |
52 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0 | |
53 | #define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8 | |
54 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0 | |
55 | #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 | |
56 | #define MV64XXX_I2C_STATUS_NO_STATUS 0xf8 | |
57 | ||
58 | /* Driver states */ | |
59 | enum { | |
60 | MV64XXX_I2C_STATE_INVALID, | |
61 | MV64XXX_I2C_STATE_IDLE, | |
62 | MV64XXX_I2C_STATE_WAITING_FOR_START_COND, | |
eda6bee6 | 63 | MV64XXX_I2C_STATE_WAITING_FOR_RESTART, |
1da177e4 LT |
64 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, |
65 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, | |
66 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, | |
67 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, | |
1da177e4 LT |
68 | }; |
69 | ||
70 | /* Driver actions */ | |
71 | enum { | |
72 | MV64XXX_I2C_ACTION_INVALID, | |
73 | MV64XXX_I2C_ACTION_CONTINUE, | |
74 | MV64XXX_I2C_ACTION_SEND_START, | |
eda6bee6 | 75 | MV64XXX_I2C_ACTION_SEND_RESTART, |
1da177e4 LT |
76 | MV64XXX_I2C_ACTION_SEND_ADDR_1, |
77 | MV64XXX_I2C_ACTION_SEND_ADDR_2, | |
78 | MV64XXX_I2C_ACTION_SEND_DATA, | |
79 | MV64XXX_I2C_ACTION_RCV_DATA, | |
80 | MV64XXX_I2C_ACTION_RCV_DATA_STOP, | |
81 | MV64XXX_I2C_ACTION_SEND_STOP, | |
82 | }; | |
83 | ||
004e8ed7 MR |
84 | struct mv64xxx_i2c_regs { |
85 | u8 addr; | |
86 | u8 ext_addr; | |
87 | u8 data; | |
88 | u8 control; | |
89 | u8 status; | |
90 | u8 clock; | |
91 | u8 soft_reset; | |
92 | }; | |
93 | ||
1da177e4 | 94 | struct mv64xxx_i2c_data { |
4243fa0b RK |
95 | struct i2c_msg *msgs; |
96 | int num_msgs; | |
1da177e4 LT |
97 | int irq; |
98 | u32 state; | |
99 | u32 action; | |
e91c021c | 100 | u32 aborting; |
1da177e4 LT |
101 | u32 cntl_bits; |
102 | void __iomem *reg_base; | |
004e8ed7 | 103 | struct mv64xxx_i2c_regs reg_offsets; |
1da177e4 LT |
104 | u32 addr1; |
105 | u32 addr2; | |
106 | u32 bytes_left; | |
107 | u32 byte_posn; | |
eda6bee6 | 108 | u32 send_stop; |
1da177e4 LT |
109 | u32 block; |
110 | int rc; | |
111 | u32 freq_m; | |
112 | u32 freq_n; | |
b61d1575 AL |
113 | #if defined(CONFIG_HAVE_CLK) |
114 | struct clk *clk; | |
115 | #endif | |
1da177e4 LT |
116 | wait_queue_head_t waitq; |
117 | spinlock_t lock; | |
118 | struct i2c_msg *msg; | |
119 | struct i2c_adapter adapter; | |
120 | }; | |
121 | ||
004e8ed7 MR |
122 | static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { |
123 | .addr = 0x00, | |
124 | .ext_addr = 0x10, | |
125 | .data = 0x04, | |
126 | .control = 0x08, | |
127 | .status = 0x0c, | |
128 | .clock = 0x0c, | |
129 | .soft_reset = 0x1c, | |
130 | }; | |
131 | ||
3d66ac7d MR |
132 | static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_sun4i = { |
133 | .addr = 0x00, | |
134 | .ext_addr = 0x04, | |
135 | .data = 0x08, | |
136 | .control = 0x0c, | |
137 | .status = 0x10, | |
138 | .clock = 0x14, | |
139 | .soft_reset = 0x18, | |
140 | }; | |
141 | ||
3420afbc RK |
142 | static void |
143 | mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, | |
144 | struct i2c_msg *msg) | |
145 | { | |
146 | u32 dir = 0; | |
147 | ||
148 | drv_data->msg = msg; | |
149 | drv_data->byte_posn = 0; | |
150 | drv_data->bytes_left = msg->len; | |
151 | drv_data->aborting = 0; | |
152 | drv_data->rc = 0; | |
153 | drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | | |
154 | MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; | |
155 | ||
156 | if (msg->flags & I2C_M_RD) | |
157 | dir = 1; | |
158 | ||
159 | if (msg->flags & I2C_M_TEN) { | |
160 | drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; | |
161 | drv_data->addr2 = (u32)msg->addr & 0xff; | |
162 | } else { | |
683e69b8 | 163 | drv_data->addr1 = MV64XXX_I2C_ADDR_ADDR((u32)msg->addr) | dir; |
3420afbc RK |
164 | drv_data->addr2 = 0; |
165 | } | |
166 | } | |
167 | ||
1da177e4 LT |
168 | /* |
169 | ***************************************************************************** | |
170 | * | |
171 | * Finite State Machine & Interrupt Routines | |
172 | * | |
173 | ***************************************************************************** | |
174 | */ | |
a07ad1cc DF |
175 | |
176 | /* Reset hardware and initialize FSM */ | |
177 | static void | |
178 | mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) | |
179 | { | |
004e8ed7 | 180 | writel(0, drv_data->reg_base + drv_data->reg_offsets.soft_reset); |
683e69b8 | 181 | writel(MV64XXX_I2C_BAUD_DIV_M(drv_data->freq_m) | MV64XXX_I2C_BAUD_DIV_N(drv_data->freq_n), |
004e8ed7 MR |
182 | drv_data->reg_base + drv_data->reg_offsets.clock); |
183 | writel(0, drv_data->reg_base + drv_data->reg_offsets.addr); | |
184 | writel(0, drv_data->reg_base + drv_data->reg_offsets.ext_addr); | |
a07ad1cc | 185 | writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, |
004e8ed7 | 186 | drv_data->reg_base + drv_data->reg_offsets.control); |
a07ad1cc DF |
187 | drv_data->state = MV64XXX_I2C_STATE_IDLE; |
188 | } | |
189 | ||
1da177e4 LT |
190 | static void |
191 | mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |
192 | { | |
193 | /* | |
194 | * If state is idle, then this is likely the remnants of an old | |
195 | * operation that driver has given up on or the user has killed. | |
196 | * If so, issue the stop condition and go to idle. | |
197 | */ | |
198 | if (drv_data->state == MV64XXX_I2C_STATE_IDLE) { | |
199 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | |
200 | return; | |
201 | } | |
202 | ||
1da177e4 LT |
203 | /* The status from the ctlr [mostly] tells us what to do next */ |
204 | switch (status) { | |
205 | /* Start condition interrupt */ | |
206 | case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */ | |
207 | case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */ | |
208 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; | |
209 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; | |
210 | break; | |
211 | ||
212 | /* Performing a write */ | |
213 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */ | |
214 | if (drv_data->msg->flags & I2C_M_TEN) { | |
215 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; | |
216 | drv_data->state = | |
217 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; | |
218 | break; | |
219 | } | |
220 | /* FALLTHRU */ | |
221 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ | |
222 | case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ | |
e91c021c MG |
223 | if ((drv_data->bytes_left == 0) |
224 | || (drv_data->aborting | |
225 | && (drv_data->byte_posn != 0))) { | |
4243fa0b | 226 | if (drv_data->send_stop || drv_data->aborting) { |
eda6bee6 RG |
227 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; |
228 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | |
229 | } else { | |
230 | drv_data->action = | |
231 | MV64XXX_I2C_ACTION_SEND_RESTART; | |
232 | drv_data->state = | |
233 | MV64XXX_I2C_STATE_WAITING_FOR_RESTART; | |
234 | } | |
e91c021c | 235 | } else { |
1da177e4 LT |
236 | drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; |
237 | drv_data->state = | |
238 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; | |
239 | drv_data->bytes_left--; | |
1da177e4 LT |
240 | } |
241 | break; | |
242 | ||
243 | /* Performing a read */ | |
244 | case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */ | |
245 | if (drv_data->msg->flags & I2C_M_TEN) { | |
246 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; | |
247 | drv_data->state = | |
248 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; | |
249 | break; | |
250 | } | |
251 | /* FALLTHRU */ | |
252 | case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */ | |
253 | if (drv_data->bytes_left == 0) { | |
254 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | |
255 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | |
256 | break; | |
257 | } | |
258 | /* FALLTHRU */ | |
259 | case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */ | |
260 | if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK) | |
261 | drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; | |
262 | else { | |
263 | drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA; | |
264 | drv_data->bytes_left--; | |
265 | } | |
266 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; | |
267 | ||
e91c021c | 268 | if ((drv_data->bytes_left == 1) || drv_data->aborting) |
1da177e4 LT |
269 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; |
270 | break; | |
271 | ||
272 | case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */ | |
273 | drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP; | |
274 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | |
275 | break; | |
276 | ||
277 | case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */ | |
278 | case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */ | |
279 | case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */ | |
280 | /* Doesn't seem to be a device at other end */ | |
281 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | |
282 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | |
6faa3535 | 283 | drv_data->rc = -ENXIO; |
1da177e4 LT |
284 | break; |
285 | ||
286 | default: | |
287 | dev_err(&drv_data->adapter.dev, | |
288 | "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " | |
289 | "status: 0x%x, addr: 0x%x, flags: 0x%x\n", | |
290 | drv_data->state, status, drv_data->msg->addr, | |
291 | drv_data->msg->flags); | |
292 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | |
a07ad1cc | 293 | mv64xxx_i2c_hw_init(drv_data); |
1da177e4 LT |
294 | drv_data->rc = -EIO; |
295 | } | |
296 | } | |
297 | ||
298 | static void | |
299 | mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) | |
300 | { | |
301 | switch(drv_data->action) { | |
eda6bee6 | 302 | case MV64XXX_I2C_ACTION_SEND_RESTART: |
4243fa0b RK |
303 | /* We should only get here if we have further messages */ |
304 | BUG_ON(drv_data->num_msgs == 0); | |
305 | ||
eda6bee6 | 306 | drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; |
eda6bee6 | 307 | writel(drv_data->cntl_bits, |
004e8ed7 | 308 | drv_data->reg_base + drv_data->reg_offsets.control); |
4243fa0b RK |
309 | |
310 | drv_data->msgs++; | |
311 | drv_data->num_msgs--; | |
312 | ||
313 | /* Setup for the next message */ | |
314 | mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); | |
315 | ||
316 | /* | |
317 | * We're never at the start of the message here, and by this | |
318 | * time it's already too late to do any protocol mangling. | |
319 | * Thankfully, do not advertise support for that feature. | |
320 | */ | |
321 | drv_data->send_stop = drv_data->num_msgs == 1; | |
eda6bee6 RG |
322 | break; |
323 | ||
1da177e4 LT |
324 | case MV64XXX_I2C_ACTION_CONTINUE: |
325 | writel(drv_data->cntl_bits, | |
004e8ed7 | 326 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 LT |
327 | break; |
328 | ||
329 | case MV64XXX_I2C_ACTION_SEND_START: | |
330 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, | |
004e8ed7 | 331 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 LT |
332 | break; |
333 | ||
334 | case MV64XXX_I2C_ACTION_SEND_ADDR_1: | |
335 | writel(drv_data->addr1, | |
004e8ed7 | 336 | drv_data->reg_base + drv_data->reg_offsets.data); |
1da177e4 | 337 | writel(drv_data->cntl_bits, |
004e8ed7 | 338 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 LT |
339 | break; |
340 | ||
341 | case MV64XXX_I2C_ACTION_SEND_ADDR_2: | |
342 | writel(drv_data->addr2, | |
004e8ed7 | 343 | drv_data->reg_base + drv_data->reg_offsets.data); |
1da177e4 | 344 | writel(drv_data->cntl_bits, |
004e8ed7 | 345 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 LT |
346 | break; |
347 | ||
348 | case MV64XXX_I2C_ACTION_SEND_DATA: | |
349 | writel(drv_data->msg->buf[drv_data->byte_posn++], | |
004e8ed7 | 350 | drv_data->reg_base + drv_data->reg_offsets.data); |
1da177e4 | 351 | writel(drv_data->cntl_bits, |
004e8ed7 | 352 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 LT |
353 | break; |
354 | ||
355 | case MV64XXX_I2C_ACTION_RCV_DATA: | |
356 | drv_data->msg->buf[drv_data->byte_posn++] = | |
004e8ed7 | 357 | readl(drv_data->reg_base + drv_data->reg_offsets.data); |
1da177e4 | 358 | writel(drv_data->cntl_bits, |
004e8ed7 | 359 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 LT |
360 | break; |
361 | ||
362 | case MV64XXX_I2C_ACTION_RCV_DATA_STOP: | |
363 | drv_data->msg->buf[drv_data->byte_posn++] = | |
004e8ed7 | 364 | readl(drv_data->reg_base + drv_data->reg_offsets.data); |
1da177e4 LT |
365 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; |
366 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, | |
004e8ed7 | 367 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 | 368 | drv_data->block = 0; |
d295a86e | 369 | wake_up(&drv_data->waitq); |
1da177e4 LT |
370 | break; |
371 | ||
372 | case MV64XXX_I2C_ACTION_INVALID: | |
373 | default: | |
374 | dev_err(&drv_data->adapter.dev, | |
375 | "mv64xxx_i2c_do_action: Invalid action: %d\n", | |
376 | drv_data->action); | |
377 | drv_data->rc = -EIO; | |
378 | /* FALLTHRU */ | |
379 | case MV64XXX_I2C_ACTION_SEND_STOP: | |
380 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; | |
381 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, | |
004e8ed7 | 382 | drv_data->reg_base + drv_data->reg_offsets.control); |
1da177e4 | 383 | drv_data->block = 0; |
d295a86e | 384 | wake_up(&drv_data->waitq); |
1da177e4 LT |
385 | break; |
386 | } | |
387 | } | |
388 | ||
b0999cc5 | 389 | static irqreturn_t |
7d12e780 | 390 | mv64xxx_i2c_intr(int irq, void *dev_id) |
1da177e4 LT |
391 | { |
392 | struct mv64xxx_i2c_data *drv_data = dev_id; | |
393 | unsigned long flags; | |
394 | u32 status; | |
b0999cc5 | 395 | irqreturn_t rc = IRQ_NONE; |
1da177e4 LT |
396 | |
397 | spin_lock_irqsave(&drv_data->lock, flags); | |
004e8ed7 | 398 | while (readl(drv_data->reg_base + drv_data->reg_offsets.control) & |
1da177e4 | 399 | MV64XXX_I2C_REG_CONTROL_IFLG) { |
004e8ed7 | 400 | status = readl(drv_data->reg_base + drv_data->reg_offsets.status); |
1da177e4 LT |
401 | mv64xxx_i2c_fsm(drv_data, status); |
402 | mv64xxx_i2c_do_action(drv_data); | |
403 | rc = IRQ_HANDLED; | |
404 | } | |
405 | spin_unlock_irqrestore(&drv_data->lock, flags); | |
406 | ||
407 | return rc; | |
408 | } | |
409 | ||
410 | /* | |
411 | ***************************************************************************** | |
412 | * | |
413 | * I2C Msg Execution Routines | |
414 | * | |
415 | ***************************************************************************** | |
416 | */ | |
1da177e4 LT |
417 | static void |
418 | mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) | |
419 | { | |
420 | long time_left; | |
421 | unsigned long flags; | |
422 | char abort = 0; | |
423 | ||
d295a86e | 424 | time_left = wait_event_timeout(drv_data->waitq, |
8a52c6b4 | 425 | !drv_data->block, drv_data->adapter.timeout); |
1da177e4 LT |
426 | |
427 | spin_lock_irqsave(&drv_data->lock, flags); | |
428 | if (!time_left) { /* Timed out */ | |
429 | drv_data->rc = -ETIMEDOUT; | |
430 | abort = 1; | |
431 | } else if (time_left < 0) { /* Interrupted/Error */ | |
432 | drv_data->rc = time_left; /* errno value */ | |
433 | abort = 1; | |
434 | } | |
435 | ||
436 | if (abort && drv_data->block) { | |
e91c021c | 437 | drv_data->aborting = 1; |
1da177e4 LT |
438 | spin_unlock_irqrestore(&drv_data->lock, flags); |
439 | ||
440 | time_left = wait_event_timeout(drv_data->waitq, | |
8a52c6b4 | 441 | !drv_data->block, drv_data->adapter.timeout); |
1da177e4 | 442 | |
e91c021c | 443 | if ((time_left <= 0) && drv_data->block) { |
1da177e4 LT |
444 | drv_data->state = MV64XXX_I2C_STATE_IDLE; |
445 | dev_err(&drv_data->adapter.dev, | |
e91c021c MG |
446 | "mv64xxx: I2C bus locked, block: %d, " |
447 | "time_left: %d\n", drv_data->block, | |
448 | (int)time_left); | |
a07ad1cc | 449 | mv64xxx_i2c_hw_init(drv_data); |
1da177e4 LT |
450 | } |
451 | } else | |
452 | spin_unlock_irqrestore(&drv_data->lock, flags); | |
453 | } | |
454 | ||
455 | static int | |
eda6bee6 | 456 | mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, |
4243fa0b | 457 | int is_last) |
1da177e4 LT |
458 | { |
459 | unsigned long flags; | |
460 | ||
461 | spin_lock_irqsave(&drv_data->lock, flags); | |
462 | mv64xxx_i2c_prepare_for_io(drv_data, msg); | |
463 | ||
4243fa0b RK |
464 | drv_data->action = MV64XXX_I2C_ACTION_SEND_START; |
465 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; | |
1da177e4 | 466 | |
eda6bee6 | 467 | drv_data->send_stop = is_last; |
1da177e4 LT |
468 | drv_data->block = 1; |
469 | mv64xxx_i2c_do_action(drv_data); | |
470 | spin_unlock_irqrestore(&drv_data->lock, flags); | |
471 | ||
472 | mv64xxx_i2c_wait_for_completion(drv_data); | |
473 | return drv_data->rc; | |
474 | } | |
475 | ||
476 | /* | |
477 | ***************************************************************************** | |
478 | * | |
479 | * I2C Core Support Routines (Interface to higher level I2C code) | |
480 | * | |
481 | ***************************************************************************** | |
482 | */ | |
483 | static u32 | |
484 | mv64xxx_i2c_functionality(struct i2c_adapter *adap) | |
485 | { | |
486 | return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; | |
487 | } | |
488 | ||
489 | static int | |
490 | mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |
491 | { | |
492 | struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); | |
4243fa0b | 493 | int rc, ret = num; |
1da177e4 | 494 | |
4243fa0b RK |
495 | BUG_ON(drv_data->msgs != NULL); |
496 | drv_data->msgs = msgs; | |
497 | drv_data->num_msgs = num; | |
498 | ||
499 | rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1); | |
500 | if (rc < 0) | |
501 | ret = rc; | |
502 | ||
503 | drv_data->num_msgs = 0; | |
504 | drv_data->msgs = NULL; | |
1da177e4 | 505 | |
4243fa0b | 506 | return ret; |
1da177e4 LT |
507 | } |
508 | ||
8f9082c5 | 509 | static const struct i2c_algorithm mv64xxx_i2c_algo = { |
1da177e4 LT |
510 | .master_xfer = mv64xxx_i2c_xfer, |
511 | .functionality = mv64xxx_i2c_functionality, | |
512 | }; | |
513 | ||
514 | /* | |
515 | ***************************************************************************** | |
516 | * | |
517 | * Driver Interface & Early Init Routines | |
518 | * | |
519 | ***************************************************************************** | |
520 | */ | |
004e8ed7 | 521 | static const struct of_device_id mv64xxx_i2c_of_match_table[] = { |
3d66ac7d | 522 | { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i}, |
004e8ed7 MR |
523 | { .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, |
524 | {} | |
525 | }; | |
526 | MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); | |
527 | ||
b61d1575 | 528 | #ifdef CONFIG_OF |
0b255e92 | 529 | static int |
b61d1575 AL |
530 | mv64xxx_calc_freq(const int tclk, const int n, const int m) |
531 | { | |
532 | return tclk / (10 * (m + 1) * (2 << n)); | |
533 | } | |
534 | ||
0b255e92 | 535 | static bool |
b61d1575 AL |
536 | mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, |
537 | u32 *best_m) | |
538 | { | |
539 | int freq, delta, best_delta = INT_MAX; | |
540 | int m, n; | |
541 | ||
542 | for (n = 0; n <= 7; n++) | |
543 | for (m = 0; m <= 15; m++) { | |
544 | freq = mv64xxx_calc_freq(tclk, n, m); | |
545 | delta = req_freq - freq; | |
546 | if (delta >= 0 && delta < best_delta) { | |
547 | *best_m = m; | |
548 | *best_n = n; | |
549 | best_delta = delta; | |
550 | } | |
551 | if (best_delta == 0) | |
552 | return true; | |
553 | } | |
554 | if (best_delta == INT_MAX) | |
555 | return false; | |
556 | return true; | |
557 | } | |
558 | ||
0b255e92 | 559 | static int |
b61d1575 | 560 | mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, |
004e8ed7 | 561 | struct device *dev) |
b61d1575 | 562 | { |
004e8ed7 MR |
563 | const struct of_device_id *device; |
564 | struct device_node *np = dev->of_node; | |
b61d1575 AL |
565 | u32 bus_freq, tclk; |
566 | int rc = 0; | |
567 | ||
568 | /* CLK is mandatory when using DT to describe the i2c bus. We | |
569 | * need to know tclk in order to calculate bus clock | |
570 | * factors. | |
571 | */ | |
572 | #if !defined(CONFIG_HAVE_CLK) | |
573 | /* Have OF but no CLK */ | |
574 | return -ENODEV; | |
575 | #else | |
576 | if (IS_ERR(drv_data->clk)) { | |
577 | rc = -ENODEV; | |
578 | goto out; | |
579 | } | |
580 | tclk = clk_get_rate(drv_data->clk); | |
4c730a06 GC |
581 | |
582 | rc = of_property_read_u32(np, "clock-frequency", &bus_freq); | |
583 | if (rc) | |
584 | bus_freq = 100000; /* 100kHz by default */ | |
585 | ||
b61d1575 AL |
586 | if (!mv64xxx_find_baud_factors(bus_freq, tclk, |
587 | &drv_data->freq_n, &drv_data->freq_m)) { | |
588 | rc = -EINVAL; | |
589 | goto out; | |
590 | } | |
591 | drv_data->irq = irq_of_parse_and_map(np, 0); | |
592 | ||
593 | /* Its not yet defined how timeouts will be specified in device tree. | |
594 | * So hard code the value to 1 second. | |
595 | */ | |
596 | drv_data->adapter.timeout = HZ; | |
004e8ed7 MR |
597 | |
598 | device = of_match_device(mv64xxx_i2c_of_match_table, dev); | |
599 | if (!device) | |
600 | return -ENODEV; | |
601 | ||
602 | memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets)); | |
603 | ||
b61d1575 AL |
604 | out: |
605 | return rc; | |
606 | #endif | |
607 | } | |
608 | #else /* CONFIG_OF */ | |
0b255e92 | 609 | static int |
b61d1575 | 610 | mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, |
004e8ed7 | 611 | struct device *dev) |
b61d1575 AL |
612 | { |
613 | return -ENODEV; | |
614 | } | |
615 | #endif /* CONFIG_OF */ | |
616 | ||
0b255e92 | 617 | static int |
3ae5eaec | 618 | mv64xxx_i2c_probe(struct platform_device *pd) |
1da177e4 | 619 | { |
1da177e4 | 620 | struct mv64xxx_i2c_data *drv_data; |
3ae5eaec | 621 | struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; |
16874b07 | 622 | struct resource *r; |
1da177e4 LT |
623 | int rc; |
624 | ||
b61d1575 | 625 | if ((!pdata && !pd->dev.of_node)) |
1da177e4 LT |
626 | return -ENODEV; |
627 | ||
2c911103 RK |
628 | drv_data = devm_kzalloc(&pd->dev, sizeof(struct mv64xxx_i2c_data), |
629 | GFP_KERNEL); | |
1da177e4 LT |
630 | if (!drv_data) |
631 | return -ENOMEM; | |
632 | ||
16874b07 RK |
633 | r = platform_get_resource(pd, IORESOURCE_MEM, 0); |
634 | drv_data->reg_base = devm_ioremap_resource(&pd->dev, r); | |
2c911103 RK |
635 | if (IS_ERR(drv_data->reg_base)) |
636 | return PTR_ERR(drv_data->reg_base); | |
1da177e4 | 637 | |
e91c021c | 638 | strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", |
2096b956 | 639 | sizeof(drv_data->adapter.name)); |
1da177e4 LT |
640 | |
641 | init_waitqueue_head(&drv_data->waitq); | |
642 | spin_lock_init(&drv_data->lock); | |
643 | ||
b61d1575 AL |
644 | #if defined(CONFIG_HAVE_CLK) |
645 | /* Not all platforms have a clk */ | |
4c5c95f5 | 646 | drv_data->clk = devm_clk_get(&pd->dev, NULL); |
b61d1575 AL |
647 | if (!IS_ERR(drv_data->clk)) { |
648 | clk_prepare(drv_data->clk); | |
649 | clk_enable(drv_data->clk); | |
650 | } | |
651 | #endif | |
652 | if (pdata) { | |
653 | drv_data->freq_m = pdata->freq_m; | |
654 | drv_data->freq_n = pdata->freq_n; | |
655 | drv_data->irq = platform_get_irq(pd, 0); | |
656 | drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); | |
004e8ed7 | 657 | memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets)); |
b61d1575 | 658 | } else if (pd->dev.of_node) { |
004e8ed7 | 659 | rc = mv64xxx_of_config(drv_data, &pd->dev); |
b61d1575 | 660 | if (rc) |
2c911103 | 661 | goto exit_clk; |
b61d1575 | 662 | } |
48944738 DV |
663 | if (drv_data->irq < 0) { |
664 | rc = -ENXIO; | |
2c911103 | 665 | goto exit_clk; |
48944738 | 666 | } |
b61d1575 | 667 | |
12a917f6 | 668 | drv_data->adapter.dev.parent = &pd->dev; |
1da177e4 LT |
669 | drv_data->adapter.algo = &mv64xxx_i2c_algo; |
670 | drv_data->adapter.owner = THIS_MODULE; | |
3401b2ff | 671 | drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; |
65b22ad9 | 672 | drv_data->adapter.nr = pd->id; |
b61d1575 | 673 | drv_data->adapter.dev.of_node = pd->dev.of_node; |
3ae5eaec | 674 | platform_set_drvdata(pd, drv_data); |
1da177e4 LT |
675 | i2c_set_adapdata(&drv_data->adapter, drv_data); |
676 | ||
3269bb63 MB |
677 | mv64xxx_i2c_hw_init(drv_data); |
678 | ||
0c195afb RK |
679 | rc = request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, |
680 | MV64XXX_I2C_CTLR_NAME, drv_data); | |
681 | if (rc) { | |
dfded4ae | 682 | dev_err(&drv_data->adapter.dev, |
0c195afb RK |
683 | "mv64xxx: Can't register intr handler irq%d: %d\n", |
684 | drv_data->irq, rc); | |
2c911103 | 685 | goto exit_clk; |
65b22ad9 | 686 | } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { |
dfded4ae MG |
687 | dev_err(&drv_data->adapter.dev, |
688 | "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); | |
1da177e4 LT |
689 | goto exit_free_irq; |
690 | } | |
691 | ||
b61d1575 AL |
692 | of_i2c_register_devices(&drv_data->adapter); |
693 | ||
1da177e4 LT |
694 | return 0; |
695 | ||
2c911103 RK |
696 | exit_free_irq: |
697 | free_irq(drv_data->irq, drv_data); | |
698 | exit_clk: | |
b61d1575 AL |
699 | #if defined(CONFIG_HAVE_CLK) |
700 | /* Not all platforms have a clk */ | |
701 | if (!IS_ERR(drv_data->clk)) { | |
702 | clk_disable(drv_data->clk); | |
703 | clk_unprepare(drv_data->clk); | |
704 | } | |
705 | #endif | |
1da177e4 LT |
706 | return rc; |
707 | } | |
708 | ||
0b255e92 | 709 | static int |
3ae5eaec | 710 | mv64xxx_i2c_remove(struct platform_device *dev) |
1da177e4 | 711 | { |
3ae5eaec | 712 | struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev); |
1da177e4 | 713 | |
bf51a8c5 | 714 | i2c_del_adapter(&drv_data->adapter); |
1da177e4 | 715 | free_irq(drv_data->irq, drv_data); |
b61d1575 AL |
716 | #if defined(CONFIG_HAVE_CLK) |
717 | /* Not all platforms have a clk */ | |
718 | if (!IS_ERR(drv_data->clk)) { | |
719 | clk_disable(drv_data->clk); | |
720 | clk_unprepare(drv_data->clk); | |
721 | } | |
722 | #endif | |
1da177e4 | 723 | |
bf51a8c5 | 724 | return 0; |
1da177e4 LT |
725 | } |
726 | ||
3ae5eaec | 727 | static struct platform_driver mv64xxx_i2c_driver = { |
1da177e4 | 728 | .probe = mv64xxx_i2c_probe, |
0b255e92 | 729 | .remove = mv64xxx_i2c_remove, |
3ae5eaec RK |
730 | .driver = { |
731 | .owner = THIS_MODULE, | |
732 | .name = MV64XXX_I2C_CTLR_NAME, | |
b61d1575 | 733 | .of_match_table = of_match_ptr(mv64xxx_i2c_of_match_table), |
3ae5eaec | 734 | }, |
1da177e4 LT |
735 | }; |
736 | ||
a3664b51 | 737 | module_platform_driver(mv64xxx_i2c_driver); |
1da177e4 LT |
738 | |
739 | MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>"); | |
740 | MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver"); | |
741 | MODULE_LICENSE("GPL"); |