diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-mv64xxx.c')
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 321 |
1 files changed, 161 insertions, 160 deletions
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 1a3abd6a0bfc..b1f42bf40963 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
@@ -19,19 +19,15 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_device.h> | ||
22 | #include <linux/of_irq.h> | 23 | #include <linux/of_irq.h> |
23 | #include <linux/of_i2c.h> | 24 | #include <linux/of_i2c.h> |
24 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
25 | #include <linux/err.h> | 26 | #include <linux/err.h> |
26 | 27 | ||
27 | /* Register defines */ | 28 | #define MV64XXX_I2C_ADDR_ADDR(val) ((val & 0x7f) << 1) |
28 | #define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 | 29 | #define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7) |
29 | #define MV64XXX_I2C_REG_DATA 0x04 | 30 | #define MV64XXX_I2C_BAUD_DIV_M(val) ((val & 0xf) << 3) |
30 | #define MV64XXX_I2C_REG_CONTROL 0x08 | ||
31 | #define MV64XXX_I2C_REG_STATUS 0x0c | ||
32 | #define MV64XXX_I2C_REG_BAUD 0x0c | ||
33 | #define MV64XXX_I2C_REG_EXT_SLAVE_ADDR 0x10 | ||
34 | #define MV64XXX_I2C_REG_SOFT_RESET 0x1c | ||
35 | 31 | ||
36 | #define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 | 32 | #define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 |
37 | #define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 | 33 | #define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 |
@@ -85,15 +81,26 @@ enum { | |||
85 | MV64XXX_I2C_ACTION_SEND_STOP, | 81 | MV64XXX_I2C_ACTION_SEND_STOP, |
86 | }; | 82 | }; |
87 | 83 | ||
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 | |||
88 | struct mv64xxx_i2c_data { | 94 | struct mv64xxx_i2c_data { |
95 | struct i2c_msg *msgs; | ||
96 | int num_msgs; | ||
89 | int irq; | 97 | int irq; |
90 | u32 state; | 98 | u32 state; |
91 | u32 action; | 99 | u32 action; |
92 | u32 aborting; | 100 | u32 aborting; |
93 | u32 cntl_bits; | 101 | u32 cntl_bits; |
94 | void __iomem *reg_base; | 102 | void __iomem *reg_base; |
95 | u32 reg_base_p; | 103 | struct mv64xxx_i2c_regs reg_offsets; |
96 | u32 reg_size; | ||
97 | u32 addr1; | 104 | u32 addr1; |
98 | u32 addr2; | 105 | u32 addr2; |
99 | u32 bytes_left; | 106 | u32 bytes_left; |
@@ -112,6 +119,52 @@ struct mv64xxx_i2c_data { | |||
112 | struct i2c_adapter adapter; | 119 | struct i2c_adapter adapter; |
113 | }; | 120 | }; |
114 | 121 | ||
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 | |||
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 | |||
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 { | ||
163 | drv_data->addr1 = MV64XXX_I2C_ADDR_ADDR((u32)msg->addr) | dir; | ||
164 | drv_data->addr2 = 0; | ||
165 | } | ||
166 | } | ||
167 | |||
115 | /* | 168 | /* |
116 | ***************************************************************************** | 169 | ***************************************************************************** |
117 | * | 170 | * |
@@ -124,13 +177,13 @@ struct mv64xxx_i2c_data { | |||
124 | static void | 177 | static void |
125 | mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) | 178 | mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) |
126 | { | 179 | { |
127 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET); | 180 | writel(0, drv_data->reg_base + drv_data->reg_offsets.soft_reset); |
128 | writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)), | 181 | writel(MV64XXX_I2C_BAUD_DIV_M(drv_data->freq_m) | MV64XXX_I2C_BAUD_DIV_N(drv_data->freq_n), |
129 | drv_data->reg_base + MV64XXX_I2C_REG_BAUD); | 182 | drv_data->reg_base + drv_data->reg_offsets.clock); |
130 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR); | 183 | writel(0, drv_data->reg_base + drv_data->reg_offsets.addr); |
131 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); | 184 | writel(0, drv_data->reg_base + drv_data->reg_offsets.ext_addr); |
132 | writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, | 185 | writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, |
133 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 186 | drv_data->reg_base + drv_data->reg_offsets.control); |
134 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | 187 | drv_data->state = MV64XXX_I2C_STATE_IDLE; |
135 | } | 188 | } |
136 | 189 | ||
@@ -170,7 +223,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |||
170 | if ((drv_data->bytes_left == 0) | 223 | if ((drv_data->bytes_left == 0) |
171 | || (drv_data->aborting | 224 | || (drv_data->aborting |
172 | && (drv_data->byte_posn != 0))) { | 225 | && (drv_data->byte_posn != 0))) { |
173 | if (drv_data->send_stop) { | 226 | if (drv_data->send_stop || drv_data->aborting) { |
174 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | 227 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; |
175 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | 228 | drv_data->state = MV64XXX_I2C_STATE_IDLE; |
176 | } else { | 229 | } else { |
@@ -227,7 +280,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |||
227 | /* Doesn't seem to be a device at other end */ | 280 | /* Doesn't seem to be a device at other end */ |
228 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; | 281 | drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; |
229 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | 282 | drv_data->state = MV64XXX_I2C_STATE_IDLE; |
230 | drv_data->rc = -ENODEV; | 283 | drv_data->rc = -ENXIO; |
231 | break; | 284 | break; |
232 | 285 | ||
233 | default: | 286 | default: |
@@ -247,58 +300,71 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) | |||
247 | { | 300 | { |
248 | switch(drv_data->action) { | 301 | switch(drv_data->action) { |
249 | case MV64XXX_I2C_ACTION_SEND_RESTART: | 302 | case MV64XXX_I2C_ACTION_SEND_RESTART: |
303 | /* We should only get here if we have further messages */ | ||
304 | BUG_ON(drv_data->num_msgs == 0); | ||
305 | |||
250 | drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; | 306 | drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; |
251 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; | ||
252 | writel(drv_data->cntl_bits, | 307 | writel(drv_data->cntl_bits, |
253 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 308 | drv_data->reg_base + drv_data->reg_offsets.control); |
254 | drv_data->block = 0; | 309 | |
255 | wake_up(&drv_data->waitq); | 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; | ||
256 | break; | 322 | break; |
257 | 323 | ||
258 | case MV64XXX_I2C_ACTION_CONTINUE: | 324 | case MV64XXX_I2C_ACTION_CONTINUE: |
259 | writel(drv_data->cntl_bits, | 325 | writel(drv_data->cntl_bits, |
260 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 326 | drv_data->reg_base + drv_data->reg_offsets.control); |
261 | break; | 327 | break; |
262 | 328 | ||
263 | case MV64XXX_I2C_ACTION_SEND_START: | 329 | case MV64XXX_I2C_ACTION_SEND_START: |
264 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, | 330 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, |
265 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 331 | drv_data->reg_base + drv_data->reg_offsets.control); |
266 | break; | 332 | break; |
267 | 333 | ||
268 | case MV64XXX_I2C_ACTION_SEND_ADDR_1: | 334 | case MV64XXX_I2C_ACTION_SEND_ADDR_1: |
269 | writel(drv_data->addr1, | 335 | writel(drv_data->addr1, |
270 | drv_data->reg_base + MV64XXX_I2C_REG_DATA); | 336 | drv_data->reg_base + drv_data->reg_offsets.data); |
271 | writel(drv_data->cntl_bits, | 337 | writel(drv_data->cntl_bits, |
272 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 338 | drv_data->reg_base + drv_data->reg_offsets.control); |
273 | break; | 339 | break; |
274 | 340 | ||
275 | case MV64XXX_I2C_ACTION_SEND_ADDR_2: | 341 | case MV64XXX_I2C_ACTION_SEND_ADDR_2: |
276 | writel(drv_data->addr2, | 342 | writel(drv_data->addr2, |
277 | drv_data->reg_base + MV64XXX_I2C_REG_DATA); | 343 | drv_data->reg_base + drv_data->reg_offsets.data); |
278 | writel(drv_data->cntl_bits, | 344 | writel(drv_data->cntl_bits, |
279 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 345 | drv_data->reg_base + drv_data->reg_offsets.control); |
280 | break; | 346 | break; |
281 | 347 | ||
282 | case MV64XXX_I2C_ACTION_SEND_DATA: | 348 | case MV64XXX_I2C_ACTION_SEND_DATA: |
283 | writel(drv_data->msg->buf[drv_data->byte_posn++], | 349 | writel(drv_data->msg->buf[drv_data->byte_posn++], |
284 | drv_data->reg_base + MV64XXX_I2C_REG_DATA); | 350 | drv_data->reg_base + drv_data->reg_offsets.data); |
285 | writel(drv_data->cntl_bits, | 351 | writel(drv_data->cntl_bits, |
286 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 352 | drv_data->reg_base + drv_data->reg_offsets.control); |
287 | break; | 353 | break; |
288 | 354 | ||
289 | case MV64XXX_I2C_ACTION_RCV_DATA: | 355 | case MV64XXX_I2C_ACTION_RCV_DATA: |
290 | drv_data->msg->buf[drv_data->byte_posn++] = | 356 | drv_data->msg->buf[drv_data->byte_posn++] = |
291 | readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); | 357 | readl(drv_data->reg_base + drv_data->reg_offsets.data); |
292 | writel(drv_data->cntl_bits, | 358 | writel(drv_data->cntl_bits, |
293 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 359 | drv_data->reg_base + drv_data->reg_offsets.control); |
294 | break; | 360 | break; |
295 | 361 | ||
296 | case MV64XXX_I2C_ACTION_RCV_DATA_STOP: | 362 | case MV64XXX_I2C_ACTION_RCV_DATA_STOP: |
297 | drv_data->msg->buf[drv_data->byte_posn++] = | 363 | drv_data->msg->buf[drv_data->byte_posn++] = |
298 | readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); | 364 | readl(drv_data->reg_base + drv_data->reg_offsets.data); |
299 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; | 365 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; |
300 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, | 366 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, |
301 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 367 | drv_data->reg_base + drv_data->reg_offsets.control); |
302 | drv_data->block = 0; | 368 | drv_data->block = 0; |
303 | wake_up(&drv_data->waitq); | 369 | wake_up(&drv_data->waitq); |
304 | break; | 370 | break; |
@@ -313,7 +379,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) | |||
313 | case MV64XXX_I2C_ACTION_SEND_STOP: | 379 | case MV64XXX_I2C_ACTION_SEND_STOP: |
314 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; | 380 | drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; |
315 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, | 381 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, |
316 | drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); | 382 | drv_data->reg_base + drv_data->reg_offsets.control); |
317 | drv_data->block = 0; | 383 | drv_data->block = 0; |
318 | wake_up(&drv_data->waitq); | 384 | wake_up(&drv_data->waitq); |
319 | break; | 385 | break; |
@@ -329,9 +395,9 @@ mv64xxx_i2c_intr(int irq, void *dev_id) | |||
329 | irqreturn_t rc = IRQ_NONE; | 395 | irqreturn_t rc = IRQ_NONE; |
330 | 396 | ||
331 | spin_lock_irqsave(&drv_data->lock, flags); | 397 | spin_lock_irqsave(&drv_data->lock, flags); |
332 | while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & | 398 | while (readl(drv_data->reg_base + drv_data->reg_offsets.control) & |
333 | MV64XXX_I2C_REG_CONTROL_IFLG) { | 399 | MV64XXX_I2C_REG_CONTROL_IFLG) { |
334 | status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); | 400 | status = readl(drv_data->reg_base + drv_data->reg_offsets.status); |
335 | mv64xxx_i2c_fsm(drv_data, status); | 401 | mv64xxx_i2c_fsm(drv_data, status); |
336 | mv64xxx_i2c_do_action(drv_data); | 402 | mv64xxx_i2c_do_action(drv_data); |
337 | rc = IRQ_HANDLED; | 403 | rc = IRQ_HANDLED; |
@@ -349,32 +415,6 @@ mv64xxx_i2c_intr(int irq, void *dev_id) | |||
349 | ***************************************************************************** | 415 | ***************************************************************************** |
350 | */ | 416 | */ |
351 | static void | 417 | static void |
352 | mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, | ||
353 | struct i2c_msg *msg) | ||
354 | { | ||
355 | u32 dir = 0; | ||
356 | |||
357 | drv_data->msg = msg; | ||
358 | drv_data->byte_posn = 0; | ||
359 | drv_data->bytes_left = msg->len; | ||
360 | drv_data->aborting = 0; | ||
361 | drv_data->rc = 0; | ||
362 | drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | | ||
363 | MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; | ||
364 | |||
365 | if (msg->flags & I2C_M_RD) | ||
366 | dir = 1; | ||
367 | |||
368 | if (msg->flags & I2C_M_TEN) { | ||
369 | drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; | ||
370 | drv_data->addr2 = (u32)msg->addr & 0xff; | ||
371 | } else { | ||
372 | drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir; | ||
373 | drv_data->addr2 = 0; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | static void | ||
378 | mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) | 418 | mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) |
379 | { | 419 | { |
380 | long time_left; | 420 | long time_left; |
@@ -414,36 +454,15 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) | |||
414 | 454 | ||
415 | static int | 455 | static int |
416 | mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, | 456 | mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, |
417 | int is_first, int is_last) | 457 | int is_last) |
418 | { | 458 | { |
419 | unsigned long flags; | 459 | unsigned long flags; |
420 | 460 | ||
421 | spin_lock_irqsave(&drv_data->lock, flags); | 461 | spin_lock_irqsave(&drv_data->lock, flags); |
422 | mv64xxx_i2c_prepare_for_io(drv_data, msg); | 462 | mv64xxx_i2c_prepare_for_io(drv_data, msg); |
423 | 463 | ||
424 | if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */ | 464 | drv_data->action = MV64XXX_I2C_ACTION_SEND_START; |
425 | if (drv_data->msg->flags & I2C_M_RD) { | 465 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; |
426 | /* No action to do, wait for slave to send a byte */ | ||
427 | drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; | ||
428 | drv_data->state = | ||
429 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; | ||
430 | } else { | ||
431 | drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; | ||
432 | drv_data->state = | ||
433 | MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; | ||
434 | drv_data->bytes_left--; | ||
435 | } | ||
436 | } else { | ||
437 | if (is_first) { | ||
438 | drv_data->action = MV64XXX_I2C_ACTION_SEND_START; | ||
439 | drv_data->state = | ||
440 | MV64XXX_I2C_STATE_WAITING_FOR_START_COND; | ||
441 | } else { | ||
442 | drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; | ||
443 | drv_data->state = | ||
444 | MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; | ||
445 | } | ||
446 | } | ||
447 | 466 | ||
448 | drv_data->send_stop = is_last; | 467 | drv_data->send_stop = is_last; |
449 | drv_data->block = 1; | 468 | drv_data->block = 1; |
@@ -471,16 +490,20 @@ static int | |||
471 | mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | 490 | mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) |
472 | { | 491 | { |
473 | struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); | 492 | struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); |
474 | int i, rc; | 493 | int rc, ret = num; |
475 | 494 | ||
476 | for (i = 0; i < num; i++) { | 495 | BUG_ON(drv_data->msgs != NULL); |
477 | rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i], | 496 | drv_data->msgs = msgs; |
478 | i == 0, i + 1 == num); | 497 | drv_data->num_msgs = num; |
479 | if (rc < 0) | 498 | |
480 | return rc; | 499 | rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1); |
481 | } | 500 | if (rc < 0) |
501 | ret = rc; | ||
502 | |||
503 | drv_data->num_msgs = 0; | ||
504 | drv_data->msgs = NULL; | ||
482 | 505 | ||
483 | return num; | 506 | return ret; |
484 | } | 507 | } |
485 | 508 | ||
486 | static const struct i2c_algorithm mv64xxx_i2c_algo = { | 509 | static const struct i2c_algorithm mv64xxx_i2c_algo = { |
@@ -495,39 +518,12 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = { | |||
495 | * | 518 | * |
496 | ***************************************************************************** | 519 | ***************************************************************************** |
497 | */ | 520 | */ |
498 | static int | 521 | static const struct of_device_id mv64xxx_i2c_of_match_table[] = { |
499 | mv64xxx_i2c_map_regs(struct platform_device *pd, | 522 | { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i}, |
500 | struct mv64xxx_i2c_data *drv_data) | 523 | { .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, |
501 | { | 524 | {} |
502 | int size; | 525 | }; |
503 | struct resource *r = platform_get_resource(pd, IORESOURCE_MEM, 0); | 526 | MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); |
504 | |||
505 | if (!r) | ||
506 | return -ENODEV; | ||
507 | |||
508 | size = resource_size(r); | ||
509 | |||
510 | if (!request_mem_region(r->start, size, drv_data->adapter.name)) | ||
511 | return -EBUSY; | ||
512 | |||
513 | drv_data->reg_base = ioremap(r->start, size); | ||
514 | drv_data->reg_base_p = r->start; | ||
515 | drv_data->reg_size = size; | ||
516 | |||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static void | ||
521 | mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) | ||
522 | { | ||
523 | if (drv_data->reg_base) { | ||
524 | iounmap(drv_data->reg_base); | ||
525 | release_mem_region(drv_data->reg_base_p, drv_data->reg_size); | ||
526 | } | ||
527 | |||
528 | drv_data->reg_base = NULL; | ||
529 | drv_data->reg_base_p = 0; | ||
530 | } | ||
531 | 527 | ||
532 | #ifdef CONFIG_OF | 528 | #ifdef CONFIG_OF |
533 | static int | 529 | static int |
@@ -562,8 +558,10 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, | |||
562 | 558 | ||
563 | static int | 559 | static int |
564 | mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, | 560 | mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, |
565 | struct device_node *np) | 561 | struct device *dev) |
566 | { | 562 | { |
563 | const struct of_device_id *device; | ||
564 | struct device_node *np = dev->of_node; | ||
567 | u32 bus_freq, tclk; | 565 | u32 bus_freq, tclk; |
568 | int rc = 0; | 566 | int rc = 0; |
569 | 567 | ||
@@ -580,7 +578,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, | |||
580 | goto out; | 578 | goto out; |
581 | } | 579 | } |
582 | tclk = clk_get_rate(drv_data->clk); | 580 | tclk = clk_get_rate(drv_data->clk); |
583 | of_property_read_u32(np, "clock-frequency", &bus_freq); | 581 | |
582 | rc = of_property_read_u32(np, "clock-frequency", &bus_freq); | ||
583 | if (rc) | ||
584 | bus_freq = 100000; /* 100kHz by default */ | ||
585 | |||
584 | if (!mv64xxx_find_baud_factors(bus_freq, tclk, | 586 | if (!mv64xxx_find_baud_factors(bus_freq, tclk, |
585 | &drv_data->freq_n, &drv_data->freq_m)) { | 587 | &drv_data->freq_n, &drv_data->freq_m)) { |
586 | rc = -EINVAL; | 588 | rc = -EINVAL; |
@@ -592,6 +594,13 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, | |||
592 | * So hard code the value to 1 second. | 594 | * So hard code the value to 1 second. |
593 | */ | 595 | */ |
594 | drv_data->adapter.timeout = HZ; | 596 | drv_data->adapter.timeout = HZ; |
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 | |||
595 | out: | 604 | out: |
596 | return rc; | 605 | return rc; |
597 | #endif | 606 | #endif |
@@ -599,7 +608,7 @@ out: | |||
599 | #else /* CONFIG_OF */ | 608 | #else /* CONFIG_OF */ |
600 | static int | 609 | static int |
601 | mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, | 610 | mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, |
602 | struct device_node *np) | 611 | struct device *dev) |
603 | { | 612 | { |
604 | return -ENODEV; | 613 | return -ENODEV; |
605 | } | 614 | } |
@@ -610,19 +619,21 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
610 | { | 619 | { |
611 | struct mv64xxx_i2c_data *drv_data; | 620 | struct mv64xxx_i2c_data *drv_data; |
612 | struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; | 621 | struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; |
622 | struct resource *r; | ||
613 | int rc; | 623 | int rc; |
614 | 624 | ||
615 | if ((!pdata && !pd->dev.of_node)) | 625 | if ((!pdata && !pd->dev.of_node)) |
616 | return -ENODEV; | 626 | return -ENODEV; |
617 | 627 | ||
618 | drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); | 628 | drv_data = devm_kzalloc(&pd->dev, sizeof(struct mv64xxx_i2c_data), |
629 | GFP_KERNEL); | ||
619 | if (!drv_data) | 630 | if (!drv_data) |
620 | return -ENOMEM; | 631 | return -ENOMEM; |
621 | 632 | ||
622 | if (mv64xxx_i2c_map_regs(pd, drv_data)) { | 633 | r = platform_get_resource(pd, IORESOURCE_MEM, 0); |
623 | rc = -ENODEV; | 634 | drv_data->reg_base = devm_ioremap_resource(&pd->dev, r); |
624 | goto exit_kfree; | 635 | if (IS_ERR(drv_data->reg_base)) |
625 | } | 636 | return PTR_ERR(drv_data->reg_base); |
626 | 637 | ||
627 | strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", | 638 | strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", |
628 | sizeof(drv_data->adapter.name)); | 639 | sizeof(drv_data->adapter.name)); |
@@ -632,7 +643,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
632 | 643 | ||
633 | #if defined(CONFIG_HAVE_CLK) | 644 | #if defined(CONFIG_HAVE_CLK) |
634 | /* Not all platforms have a clk */ | 645 | /* Not all platforms have a clk */ |
635 | drv_data->clk = clk_get(&pd->dev, NULL); | 646 | drv_data->clk = devm_clk_get(&pd->dev, NULL); |
636 | if (!IS_ERR(drv_data->clk)) { | 647 | if (!IS_ERR(drv_data->clk)) { |
637 | clk_prepare(drv_data->clk); | 648 | clk_prepare(drv_data->clk); |
638 | clk_enable(drv_data->clk); | 649 | clk_enable(drv_data->clk); |
@@ -643,14 +654,15 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
643 | drv_data->freq_n = pdata->freq_n; | 654 | drv_data->freq_n = pdata->freq_n; |
644 | drv_data->irq = platform_get_irq(pd, 0); | 655 | drv_data->irq = platform_get_irq(pd, 0); |
645 | drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); | 656 | drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); |
657 | memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets)); | ||
646 | } else if (pd->dev.of_node) { | 658 | } else if (pd->dev.of_node) { |
647 | rc = mv64xxx_of_config(drv_data, pd->dev.of_node); | 659 | rc = mv64xxx_of_config(drv_data, &pd->dev); |
648 | if (rc) | 660 | if (rc) |
649 | goto exit_unmap_regs; | 661 | goto exit_clk; |
650 | } | 662 | } |
651 | if (drv_data->irq < 0) { | 663 | if (drv_data->irq < 0) { |
652 | rc = -ENXIO; | 664 | rc = -ENXIO; |
653 | goto exit_unmap_regs; | 665 | goto exit_clk; |
654 | } | 666 | } |
655 | 667 | ||
656 | drv_data->adapter.dev.parent = &pd->dev; | 668 | drv_data->adapter.dev.parent = &pd->dev; |
@@ -664,13 +676,13 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
664 | 676 | ||
665 | mv64xxx_i2c_hw_init(drv_data); | 677 | mv64xxx_i2c_hw_init(drv_data); |
666 | 678 | ||
667 | if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, | 679 | rc = request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, |
668 | MV64XXX_I2C_CTLR_NAME, drv_data)) { | 680 | MV64XXX_I2C_CTLR_NAME, drv_data); |
681 | if (rc) { | ||
669 | dev_err(&drv_data->adapter.dev, | 682 | dev_err(&drv_data->adapter.dev, |
670 | "mv64xxx: Can't register intr handler irq: %d\n", | 683 | "mv64xxx: Can't register intr handler irq%d: %d\n", |
671 | drv_data->irq); | 684 | drv_data->irq, rc); |
672 | rc = -EINVAL; | 685 | goto exit_clk; |
673 | goto exit_unmap_regs; | ||
674 | } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { | 686 | } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { |
675 | dev_err(&drv_data->adapter.dev, | 687 | dev_err(&drv_data->adapter.dev, |
676 | "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); | 688 | "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); |
@@ -681,9 +693,9 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
681 | 693 | ||
682 | return 0; | 694 | return 0; |
683 | 695 | ||
684 | exit_free_irq: | 696 | exit_free_irq: |
685 | free_irq(drv_data->irq, drv_data); | 697 | free_irq(drv_data->irq, drv_data); |
686 | exit_unmap_regs: | 698 | exit_clk: |
687 | #if defined(CONFIG_HAVE_CLK) | 699 | #if defined(CONFIG_HAVE_CLK) |
688 | /* Not all platforms have a clk */ | 700 | /* Not all platforms have a clk */ |
689 | if (!IS_ERR(drv_data->clk)) { | 701 | if (!IS_ERR(drv_data->clk)) { |
@@ -691,9 +703,6 @@ mv64xxx_i2c_probe(struct platform_device *pd) | |||
691 | clk_unprepare(drv_data->clk); | 703 | clk_unprepare(drv_data->clk); |
692 | } | 704 | } |
693 | #endif | 705 | #endif |
694 | mv64xxx_i2c_unmap_regs(drv_data); | ||
695 | exit_kfree: | ||
696 | kfree(drv_data); | ||
697 | return rc; | 706 | return rc; |
698 | } | 707 | } |
699 | 708 | ||
@@ -704,7 +713,6 @@ mv64xxx_i2c_remove(struct platform_device *dev) | |||
704 | 713 | ||
705 | i2c_del_adapter(&drv_data->adapter); | 714 | i2c_del_adapter(&drv_data->adapter); |
706 | free_irq(drv_data->irq, drv_data); | 715 | free_irq(drv_data->irq, drv_data); |
707 | mv64xxx_i2c_unmap_regs(drv_data); | ||
708 | #if defined(CONFIG_HAVE_CLK) | 716 | #if defined(CONFIG_HAVE_CLK) |
709 | /* Not all platforms have a clk */ | 717 | /* Not all platforms have a clk */ |
710 | if (!IS_ERR(drv_data->clk)) { | 718 | if (!IS_ERR(drv_data->clk)) { |
@@ -712,17 +720,10 @@ mv64xxx_i2c_remove(struct platform_device *dev) | |||
712 | clk_unprepare(drv_data->clk); | 720 | clk_unprepare(drv_data->clk); |
713 | } | 721 | } |
714 | #endif | 722 | #endif |
715 | kfree(drv_data); | ||
716 | 723 | ||
717 | return 0; | 724 | return 0; |
718 | } | 725 | } |
719 | 726 | ||
720 | static const struct of_device_id mv64xxx_i2c_of_match_table[] = { | ||
721 | { .compatible = "marvell,mv64xxx-i2c", }, | ||
722 | {} | ||
723 | }; | ||
724 | MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); | ||
725 | |||
726 | static struct platform_driver mv64xxx_i2c_driver = { | 727 | static struct platform_driver mv64xxx_i2c_driver = { |
727 | .probe = mv64xxx_i2c_probe, | 728 | .probe = mv64xxx_i2c_probe, |
728 | .remove = mv64xxx_i2c_remove, | 729 | .remove = mv64xxx_i2c_remove, |