diff options
| author | Marek Vasut <marex@denx.de> | 2012-08-23 23:44:31 -0400 |
|---|---|---|
| committer | Wolfram Sang <w.sang@pengutronix.de> | 2012-10-08 06:47:33 -0400 |
| commit | 62885f59a26195d9f6a3f8c795225dfbab62a110 (patch) | |
| tree | 56773f6a15d22154816b240c4988cb906df7ed5f | |
| parent | 102084d3d3969646cc89ea159e50898aeafc6649 (diff) | |
MXS: Implement DMA support into mxs-i2c
This patch implements DMA support into mxs-i2c. DMA transfers are now enabled
via DT. The DMA operation is enabled by default.
Signed-off-by: Marek Vasut <marex@denx.de>
Tested-by: Fabio Estevam <fabio.estevam@freescale.com>
[wsa: rebased to 3.6-rc7]
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
| -rw-r--r-- | Documentation/devicetree/bindings/i2c/i2c-mxs.txt | 2 | ||||
| -rw-r--r-- | arch/arm/boot/dts/imx28.dtsi | 2 | ||||
| -rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 269 |
3 files changed, 251 insertions, 22 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt index 30ac3a0557f7..7a3fe9e5f4cb 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt | |||
| @@ -6,6 +6,7 @@ Required properties: | |||
| 6 | - interrupts: Should contain ERROR and DMA interrupts | 6 | - interrupts: Should contain ERROR and DMA interrupts |
| 7 | - clock-frequency: Desired I2C bus clock frequency in Hz. | 7 | - clock-frequency: Desired I2C bus clock frequency in Hz. |
| 8 | Only 100000Hz and 400000Hz modes are supported. | 8 | Only 100000Hz and 400000Hz modes are supported. |
| 9 | - fsl,i2c-dma-channel: APBX DMA channel for the I2C | ||
| 9 | 10 | ||
| 10 | Examples: | 11 | Examples: |
| 11 | 12 | ||
| @@ -16,4 +17,5 @@ i2c0: i2c@80058000 { | |||
| 16 | reg = <0x80058000 2000>; | 17 | reg = <0x80058000 2000>; |
| 17 | interrupts = <111 68>; | 18 | interrupts = <111 68>; |
| 18 | clock-frequency = <100000>; | 19 | clock-frequency = <100000>; |
| 20 | fsl,i2c-dma-channel = <6>; | ||
| 19 | }; | 21 | }; |
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 3fa6d190fab4..ba8227e92bd1 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi | |||
| @@ -661,6 +661,7 @@ | |||
| 661 | reg = <0x80058000 0x2000>; | 661 | reg = <0x80058000 0x2000>; |
| 662 | interrupts = <111 68>; | 662 | interrupts = <111 68>; |
| 663 | clock-frequency = <100000>; | 663 | clock-frequency = <100000>; |
| 664 | fsl,i2c-dma-channel = <6>; | ||
| 664 | status = "disabled"; | 665 | status = "disabled"; |
| 665 | }; | 666 | }; |
| 666 | 667 | ||
| @@ -671,6 +672,7 @@ | |||
| 671 | reg = <0x8005a000 0x2000>; | 672 | reg = <0x8005a000 0x2000>; |
| 672 | interrupts = <110 69>; | 673 | interrupts = <110 69>; |
| 673 | clock-frequency = <100000>; | 674 | clock-frequency = <100000>; |
| 675 | fsl,i2c-dma-channel = <7>; | ||
| 674 | status = "disabled"; | 676 | status = "disabled"; |
| 675 | }; | 677 | }; |
| 676 | 678 | ||
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 51f05b8520ed..1f58197062cf 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
| @@ -7,8 +7,6 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. | 8 | * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. |
| 9 | * | 9 | * |
| 10 | * TODO: add dma-support if platform-support for it is available | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | 10 | * 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 | 11 | * 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 | 12 | * the Free Software Foundation; either version 2 of the License, or |
| @@ -31,9 +29,16 @@ | |||
| 31 | #include <linux/of.h> | 29 | #include <linux/of.h> |
| 32 | #include <linux/of_device.h> | 30 | #include <linux/of_device.h> |
| 33 | #include <linux/of_i2c.h> | 31 | #include <linux/of_i2c.h> |
| 32 | #include <linux/dma-mapping.h> | ||
| 33 | #include <linux/dmaengine.h> | ||
| 34 | #include <linux/fsl/mxs-dma.h> | ||
| 34 | 35 | ||
| 35 | #define DRIVER_NAME "mxs-i2c" | 36 | #define DRIVER_NAME "mxs-i2c" |
| 36 | 37 | ||
| 38 | static bool use_pioqueue; | ||
| 39 | module_param(use_pioqueue, bool, 0); | ||
| 40 | MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); | ||
| 41 | |||
| 37 | #define MXS_I2C_CTRL0 (0x00) | 42 | #define MXS_I2C_CTRL0 (0x00) |
| 38 | #define MXS_I2C_CTRL0_SET (0x04) | 43 | #define MXS_I2C_CTRL0_SET (0x04) |
| 39 | 44 | ||
| @@ -146,6 +151,16 @@ struct mxs_i2c_dev { | |||
| 146 | u32 cmd_err; | 151 | u32 cmd_err; |
| 147 | struct i2c_adapter adapter; | 152 | struct i2c_adapter adapter; |
| 148 | const struct mxs_i2c_speed_config *speed; | 153 | const struct mxs_i2c_speed_config *speed; |
| 154 | |||
| 155 | /* DMA support components */ | ||
| 156 | bool dma_mode; | ||
| 157 | int dma_channel; | ||
| 158 | struct dma_chan *dmach; | ||
| 159 | struct mxs_dma_data dma_data; | ||
| 160 | uint32_t pio_data[2]; | ||
| 161 | uint32_t addr_data; | ||
| 162 | struct scatterlist sg_io[2]; | ||
| 163 | bool dma_read; | ||
| 149 | }; | 164 | }; |
| 150 | 165 | ||
| 151 | static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) | 166 | static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) |
| @@ -157,7 +172,11 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) | |||
| 157 | writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2); | 172 | writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2); |
| 158 | 173 | ||
| 159 | writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); | 174 | writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); |
| 160 | writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, | 175 | if (i2c->dma_mode) |
| 176 | writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, | ||
| 177 | i2c->regs + MXS_I2C_QUEUECTRL_CLR); | ||
| 178 | else | ||
| 179 | writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, | ||
| 161 | i2c->regs + MXS_I2C_QUEUECTRL_SET); | 180 | i2c->regs + MXS_I2C_QUEUECTRL_SET); |
| 162 | } | 181 | } |
| 163 | 182 | ||
| @@ -248,6 +267,150 @@ static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) | |||
| 248 | return 0; | 267 | return 0; |
| 249 | } | 268 | } |
| 250 | 269 | ||
| 270 | static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) | ||
| 271 | { | ||
| 272 | if (i2c->dma_read) { | ||
| 273 | dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); | ||
| 274 | dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE); | ||
| 275 | } else { | ||
| 276 | dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | static void mxs_i2c_dma_irq_callback(void *param) | ||
| 281 | { | ||
| 282 | struct mxs_i2c_dev *i2c = param; | ||
| 283 | |||
| 284 | complete(&i2c->cmd_complete); | ||
| 285 | mxs_i2c_dma_finish(i2c); | ||
| 286 | } | ||
| 287 | |||
| 288 | static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap, | ||
| 289 | struct i2c_msg *msg, uint32_t flags) | ||
| 290 | { | ||
| 291 | struct dma_async_tx_descriptor *desc; | ||
| 292 | struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); | ||
| 293 | |||
| 294 | if (msg->flags & I2C_M_RD) { | ||
| 295 | i2c->dma_read = 1; | ||
| 296 | i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ; | ||
| 297 | |||
| 298 | /* | ||
| 299 | * SELECT command. | ||
| 300 | */ | ||
| 301 | |||
| 302 | /* Queue the PIO register write transfer. */ | ||
| 303 | i2c->pio_data[0] = MXS_CMD_I2C_SELECT; | ||
| 304 | desc = dmaengine_prep_slave_sg(i2c->dmach, | ||
| 305 | (struct scatterlist *)&i2c->pio_data[0], | ||
| 306 | 1, DMA_TRANS_NONE, 0); | ||
| 307 | if (!desc) { | ||
| 308 | dev_err(i2c->dev, | ||
| 309 | "Failed to get PIO reg. write descriptor.\n"); | ||
| 310 | goto select_init_pio_fail; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* Queue the DMA data transfer. */ | ||
| 314 | sg_init_one(&i2c->sg_io[0], &i2c->addr_data, 1); | ||
| 315 | dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); | ||
| 316 | desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1, | ||
| 317 | DMA_MEM_TO_DEV, | ||
| 318 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 319 | if (!desc) { | ||
| 320 | dev_err(i2c->dev, | ||
| 321 | "Failed to get DMA data write descriptor.\n"); | ||
| 322 | goto select_init_dma_fail; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* | ||
| 326 | * READ command. | ||
| 327 | */ | ||
| 328 | |||
| 329 | /* Queue the PIO register write transfer. */ | ||
| 330 | i2c->pio_data[1] = flags | MXS_CMD_I2C_READ | | ||
| 331 | MXS_I2C_CTRL0_XFER_COUNT(msg->len); | ||
| 332 | desc = dmaengine_prep_slave_sg(i2c->dmach, | ||
| 333 | (struct scatterlist *)&i2c->pio_data[1], | ||
| 334 | 1, DMA_TRANS_NONE, DMA_PREP_INTERRUPT); | ||
| 335 | if (!desc) { | ||
| 336 | dev_err(i2c->dev, | ||
| 337 | "Failed to get PIO reg. write descriptor.\n"); | ||
| 338 | goto select_init_dma_fail; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* Queue the DMA data transfer. */ | ||
| 342 | sg_init_one(&i2c->sg_io[1], msg->buf, msg->len); | ||
| 343 | dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE); | ||
| 344 | desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1, | ||
| 345 | DMA_DEV_TO_MEM, | ||
| 346 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 347 | if (!desc) { | ||
| 348 | dev_err(i2c->dev, | ||
| 349 | "Failed to get DMA data write descriptor.\n"); | ||
| 350 | goto read_init_dma_fail; | ||
| 351 | } | ||
| 352 | } else { | ||
| 353 | i2c->dma_read = 0; | ||
| 354 | i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE; | ||
| 355 | |||
| 356 | /* | ||
| 357 | * WRITE command. | ||
| 358 | */ | ||
| 359 | |||
| 360 | /* Queue the PIO register write transfer. */ | ||
| 361 | i2c->pio_data[0] = flags | MXS_CMD_I2C_WRITE | | ||
| 362 | MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1); | ||
| 363 | desc = dmaengine_prep_slave_sg(i2c->dmach, | ||
| 364 | (struct scatterlist *)&i2c->pio_data[0], | ||
| 365 | 1, DMA_TRANS_NONE, 0); | ||
| 366 | if (!desc) { | ||
| 367 | dev_err(i2c->dev, | ||
| 368 | "Failed to get PIO reg. write descriptor.\n"); | ||
| 369 | goto write_init_pio_fail; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* Queue the DMA data transfer. */ | ||
| 373 | sg_init_table(i2c->sg_io, 2); | ||
| 374 | sg_set_buf(&i2c->sg_io[0], &i2c->addr_data, 1); | ||
| 375 | sg_set_buf(&i2c->sg_io[1], msg->buf, msg->len); | ||
| 376 | dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); | ||
| 377 | desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2, | ||
| 378 | DMA_MEM_TO_DEV, | ||
| 379 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 380 | if (!desc) { | ||
| 381 | dev_err(i2c->dev, | ||
| 382 | "Failed to get DMA data write descriptor.\n"); | ||
| 383 | goto write_init_dma_fail; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | |||
| 387 | /* | ||
| 388 | * The last descriptor must have this callback, | ||
| 389 | * to finish the DMA transaction. | ||
| 390 | */ | ||
| 391 | desc->callback = mxs_i2c_dma_irq_callback; | ||
| 392 | desc->callback_param = i2c; | ||
| 393 | |||
| 394 | /* Start the transfer. */ | ||
| 395 | dmaengine_submit(desc); | ||
| 396 | dma_async_issue_pending(i2c->dmach); | ||
| 397 | return 0; | ||
| 398 | |||
| 399 | /* Read failpath. */ | ||
| 400 | read_init_dma_fail: | ||
| 401 | dma_unmap_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE); | ||
| 402 | select_init_dma_fail: | ||
| 403 | dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); | ||
| 404 | select_init_pio_fail: | ||
| 405 | return -EINVAL; | ||
| 406 | |||
| 407 | /* Write failpath. */ | ||
| 408 | write_init_dma_fail: | ||
| 409 | dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); | ||
| 410 | write_init_pio_fail: | ||
| 411 | return -EINVAL; | ||
| 412 | } | ||
| 413 | |||
| 251 | /* | 414 | /* |
| 252 | * Low level master read/write transaction. | 415 | * Low level master read/write transaction. |
| 253 | */ | 416 | */ |
| @@ -258,6 +421,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 258 | int ret; | 421 | int ret; |
| 259 | int flags; | 422 | int flags; |
| 260 | 423 | ||
| 424 | flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; | ||
| 425 | |||
| 261 | dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", | 426 | dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", |
| 262 | msg->addr, msg->len, msg->flags, stop); | 427 | msg->addr, msg->len, msg->flags, stop); |
| 263 | 428 | ||
| @@ -267,23 +432,29 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 267 | init_completion(&i2c->cmd_complete); | 432 | init_completion(&i2c->cmd_complete); |
| 268 | i2c->cmd_err = 0; | 433 | i2c->cmd_err = 0; |
| 269 | 434 | ||
| 270 | flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; | 435 | if (i2c->dma_mode) { |
| 271 | 436 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); | |
| 272 | if (msg->flags & I2C_M_RD) | 437 | if (ret) |
| 273 | mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags); | 438 | return ret; |
| 274 | else | 439 | } else { |
| 275 | mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len, | 440 | if (msg->flags & I2C_M_RD) { |
| 276 | flags); | 441 | mxs_i2c_pioq_setup_read(i2c, msg->addr, |
| 442 | msg->len, flags); | ||
| 443 | } else { | ||
| 444 | mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, | ||
| 445 | msg->len, flags); | ||
| 446 | } | ||
| 277 | 447 | ||
| 278 | writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, | 448 | writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, |
| 279 | i2c->regs + MXS_I2C_QUEUECTRL_SET); | 449 | i2c->regs + MXS_I2C_QUEUECTRL_SET); |
| 450 | } | ||
| 280 | 451 | ||
| 281 | ret = wait_for_completion_timeout(&i2c->cmd_complete, | 452 | ret = wait_for_completion_timeout(&i2c->cmd_complete, |
| 282 | msecs_to_jiffies(1000)); | 453 | msecs_to_jiffies(1000)); |
| 283 | if (ret == 0) | 454 | if (ret == 0) |
| 284 | goto timeout; | 455 | goto timeout; |
| 285 | 456 | ||
| 286 | if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) { | 457 | if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) { |
| 287 | ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); | 458 | ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); |
| 288 | if (ret) | 459 | if (ret) |
| 289 | goto timeout; | 460 | goto timeout; |
| @@ -301,6 +472,8 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
| 301 | 472 | ||
| 302 | timeout: | 473 | timeout: |
| 303 | dev_dbg(i2c->dev, "Timeout!\n"); | 474 | dev_dbg(i2c->dev, "Timeout!\n"); |
| 475 | if (i2c->dma_mode) | ||
| 476 | mxs_i2c_dma_finish(i2c); | ||
| 304 | mxs_i2c_reset(i2c); | 477 | mxs_i2c_reset(i2c); |
| 305 | return -ETIMEDOUT; | 478 | return -ETIMEDOUT; |
| 306 | } | 479 | } |
| @@ -342,11 +515,13 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) | |||
| 342 | /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */ | 515 | /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */ |
| 343 | i2c->cmd_err = -EIO; | 516 | i2c->cmd_err = -EIO; |
| 344 | 517 | ||
| 345 | is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & | 518 | if (!i2c->dma_mode) { |
| 346 | MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; | 519 | is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & |
| 520 | MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; | ||
| 347 | 521 | ||
| 348 | if (is_last_cmd || i2c->cmd_err) | 522 | if (is_last_cmd || i2c->cmd_err) |
| 349 | complete(&i2c->cmd_complete); | 523 | complete(&i2c->cmd_complete); |
| 524 | } | ||
| 350 | 525 | ||
| 351 | writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); | 526 | writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); |
| 352 | 527 | ||
| @@ -358,6 +533,21 @@ static const struct i2c_algorithm mxs_i2c_algo = { | |||
| 358 | .functionality = mxs_i2c_func, | 533 | .functionality = mxs_i2c_func, |
| 359 | }; | 534 | }; |
| 360 | 535 | ||
| 536 | static bool mxs_i2c_dma_filter(struct dma_chan *chan, void *param) | ||
| 537 | { | ||
| 538 | struct mxs_i2c_dev *i2c = param; | ||
| 539 | |||
| 540 | if (!mxs_dma_is_apbx(chan)) | ||
| 541 | return false; | ||
| 542 | |||
| 543 | if (chan->chan_id != i2c->dma_channel) | ||
| 544 | return false; | ||
| 545 | |||
| 546 | chan->private = &i2c->dma_data; | ||
| 547 | |||
| 548 | return true; | ||
| 549 | } | ||
| 550 | |||
| 361 | static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) | 551 | static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) |
| 362 | { | 552 | { |
| 363 | uint32_t speed; | 553 | uint32_t speed; |
| @@ -365,6 +555,26 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) | |||
| 365 | struct device_node *node = dev->of_node; | 555 | struct device_node *node = dev->of_node; |
| 366 | int ret; | 556 | int ret; |
| 367 | 557 | ||
| 558 | /* | ||
| 559 | * The MXS I2C DMA mode is prefered and enabled by default. | ||
| 560 | * The PIO mode is still supported, but should be used only | ||
| 561 | * for debuging purposes etc. | ||
| 562 | */ | ||
| 563 | i2c->dma_mode = !use_pioqueue; | ||
| 564 | if (!i2c->dma_mode) | ||
| 565 | dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n"); | ||
| 566 | |||
| 567 | /* | ||
| 568 | * TODO: This is a temporary solution and should be changed | ||
| 569 | * to use generic DMA binding later when the helpers get in. | ||
| 570 | */ | ||
| 571 | ret = of_property_read_u32(node, "fsl,i2c-dma-channel", | ||
| 572 | &i2c->dma_channel); | ||
| 573 | if (ret) { | ||
| 574 | dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); | ||
| 575 | i2c->dma_mode = 0; | ||
| 576 | } | ||
| 577 | |||
| 368 | ret = of_property_read_u32(node, "clock-frequency", &speed); | 578 | ret = of_property_read_u32(node, "clock-frequency", &speed); |
| 369 | if (ret) | 579 | if (ret) |
| 370 | dev_warn(dev, "No I2C speed selected, using 100kHz\n"); | 580 | dev_warn(dev, "No I2C speed selected, using 100kHz\n"); |
| @@ -384,7 +594,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
| 384 | struct pinctrl *pinctrl; | 594 | struct pinctrl *pinctrl; |
| 385 | struct resource *res; | 595 | struct resource *res; |
| 386 | resource_size_t res_size; | 596 | resource_size_t res_size; |
| 387 | int err, irq; | 597 | int err, irq, dmairq; |
| 598 | dma_cap_mask_t mask; | ||
| 388 | 599 | ||
| 389 | pinctrl = devm_pinctrl_get_select_default(dev); | 600 | pinctrl = devm_pinctrl_get_select_default(dev); |
| 390 | if (IS_ERR(pinctrl)) | 601 | if (IS_ERR(pinctrl)) |
| @@ -395,7 +606,10 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
| 395 | return -ENOMEM; | 606 | return -ENOMEM; |
| 396 | 607 | ||
| 397 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 608 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 398 | if (!res) | 609 | irq = platform_get_irq(pdev, 0); |
| 610 | dmairq = platform_get_irq(pdev, 1); | ||
| 611 | |||
| 612 | if (!res || irq < 0 || dmairq < 0) | ||
| 399 | return -ENOENT; | 613 | return -ENOENT; |
| 400 | 614 | ||
| 401 | res_size = resource_size(res); | 615 | res_size = resource_size(res); |
| @@ -406,10 +620,6 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
| 406 | if (!i2c->regs) | 620 | if (!i2c->regs) |
| 407 | return -EBUSY; | 621 | return -EBUSY; |
| 408 | 622 | ||
| 409 | irq = platform_get_irq(pdev, 0); | ||
| 410 | if (irq < 0) | ||
| 411 | return irq; | ||
| 412 | |||
| 413 | err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c); | 623 | err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c); |
| 414 | if (err) | 624 | if (err) |
| 415 | return err; | 625 | return err; |
| @@ -423,6 +633,18 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
| 423 | return err; | 633 | return err; |
| 424 | } | 634 | } |
| 425 | 635 | ||
| 636 | /* Setup the DMA */ | ||
| 637 | if (i2c->dma_mode) { | ||
| 638 | dma_cap_zero(mask); | ||
| 639 | dma_cap_set(DMA_SLAVE, mask); | ||
| 640 | i2c->dma_data.chan_irq = dmairq; | ||
| 641 | i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); | ||
| 642 | if (!i2c->dmach) { | ||
| 643 | dev_err(dev, "Failed to request dma\n"); | ||
| 644 | return -ENODEV; | ||
| 645 | } | ||
| 646 | } | ||
| 647 | |||
| 426 | platform_set_drvdata(pdev, i2c); | 648 | platform_set_drvdata(pdev, i2c); |
| 427 | 649 | ||
| 428 | /* Do reset to enforce correct startup after pinmuxing */ | 650 | /* Do reset to enforce correct startup after pinmuxing */ |
| @@ -458,6 +680,9 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev) | |||
| 458 | if (ret) | 680 | if (ret) |
| 459 | return -EBUSY; | 681 | return -EBUSY; |
| 460 | 682 | ||
| 683 | if (i2c->dmach) | ||
| 684 | dma_release_channel(i2c->dmach); | ||
| 685 | |||
| 461 | writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET); | 686 | writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET); |
| 462 | 687 | ||
| 463 | platform_set_drvdata(pdev, NULL); | 688 | platform_set_drvdata(pdev, NULL); |
