diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:56:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:56:02 -0400 |
commit | b061c59c27e0385e53c961d9fbd18c1c078d9823 (patch) | |
tree | 56240ef8e98e9e4712ee58aa8e6e3d51f6ab001f /drivers/spi/amba-pl022.c | |
parent | 99f4065bac7b8c3f829334b4218a5c2e68cbe440 (diff) | |
parent | 568a60eda2e90a11bb3d7f8ef3f6800e9b60d4e5 (diff) |
Merge branch 'spi/next' of git://git.secretlab.ca/git/linux-2.6
* 'spi/next' of git://git.secretlab.ca/git/linux-2.6: (34 commits)
spi/dw_spi: move dw_spi.h into drivers/spi
spi/dw_spi: Fix missing header
gpio/langwell: Clear edge bit before handling
gpio/langwell: Simplify demux loop
gpio/langwell: Convert irq name space
gpio/langwell: Fix broken irq_eoi change.
gpio; Make Intel chipset gpio drivers depend on x86
gpio/cs5535-gpio: Fix section mismatch
spi/rtc-{ds1390,ds3234,m41t94}: Use spi_get_drvdata() for SPI devices
spi/davinci: Support DMA transfers larger than 65535 words
spi/davinci: Use correct length parameter to dma_map_single calls
gpio: Use __devexit at necessary places
gpio: add MODULE_DEVICE_TABLE to pch_gpio and ml_ioh_gpio
gpio/mcp23s08: support mcp23s17 variant
of_mmc_spi: add card detect irq support
spi/omap_mcspi: catch xfers of non-multiple SPI word size
spi/omap_mcspi: Off-by-one error in finding the right divisor
gpio/pca953x: Fix wrong pointer type
spi/pl022: rid dangling labels
spi: add support for SuperH SPI
...
Diffstat (limited to 'drivers/spi/amba-pl022.c')
-rw-r--r-- | drivers/spi/amba-pl022.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index 95e58c70a2c9..5c2b092a915e 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c | |||
@@ -329,15 +329,16 @@ struct vendor_data { | |||
329 | /** | 329 | /** |
330 | * struct pl022 - This is the private SSP driver data structure | 330 | * struct pl022 - This is the private SSP driver data structure |
331 | * @adev: AMBA device model hookup | 331 | * @adev: AMBA device model hookup |
332 | * @vendor: Vendor data for the IP block | 332 | * @vendor: vendor data for the IP block |
333 | * @phybase: The physical memory where the SSP device resides | 333 | * @phybase: the physical memory where the SSP device resides |
334 | * @virtbase: The virtual memory where the SSP is mapped | 334 | * @virtbase: the virtual memory where the SSP is mapped |
335 | * @clk: outgoing clock "SPICLK" for the SPI bus | ||
335 | * @master: SPI framework hookup | 336 | * @master: SPI framework hookup |
336 | * @master_info: controller-specific data from machine setup | 337 | * @master_info: controller-specific data from machine setup |
337 | * @regs: SSP controller register's virtual address | ||
338 | * @pump_messages: Work struct for scheduling work to the workqueue | ||
339 | * @lock: spinlock to syncronise access to driver data | ||
340 | * @workqueue: a workqueue on which any spi_message request is queued | 338 | * @workqueue: a workqueue on which any spi_message request is queued |
339 | * @pump_messages: work struct for scheduling work to the workqueue | ||
340 | * @queue_lock: spinlock to syncronise access to message queue | ||
341 | * @queue: message queue | ||
341 | * @busy: workqueue is busy | 342 | * @busy: workqueue is busy |
342 | * @running: workqueue is running | 343 | * @running: workqueue is running |
343 | * @pump_transfers: Tasklet used in Interrupt Transfer mode | 344 | * @pump_transfers: Tasklet used in Interrupt Transfer mode |
@@ -348,8 +349,14 @@ struct vendor_data { | |||
348 | * @tx_end: end position in TX buffer to be read | 349 | * @tx_end: end position in TX buffer to be read |
349 | * @rx: current position in RX buffer to be written | 350 | * @rx: current position in RX buffer to be written |
350 | * @rx_end: end position in RX buffer to be written | 351 | * @rx_end: end position in RX buffer to be written |
351 | * @readingtype: the type of read currently going on | 352 | * @read: the type of read currently going on |
352 | * @writingtype: the type or write currently going on | 353 | * @write: the type of write currently going on |
354 | * @exp_fifo_level: expected FIFO level | ||
355 | * @dma_rx_channel: optional channel for RX DMA | ||
356 | * @dma_tx_channel: optional channel for TX DMA | ||
357 | * @sgt_rx: scattertable for the RX transfer | ||
358 | * @sgt_tx: scattertable for the TX transfer | ||
359 | * @dummypage: a dummy page used for driving data on the bus with DMA | ||
353 | */ | 360 | */ |
354 | struct pl022 { | 361 | struct pl022 { |
355 | struct amba_device *adev; | 362 | struct amba_device *adev; |
@@ -397,8 +404,8 @@ struct pl022 { | |||
397 | * @cpsr: Value of Clock prescale register | 404 | * @cpsr: Value of Clock prescale register |
398 | * @n_bytes: how many bytes(power of 2) reqd for a given data width of client | 405 | * @n_bytes: how many bytes(power of 2) reqd for a given data width of client |
399 | * @enable_dma: Whether to enable DMA or not | 406 | * @enable_dma: Whether to enable DMA or not |
400 | * @write: function ptr to be used to write when doing xfer for this chip | ||
401 | * @read: function ptr to be used to read when doing xfer for this chip | 407 | * @read: function ptr to be used to read when doing xfer for this chip |
408 | * @write: function ptr to be used to write when doing xfer for this chip | ||
402 | * @cs_control: chip select callback provided by chip | 409 | * @cs_control: chip select callback provided by chip |
403 | * @xfer_type: polling/interrupt/DMA | 410 | * @xfer_type: polling/interrupt/DMA |
404 | * | 411 | * |
@@ -508,9 +515,10 @@ static void giveback(struct pl022 *pl022) | |||
508 | msg->state = NULL; | 515 | msg->state = NULL; |
509 | if (msg->complete) | 516 | if (msg->complete) |
510 | msg->complete(msg->context); | 517 | msg->complete(msg->context); |
511 | /* This message is completed, so let's turn off the clocks! */ | 518 | /* This message is completed, so let's turn off the clocks & power */ |
512 | clk_disable(pl022->clk); | 519 | clk_disable(pl022->clk); |
513 | amba_pclk_disable(pl022->adev); | 520 | amba_pclk_disable(pl022->adev); |
521 | amba_vcore_disable(pl022->adev); | ||
514 | } | 522 | } |
515 | 523 | ||
516 | /** | 524 | /** |
@@ -917,7 +925,6 @@ static int configure_dma(struct pl022 *pl022) | |||
917 | struct dma_chan *txchan = pl022->dma_tx_channel; | 925 | struct dma_chan *txchan = pl022->dma_tx_channel; |
918 | struct dma_async_tx_descriptor *rxdesc; | 926 | struct dma_async_tx_descriptor *rxdesc; |
919 | struct dma_async_tx_descriptor *txdesc; | 927 | struct dma_async_tx_descriptor *txdesc; |
920 | dma_cookie_t cookie; | ||
921 | 928 | ||
922 | /* Check that the channels are available */ | 929 | /* Check that the channels are available */ |
923 | if (!rxchan || !txchan) | 930 | if (!rxchan || !txchan) |
@@ -962,10 +969,8 @@ static int configure_dma(struct pl022 *pl022) | |||
962 | tx_conf.dst_addr_width = rx_conf.src_addr_width; | 969 | tx_conf.dst_addr_width = rx_conf.src_addr_width; |
963 | BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width); | 970 | BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width); |
964 | 971 | ||
965 | rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG, | 972 | dmaengine_slave_config(rxchan, &rx_conf); |
966 | (unsigned long) &rx_conf); | 973 | dmaengine_slave_config(txchan, &tx_conf); |
967 | txchan->device->device_control(txchan, DMA_SLAVE_CONFIG, | ||
968 | (unsigned long) &tx_conf); | ||
969 | 974 | ||
970 | /* Create sglists for the transfers */ | 975 | /* Create sglists for the transfers */ |
971 | pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; | 976 | pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1; |
@@ -1018,23 +1023,17 @@ static int configure_dma(struct pl022 *pl022) | |||
1018 | rxdesc->callback_param = pl022; | 1023 | rxdesc->callback_param = pl022; |
1019 | 1024 | ||
1020 | /* Submit and fire RX and TX with TX last so we're ready to read! */ | 1025 | /* Submit and fire RX and TX with TX last so we're ready to read! */ |
1021 | cookie = rxdesc->tx_submit(rxdesc); | 1026 | dmaengine_submit(rxdesc); |
1022 | if (dma_submit_error(cookie)) | 1027 | dmaengine_submit(txdesc); |
1023 | goto err_submit_rx; | 1028 | dma_async_issue_pending(rxchan); |
1024 | cookie = txdesc->tx_submit(txdesc); | 1029 | dma_async_issue_pending(txchan); |
1025 | if (dma_submit_error(cookie)) | ||
1026 | goto err_submit_tx; | ||
1027 | rxchan->device->device_issue_pending(rxchan); | ||
1028 | txchan->device->device_issue_pending(txchan); | ||
1029 | 1030 | ||
1030 | return 0; | 1031 | return 0; |
1031 | 1032 | ||
1032 | err_submit_tx: | ||
1033 | err_submit_rx: | ||
1034 | err_txdesc: | 1033 | err_txdesc: |
1035 | txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0); | 1034 | dmaengine_terminate_all(txchan); |
1036 | err_rxdesc: | 1035 | err_rxdesc: |
1037 | rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0); | 1036 | dmaengine_terminate_all(rxchan); |
1038 | dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl, | 1037 | dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl, |
1039 | pl022->sgt_tx.nents, DMA_TO_DEVICE); | 1038 | pl022->sgt_tx.nents, DMA_TO_DEVICE); |
1040 | err_tx_sgmap: | 1039 | err_tx_sgmap: |
@@ -1101,8 +1100,8 @@ static void terminate_dma(struct pl022 *pl022) | |||
1101 | struct dma_chan *rxchan = pl022->dma_rx_channel; | 1100 | struct dma_chan *rxchan = pl022->dma_rx_channel; |
1102 | struct dma_chan *txchan = pl022->dma_tx_channel; | 1101 | struct dma_chan *txchan = pl022->dma_tx_channel; |
1103 | 1102 | ||
1104 | rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0); | 1103 | dmaengine_terminate_all(rxchan); |
1105 | txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0); | 1104 | dmaengine_terminate_all(txchan); |
1106 | unmap_free_dma_scatter(pl022); | 1105 | unmap_free_dma_scatter(pl022); |
1107 | } | 1106 | } |
1108 | 1107 | ||
@@ -1482,9 +1481,11 @@ static void pump_messages(struct work_struct *work) | |||
1482 | /* Setup the SPI using the per chip configuration */ | 1481 | /* Setup the SPI using the per chip configuration */ |
1483 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); | 1482 | pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); |
1484 | /* | 1483 | /* |
1485 | * We enable the clocks here, then the clocks will be disabled when | 1484 | * We enable the core voltage and clocks here, then the clocks |
1486 | * giveback() is called in each method (poll/interrupt/DMA) | 1485 | * and core will be disabled when giveback() is called in each method |
1486 | * (poll/interrupt/DMA) | ||
1487 | */ | 1487 | */ |
1488 | amba_vcore_enable(pl022->adev); | ||
1488 | amba_pclk_enable(pl022->adev); | 1489 | amba_pclk_enable(pl022->adev); |
1489 | clk_enable(pl022->clk); | 1490 | clk_enable(pl022->clk); |
1490 | restore_state(pl022); | 1491 | restore_state(pl022); |
@@ -1910,8 +1911,6 @@ static int pl022_setup(struct spi_device *spi) | |||
1910 | && ((pl022->master_info)->enable_dma)) { | 1911 | && ((pl022->master_info)->enable_dma)) { |
1911 | chip->enable_dma = true; | 1912 | chip->enable_dma = true; |
1912 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); | 1913 | dev_dbg(&spi->dev, "DMA mode set in controller state\n"); |
1913 | if (status < 0) | ||
1914 | goto err_config_params; | ||
1915 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | 1914 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, |
1916 | SSP_DMACR_MASK_RXDMAE, 0); | 1915 | SSP_DMACR_MASK_RXDMAE, 0); |
1917 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, | 1916 | SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, |
@@ -2130,8 +2129,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
2130 | goto err_spi_register; | 2129 | goto err_spi_register; |
2131 | } | 2130 | } |
2132 | dev_dbg(dev, "probe succeded\n"); | 2131 | dev_dbg(dev, "probe succeded\n"); |
2133 | /* Disable the silicon block pclk and clock it when needed */ | 2132 | /* |
2133 | * Disable the silicon block pclk and any voltage domain and just | ||
2134 | * power it up and clock it when it's needed | ||
2135 | */ | ||
2134 | amba_pclk_disable(adev); | 2136 | amba_pclk_disable(adev); |
2137 | amba_vcore_disable(adev); | ||
2135 | return 0; | 2138 | return 0; |
2136 | 2139 | ||
2137 | err_spi_register: | 2140 | err_spi_register: |
@@ -2196,9 +2199,11 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state) | |||
2196 | return status; | 2199 | return status; |
2197 | } | 2200 | } |
2198 | 2201 | ||
2202 | amba_vcore_enable(adev); | ||
2199 | amba_pclk_enable(adev); | 2203 | amba_pclk_enable(adev); |
2200 | load_ssp_default_config(pl022); | 2204 | load_ssp_default_config(pl022); |
2201 | amba_pclk_disable(adev); | 2205 | amba_pclk_disable(adev); |
2206 | amba_vcore_disable(adev); | ||
2202 | dev_dbg(&adev->dev, "suspended\n"); | 2207 | dev_dbg(&adev->dev, "suspended\n"); |
2203 | return 0; | 2208 | return 0; |
2204 | } | 2209 | } |