diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-02 20:26:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-02 20:26:42 -0400 |
commit | 7fe0b14b725d6d09a1d9e1409bd465cb88b587f9 (patch) | |
tree | 89b5ffca03145618da92c75fb3cc1dda87dbb924 /drivers/spi/spi-omap2-mcspi.c | |
parent | 7a9a2970b5c1c2ce73d4bb84edaa7ebf13e0c841 (diff) | |
parent | 536a53a300d0d40152796eefb0a9e6e36ca37f7d (diff) |
Merge tag 'spi-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc
Pull spi updates from Mark Brown:
"No framework work here, only a bunch of driver updates of varying
sizes:
- Factoring out of the core hardware support from the MXS MMC driver
by Marek Vasut to allow the hardware to also be used for SPI.
- Lots of error handling cleanups from Guenter Roeck
- Removal of the existing Tegra driver which is quite comprehensively
broken as detailed in the changelog for the removal.
- DT suppport for the PL022 and GPIO drivers.
- pinctrl support for OMAP and PL022."
Pulling from Mark Brown as Grant Likely is still busy moving.
* tag 'spi-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc: (53 commits)
spi: remove completely broken Tegra driver
spi/imx: set the inactive state of the clock according to the clock polarity
spi/pl022: get/put resources on suspend/resume
spi/pl022: use more managed resources
spi/pl022: Devicetree support w/o platform data
spi/s3c64xx: Don't free controller_data on non-dt platforms
spi: omap2-mcspi: add pinctrl support
spi/pl022: adopt pinctrl support
spi: omap2-mcspi: Cleanup the omap2_mcspi_txrx_dma function
spi/gpio: Fix stub for spi_gpio_probe_dt()
spi/mxs: Make the SPI block clock speed configurable via DT
spi: spi-sh-hspi: drop frees of devm_ alloc'd data
spi/pl022: Fix chipselects pointer computation
spi: spi-tle62x0: Use module_spi_driver macro
mxs/spi: Rework the mxs_ssp_timeout to be more readable
mxs/spi: Decrement the DMA/PIO border
mxs/spi: Increment the transfer length only if transfer succeeded
mxs/spi: Fix issues when doing long continuous transfer
spi: spi-gpio: Add DT bindings
spi: spi-gpio: store chipselect information in private structure
...
Diffstat (limited to 'drivers/spi/spi-omap2-mcspi.c')
-rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 321 |
1 files changed, 176 insertions, 145 deletions
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 5d59a69a9064..474e2174e08a 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include <linux/pm_runtime.h> | 38 | #include <linux/pm_runtime.h> |
39 | #include <linux/of.h> | 39 | #include <linux/of.h> |
40 | #include <linux/of_device.h> | 40 | #include <linux/of_device.h> |
41 | #include <linux/pinctrl/consumer.h> | ||
42 | #include <linux/err.h> | ||
41 | 43 | ||
42 | #include <linux/spi/spi.h> | 44 | #include <linux/spi/spi.h> |
43 | 45 | ||
@@ -140,13 +142,6 @@ struct omap2_mcspi_cs { | |||
140 | u32 chconf0; | 142 | u32 chconf0; |
141 | }; | 143 | }; |
142 | 144 | ||
143 | #define MOD_REG_BIT(val, mask, set) do { \ | ||
144 | if (set) \ | ||
145 | val |= mask; \ | ||
146 | else \ | ||
147 | val &= ~mask; \ | ||
148 | } while (0) | ||
149 | |||
150 | static inline void mcspi_write_reg(struct spi_master *master, | 145 | static inline void mcspi_write_reg(struct spi_master *master, |
151 | int idx, u32 val) | 146 | int idx, u32 val) |
152 | { | 147 | { |
@@ -205,7 +200,11 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi, | |||
205 | else | 200 | else |
206 | rw = OMAP2_MCSPI_CHCONF_DMAW; | 201 | rw = OMAP2_MCSPI_CHCONF_DMAW; |
207 | 202 | ||
208 | MOD_REG_BIT(l, rw, enable); | 203 | if (enable) |
204 | l |= rw; | ||
205 | else | ||
206 | l &= ~rw; | ||
207 | |||
209 | mcspi_write_chconf0(spi, l); | 208 | mcspi_write_chconf0(spi, l); |
210 | } | 209 | } |
211 | 210 | ||
@@ -224,7 +223,11 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) | |||
224 | u32 l; | 223 | u32 l; |
225 | 224 | ||
226 | l = mcspi_cached_chconf0(spi); | 225 | l = mcspi_cached_chconf0(spi); |
227 | MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); | 226 | if (cs_active) |
227 | l |= OMAP2_MCSPI_CHCONF_FORCE; | ||
228 | else | ||
229 | l &= ~OMAP2_MCSPI_CHCONF_FORCE; | ||
230 | |||
228 | mcspi_write_chconf0(spi, l); | 231 | mcspi_write_chconf0(spi, l); |
229 | } | 232 | } |
230 | 233 | ||
@@ -239,9 +242,8 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master) | |||
239 | * to single-channel master mode | 242 | * to single-channel master mode |
240 | */ | 243 | */ |
241 | l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); | 244 | l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); |
242 | MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); | 245 | l &= ~(OMAP2_MCSPI_MODULCTRL_STEST | OMAP2_MCSPI_MODULCTRL_MS); |
243 | MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); | 246 | l |= OMAP2_MCSPI_MODULCTRL_SINGLE; |
244 | MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); | ||
245 | mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); | 247 | mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); |
246 | 248 | ||
247 | ctx->modulctrl = l; | 249 | ctx->modulctrl = l; |
@@ -260,16 +262,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) | |||
260 | list_for_each_entry(cs, &ctx->cs, node) | 262 | list_for_each_entry(cs, &ctx->cs, node) |
261 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); | 263 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); |
262 | } | 264 | } |
263 | static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi) | ||
264 | { | ||
265 | pm_runtime_mark_last_busy(mcspi->dev); | ||
266 | pm_runtime_put_autosuspend(mcspi->dev); | ||
267 | } | ||
268 | |||
269 | static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) | ||
270 | { | ||
271 | return pm_runtime_get_sync(mcspi->dev); | ||
272 | } | ||
273 | 265 | ||
274 | static int omap2_prepare_transfer(struct spi_master *master) | 266 | static int omap2_prepare_transfer(struct spi_master *master) |
275 | { | 267 | { |
@@ -325,49 +317,27 @@ static void omap2_mcspi_tx_callback(void *data) | |||
325 | omap2_mcspi_set_dma_req(spi, 0, 0); | 317 | omap2_mcspi_set_dma_req(spi, 0, 0); |
326 | } | 318 | } |
327 | 319 | ||
328 | static unsigned | 320 | static void omap2_mcspi_tx_dma(struct spi_device *spi, |
329 | omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | 321 | struct spi_transfer *xfer, |
322 | struct dma_slave_config cfg) | ||
330 | { | 323 | { |
331 | struct omap2_mcspi *mcspi; | 324 | struct omap2_mcspi *mcspi; |
332 | struct omap2_mcspi_cs *cs = spi->controller_state; | ||
333 | struct omap2_mcspi_dma *mcspi_dma; | 325 | struct omap2_mcspi_dma *mcspi_dma; |
334 | unsigned int count; | 326 | unsigned int count; |
335 | int word_len, element_count; | ||
336 | int elements = 0; | ||
337 | u32 l; | ||
338 | u8 * rx; | 327 | u8 * rx; |
339 | const u8 * tx; | 328 | const u8 * tx; |
340 | void __iomem *chstat_reg; | 329 | void __iomem *chstat_reg; |
341 | struct dma_slave_config cfg; | 330 | struct omap2_mcspi_cs *cs = spi->controller_state; |
342 | enum dma_slave_buswidth width; | ||
343 | unsigned es; | ||
344 | 331 | ||
345 | mcspi = spi_master_get_devdata(spi->master); | 332 | mcspi = spi_master_get_devdata(spi->master); |
346 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; | 333 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; |
347 | l = mcspi_cached_chconf0(spi); | 334 | count = xfer->len; |
348 | 335 | ||
336 | rx = xfer->rx_buf; | ||
337 | tx = xfer->tx_buf; | ||
349 | chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; | 338 | chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; |
350 | 339 | ||
351 | if (cs->word_len <= 8) { | 340 | if (mcspi_dma->dma_tx) { |
352 | width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
353 | es = 1; | ||
354 | } else if (cs->word_len <= 16) { | ||
355 | width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
356 | es = 2; | ||
357 | } else { | ||
358 | width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
359 | es = 4; | ||
360 | } | ||
361 | |||
362 | memset(&cfg, 0, sizeof(cfg)); | ||
363 | cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; | ||
364 | cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; | ||
365 | cfg.src_addr_width = width; | ||
366 | cfg.dst_addr_width = width; | ||
367 | cfg.src_maxburst = 1; | ||
368 | cfg.dst_maxburst = 1; | ||
369 | |||
370 | if (xfer->tx_buf && mcspi_dma->dma_tx) { | ||
371 | struct dma_async_tx_descriptor *tx; | 341 | struct dma_async_tx_descriptor *tx; |
372 | struct scatterlist sg; | 342 | struct scatterlist sg; |
373 | 343 | ||
@@ -378,7 +348,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
378 | sg_dma_len(&sg) = xfer->len; | 348 | sg_dma_len(&sg) = xfer->len; |
379 | 349 | ||
380 | tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, | 350 | tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, &sg, 1, |
381 | DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 351 | DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
382 | if (tx) { | 352 | if (tx) { |
383 | tx->callback = omap2_mcspi_tx_callback; | 353 | tx->callback = omap2_mcspi_tx_callback; |
384 | tx->callback_param = spi; | 354 | tx->callback_param = spi; |
@@ -387,8 +357,50 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
387 | /* FIXME: fall back to PIO? */ | 357 | /* FIXME: fall back to PIO? */ |
388 | } | 358 | } |
389 | } | 359 | } |
360 | dma_async_issue_pending(mcspi_dma->dma_tx); | ||
361 | omap2_mcspi_set_dma_req(spi, 0, 1); | ||
362 | |||
363 | wait_for_completion(&mcspi_dma->dma_tx_completion); | ||
364 | dma_unmap_single(mcspi->dev, xfer->tx_dma, count, | ||
365 | DMA_TO_DEVICE); | ||
366 | |||
367 | /* for TX_ONLY mode, be sure all words have shifted out */ | ||
368 | if (rx == NULL) { | ||
369 | if (mcspi_wait_for_reg_bit(chstat_reg, | ||
370 | OMAP2_MCSPI_CHSTAT_TXS) < 0) | ||
371 | dev_err(&spi->dev, "TXS timed out\n"); | ||
372 | else if (mcspi_wait_for_reg_bit(chstat_reg, | ||
373 | OMAP2_MCSPI_CHSTAT_EOT) < 0) | ||
374 | dev_err(&spi->dev, "EOT timed out\n"); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | static unsigned | ||
379 | omap2_mcspi_rx_dma(struct spi_device *spi, struct spi_transfer *xfer, | ||
380 | struct dma_slave_config cfg, | ||
381 | unsigned es) | ||
382 | { | ||
383 | struct omap2_mcspi *mcspi; | ||
384 | struct omap2_mcspi_dma *mcspi_dma; | ||
385 | unsigned int count; | ||
386 | u32 l; | ||
387 | int elements = 0; | ||
388 | int word_len, element_count; | ||
389 | struct omap2_mcspi_cs *cs = spi->controller_state; | ||
390 | mcspi = spi_master_get_devdata(spi->master); | ||
391 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; | ||
392 | count = xfer->len; | ||
393 | word_len = cs->word_len; | ||
394 | l = mcspi_cached_chconf0(spi); | ||
390 | 395 | ||
391 | if (xfer->rx_buf && mcspi_dma->dma_rx) { | 396 | if (word_len <= 8) |
397 | element_count = count; | ||
398 | else if (word_len <= 16) | ||
399 | element_count = count >> 1; | ||
400 | else /* word_len <= 32 */ | ||
401 | element_count = count >> 2; | ||
402 | |||
403 | if (mcspi_dma->dma_rx) { | ||
392 | struct dma_async_tx_descriptor *tx; | 404 | struct dma_async_tx_descriptor *tx; |
393 | struct scatterlist sg; | 405 | struct scatterlist sg; |
394 | size_t len = xfer->len - es; | 406 | size_t len = xfer->len - es; |
@@ -403,108 +415,120 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
403 | sg_dma_len(&sg) = len; | 415 | sg_dma_len(&sg) = len; |
404 | 416 | ||
405 | tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, | 417 | tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, &sg, 1, |
406 | DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 418 | DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | |
419 | DMA_CTRL_ACK); | ||
407 | if (tx) { | 420 | if (tx) { |
408 | tx->callback = omap2_mcspi_rx_callback; | 421 | tx->callback = omap2_mcspi_rx_callback; |
409 | tx->callback_param = spi; | 422 | tx->callback_param = spi; |
410 | dmaengine_submit(tx); | 423 | dmaengine_submit(tx); |
411 | } else { | 424 | } else { |
412 | /* FIXME: fall back to PIO? */ | 425 | /* FIXME: fall back to PIO? */ |
413 | } | ||
414 | } | ||
415 | |||
416 | count = xfer->len; | ||
417 | word_len = cs->word_len; | ||
418 | |||
419 | rx = xfer->rx_buf; | ||
420 | tx = xfer->tx_buf; | ||
421 | |||
422 | if (word_len <= 8) { | ||
423 | element_count = count; | ||
424 | } else if (word_len <= 16) { | ||
425 | element_count = count >> 1; | ||
426 | } else /* word_len <= 32 */ { | ||
427 | element_count = count >> 2; | ||
428 | } | ||
429 | |||
430 | if (tx != NULL) { | ||
431 | dma_async_issue_pending(mcspi_dma->dma_tx); | ||
432 | omap2_mcspi_set_dma_req(spi, 0, 1); | ||
433 | } | ||
434 | |||
435 | if (rx != NULL) { | ||
436 | dma_async_issue_pending(mcspi_dma->dma_rx); | ||
437 | omap2_mcspi_set_dma_req(spi, 1, 1); | ||
438 | } | ||
439 | |||
440 | if (tx != NULL) { | ||
441 | wait_for_completion(&mcspi_dma->dma_tx_completion); | ||
442 | dma_unmap_single(mcspi->dev, xfer->tx_dma, count, | ||
443 | DMA_TO_DEVICE); | ||
444 | |||
445 | /* for TX_ONLY mode, be sure all words have shifted out */ | ||
446 | if (rx == NULL) { | ||
447 | if (mcspi_wait_for_reg_bit(chstat_reg, | ||
448 | OMAP2_MCSPI_CHSTAT_TXS) < 0) | ||
449 | dev_err(&spi->dev, "TXS timed out\n"); | ||
450 | else if (mcspi_wait_for_reg_bit(chstat_reg, | ||
451 | OMAP2_MCSPI_CHSTAT_EOT) < 0) | ||
452 | dev_err(&spi->dev, "EOT timed out\n"); | ||
453 | } | 426 | } |
454 | } | 427 | } |
455 | 428 | ||
456 | if (rx != NULL) { | 429 | dma_async_issue_pending(mcspi_dma->dma_rx); |
457 | wait_for_completion(&mcspi_dma->dma_rx_completion); | 430 | omap2_mcspi_set_dma_req(spi, 1, 1); |
458 | dma_unmap_single(mcspi->dev, xfer->rx_dma, count, | ||
459 | DMA_FROM_DEVICE); | ||
460 | omap2_mcspi_set_enable(spi, 0); | ||
461 | 431 | ||
462 | elements = element_count - 1; | 432 | wait_for_completion(&mcspi_dma->dma_rx_completion); |
433 | dma_unmap_single(mcspi->dev, xfer->rx_dma, count, | ||
434 | DMA_FROM_DEVICE); | ||
435 | omap2_mcspi_set_enable(spi, 0); | ||
463 | 436 | ||
464 | if (l & OMAP2_MCSPI_CHCONF_TURBO) { | 437 | elements = element_count - 1; |
465 | elements--; | ||
466 | 438 | ||
467 | if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) | 439 | if (l & OMAP2_MCSPI_CHCONF_TURBO) { |
468 | & OMAP2_MCSPI_CHSTAT_RXS)) { | 440 | elements--; |
469 | u32 w; | ||
470 | |||
471 | w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); | ||
472 | if (word_len <= 8) | ||
473 | ((u8 *)xfer->rx_buf)[elements++] = w; | ||
474 | else if (word_len <= 16) | ||
475 | ((u16 *)xfer->rx_buf)[elements++] = w; | ||
476 | else /* word_len <= 32 */ | ||
477 | ((u32 *)xfer->rx_buf)[elements++] = w; | ||
478 | } else { | ||
479 | dev_err(&spi->dev, | ||
480 | "DMA RX penultimate word empty"); | ||
481 | count -= (word_len <= 8) ? 2 : | ||
482 | (word_len <= 16) ? 4 : | ||
483 | /* word_len <= 32 */ 8; | ||
484 | omap2_mcspi_set_enable(spi, 1); | ||
485 | return count; | ||
486 | } | ||
487 | } | ||
488 | 441 | ||
489 | if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) | 442 | if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) |
490 | & OMAP2_MCSPI_CHSTAT_RXS)) { | 443 | & OMAP2_MCSPI_CHSTAT_RXS)) { |
491 | u32 w; | 444 | u32 w; |
492 | 445 | ||
493 | w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); | 446 | w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); |
494 | if (word_len <= 8) | 447 | if (word_len <= 8) |
495 | ((u8 *)xfer->rx_buf)[elements] = w; | 448 | ((u8 *)xfer->rx_buf)[elements++] = w; |
496 | else if (word_len <= 16) | 449 | else if (word_len <= 16) |
497 | ((u16 *)xfer->rx_buf)[elements] = w; | 450 | ((u16 *)xfer->rx_buf)[elements++] = w; |
498 | else /* word_len <= 32 */ | 451 | else /* word_len <= 32 */ |
499 | ((u32 *)xfer->rx_buf)[elements] = w; | 452 | ((u32 *)xfer->rx_buf)[elements++] = w; |
500 | } else { | 453 | } else { |
501 | dev_err(&spi->dev, "DMA RX last word empty"); | 454 | dev_err(&spi->dev, "DMA RX penultimate word empty"); |
502 | count -= (word_len <= 8) ? 1 : | 455 | count -= (word_len <= 8) ? 2 : |
503 | (word_len <= 16) ? 2 : | 456 | (word_len <= 16) ? 4 : |
504 | /* word_len <= 32 */ 4; | 457 | /* word_len <= 32 */ 8; |
458 | omap2_mcspi_set_enable(spi, 1); | ||
459 | return count; | ||
505 | } | 460 | } |
506 | omap2_mcspi_set_enable(spi, 1); | ||
507 | } | 461 | } |
462 | if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) | ||
463 | & OMAP2_MCSPI_CHSTAT_RXS)) { | ||
464 | u32 w; | ||
465 | |||
466 | w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); | ||
467 | if (word_len <= 8) | ||
468 | ((u8 *)xfer->rx_buf)[elements] = w; | ||
469 | else if (word_len <= 16) | ||
470 | ((u16 *)xfer->rx_buf)[elements] = w; | ||
471 | else /* word_len <= 32 */ | ||
472 | ((u32 *)xfer->rx_buf)[elements] = w; | ||
473 | } else { | ||
474 | dev_err(&spi->dev, "DMA RX last word empty"); | ||
475 | count -= (word_len <= 8) ? 1 : | ||
476 | (word_len <= 16) ? 2 : | ||
477 | /* word_len <= 32 */ 4; | ||
478 | } | ||
479 | omap2_mcspi_set_enable(spi, 1); | ||
480 | return count; | ||
481 | } | ||
482 | |||
483 | static unsigned | ||
484 | omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | ||
485 | { | ||
486 | struct omap2_mcspi *mcspi; | ||
487 | struct omap2_mcspi_cs *cs = spi->controller_state; | ||
488 | struct omap2_mcspi_dma *mcspi_dma; | ||
489 | unsigned int count; | ||
490 | u32 l; | ||
491 | u8 *rx; | ||
492 | const u8 *tx; | ||
493 | struct dma_slave_config cfg; | ||
494 | enum dma_slave_buswidth width; | ||
495 | unsigned es; | ||
496 | |||
497 | mcspi = spi_master_get_devdata(spi->master); | ||
498 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; | ||
499 | l = mcspi_cached_chconf0(spi); | ||
500 | |||
501 | |||
502 | if (cs->word_len <= 8) { | ||
503 | width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
504 | es = 1; | ||
505 | } else if (cs->word_len <= 16) { | ||
506 | width = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
507 | es = 2; | ||
508 | } else { | ||
509 | width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
510 | es = 4; | ||
511 | } | ||
512 | |||
513 | memset(&cfg, 0, sizeof(cfg)); | ||
514 | cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0; | ||
515 | cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0; | ||
516 | cfg.src_addr_width = width; | ||
517 | cfg.dst_addr_width = width; | ||
518 | cfg.src_maxburst = 1; | ||
519 | cfg.dst_maxburst = 1; | ||
520 | |||
521 | rx = xfer->rx_buf; | ||
522 | tx = xfer->tx_buf; | ||
523 | |||
524 | count = xfer->len; | ||
525 | |||
526 | if (tx != NULL) | ||
527 | omap2_mcspi_tx_dma(spi, xfer, cfg); | ||
528 | |||
529 | if (rx != NULL) | ||
530 | return omap2_mcspi_rx_dma(spi, xfer, cfg, es); | ||
531 | |||
508 | return count; | 532 | return count; |
509 | } | 533 | } |
510 | 534 | ||
@@ -848,12 +872,13 @@ static int omap2_mcspi_setup(struct spi_device *spi) | |||
848 | return ret; | 872 | return ret; |
849 | } | 873 | } |
850 | 874 | ||
851 | ret = omap2_mcspi_enable_clocks(mcspi); | 875 | ret = pm_runtime_get_sync(mcspi->dev); |
852 | if (ret < 0) | 876 | if (ret < 0) |
853 | return ret; | 877 | return ret; |
854 | 878 | ||
855 | ret = omap2_mcspi_setup_transfer(spi, NULL); | 879 | ret = omap2_mcspi_setup_transfer(spi, NULL); |
856 | omap2_mcspi_disable_clocks(mcspi); | 880 | pm_runtime_mark_last_busy(mcspi->dev); |
881 | pm_runtime_put_autosuspend(mcspi->dev); | ||
857 | 882 | ||
858 | return ret; | 883 | return ret; |
859 | } | 884 | } |
@@ -1067,7 +1092,7 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) | |||
1067 | struct omap2_mcspi_regs *ctx = &mcspi->ctx; | 1092 | struct omap2_mcspi_regs *ctx = &mcspi->ctx; |
1068 | int ret = 0; | 1093 | int ret = 0; |
1069 | 1094 | ||
1070 | ret = omap2_mcspi_enable_clocks(mcspi); | 1095 | ret = pm_runtime_get_sync(mcspi->dev); |
1071 | if (ret < 0) | 1096 | if (ret < 0) |
1072 | return ret; | 1097 | return ret; |
1073 | 1098 | ||
@@ -1076,7 +1101,8 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) | |||
1076 | ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; | 1101 | ctx->wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; |
1077 | 1102 | ||
1078 | omap2_mcspi_set_master_mode(master); | 1103 | omap2_mcspi_set_master_mode(master); |
1079 | omap2_mcspi_disable_clocks(mcspi); | 1104 | pm_runtime_mark_last_busy(mcspi->dev); |
1105 | pm_runtime_put_autosuspend(mcspi->dev); | ||
1080 | return 0; | 1106 | return 0; |
1081 | } | 1107 | } |
1082 | 1108 | ||
@@ -1124,6 +1150,7 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) | |||
1124 | static int bus_num = 1; | 1150 | static int bus_num = 1; |
1125 | struct device_node *node = pdev->dev.of_node; | 1151 | struct device_node *node = pdev->dev.of_node; |
1126 | const struct of_device_id *match; | 1152 | const struct of_device_id *match; |
1153 | struct pinctrl *pinctrl; | ||
1127 | 1154 | ||
1128 | master = spi_alloc_master(&pdev->dev, sizeof *mcspi); | 1155 | master = spi_alloc_master(&pdev->dev, sizeof *mcspi); |
1129 | if (master == NULL) { | 1156 | if (master == NULL) { |
@@ -1219,6 +1246,11 @@ static int __devinit omap2_mcspi_probe(struct platform_device *pdev) | |||
1219 | if (status < 0) | 1246 | if (status < 0) |
1220 | goto dma_chnl_free; | 1247 | goto dma_chnl_free; |
1221 | 1248 | ||
1249 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
1250 | if (IS_ERR(pinctrl)) | ||
1251 | dev_warn(&pdev->dev, | ||
1252 | "pins are not configured from the driver\n"); | ||
1253 | |||
1222 | pm_runtime_use_autosuspend(&pdev->dev); | 1254 | pm_runtime_use_autosuspend(&pdev->dev); |
1223 | pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); | 1255 | pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); |
1224 | pm_runtime_enable(&pdev->dev); | 1256 | pm_runtime_enable(&pdev->dev); |
@@ -1238,7 +1270,6 @@ dma_chnl_free: | |||
1238 | kfree(mcspi->dma_channels); | 1270 | kfree(mcspi->dma_channels); |
1239 | free_master: | 1271 | free_master: |
1240 | spi_master_put(master); | 1272 | spi_master_put(master); |
1241 | platform_set_drvdata(pdev, NULL); | ||
1242 | return status; | 1273 | return status; |
1243 | } | 1274 | } |
1244 | 1275 | ||
@@ -1252,12 +1283,11 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev) | |||
1252 | mcspi = spi_master_get_devdata(master); | 1283 | mcspi = spi_master_get_devdata(master); |
1253 | dma_channels = mcspi->dma_channels; | 1284 | dma_channels = mcspi->dma_channels; |
1254 | 1285 | ||
1255 | omap2_mcspi_disable_clocks(mcspi); | 1286 | pm_runtime_put_sync(mcspi->dev); |
1256 | pm_runtime_disable(&pdev->dev); | 1287 | pm_runtime_disable(&pdev->dev); |
1257 | 1288 | ||
1258 | spi_unregister_master(master); | 1289 | spi_unregister_master(master); |
1259 | kfree(dma_channels); | 1290 | kfree(dma_channels); |
1260 | platform_set_drvdata(pdev, NULL); | ||
1261 | 1291 | ||
1262 | return 0; | 1292 | return 0; |
1263 | } | 1293 | } |
@@ -1278,20 +1308,21 @@ static int omap2_mcspi_resume(struct device *dev) | |||
1278 | struct omap2_mcspi_regs *ctx = &mcspi->ctx; | 1308 | struct omap2_mcspi_regs *ctx = &mcspi->ctx; |
1279 | struct omap2_mcspi_cs *cs; | 1309 | struct omap2_mcspi_cs *cs; |
1280 | 1310 | ||
1281 | omap2_mcspi_enable_clocks(mcspi); | 1311 | pm_runtime_get_sync(mcspi->dev); |
1282 | list_for_each_entry(cs, &ctx->cs, node) { | 1312 | list_for_each_entry(cs, &ctx->cs, node) { |
1283 | if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { | 1313 | if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) { |
1284 | /* | 1314 | /* |
1285 | * We need to toggle CS state for OMAP take this | 1315 | * We need to toggle CS state for OMAP take this |
1286 | * change in account. | 1316 | * change in account. |
1287 | */ | 1317 | */ |
1288 | MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1); | 1318 | cs->chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; |
1289 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); | 1319 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); |
1290 | MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0); | 1320 | cs->chconf0 &= ~OMAP2_MCSPI_CHCONF_FORCE; |
1291 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); | 1321 | __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); |
1292 | } | 1322 | } |
1293 | } | 1323 | } |
1294 | omap2_mcspi_disable_clocks(mcspi); | 1324 | pm_runtime_mark_last_busy(mcspi->dev); |
1325 | pm_runtime_put_autosuspend(mcspi->dev); | ||
1295 | return 0; | 1326 | return 0; |
1296 | } | 1327 | } |
1297 | #else | 1328 | #else |