diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 15:57:41 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 15:57:41 -0400 |
| commit | 0082c16e3a6d87c7b156ccf21f5e6c448b102809 (patch) | |
| tree | 29e12a84578b23d403ea59021fe311ee38479407 | |
| parent | 1f03bf06e4e3b8ed9a69e7fc4cdb1be4c6c6c819 (diff) | |
| parent | 8ceffa7c4a4c378d8e371fe2f444656e75390b34 (diff) | |
Merge tag 'spi-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc
Pull spi updates from Mark Brown:
"Since Grant is even more specacularly busy than usual for the time
being I've been collecting SPI patches for him for this release -
probably things will revert back to Grant before the next release.
There's nothing too exciting here, mostly it's simple driver specific
stuff:
- Add spi: to the modaliases of SPI devices to provide namespacing.
- A driver for AD-FMCOMMS1-EBZ.
- DT binding for Orion.
- Fixes and cleanups for i.MX, PL0022, OMAP and bitbang drivers.
There may be a few more fixes I've missed, people keep sending me new
things."
* tag 'spi-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc:
spi/orion: remove uneeded spi_info
spi/bcm63xx: fix clock configuration selection
spi/orion: add device tree binding
spi/omap2: mark omap2_mcspi_master_setup as __devinit
spi: omap2-mcspi: Fix the below warning
spi: Add AD-FMCOMMS1-EBZ I2C-SPI bridge driver
spi/imx: use gpio_is_valid to determine if a gpio is valid
spi/imx: remove redundant config.speed_hz setting
spi/gpio: start with CS non-active
spi: tegra: use dmaengine based dma driver
spi/pl022: cleanup pl022 header documentation
spi/pl022: enable runtime PM
spi/pl022: delete DB5500 support
spi/pl022: disable port when unused
spi: Add "spi:" prefix to modalias attribute of spi devices
| -rw-r--r-- | Documentation/devicetree/bindings/spi/spi-orion.txt | 19 | ||||
| -rw-r--r-- | drivers/spi/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/spi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/spi/spi-bcm63xx.c | 2 | ||||
| -rw-r--r-- | drivers/spi/spi-gpio.c | 3 | ||||
| -rw-r--r-- | drivers/spi/spi-imx.c | 14 | ||||
| -rw-r--r-- | drivers/spi/spi-omap2-mcspi.c | 8 | ||||
| -rw-r--r-- | drivers/spi/spi-orion.c | 22 | ||||
| -rw-r--r-- | drivers/spi/spi-pl022.c | 23 | ||||
| -rw-r--r-- | drivers/spi/spi-tegra.c | 89 | ||||
| -rw-r--r-- | drivers/spi/spi-xcomm.c | 276 | ||||
| -rw-r--r-- | drivers/spi/spi.c | 2 | ||||
| -rw-r--r-- | include/linux/amba/pl022.h | 9 |
13 files changed, 430 insertions, 47 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-orion.txt b/Documentation/devicetree/bindings/spi/spi-orion.txt new file mode 100644 index 000000000000..a3ff50fc76fb --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-orion.txt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | Marvell Orion SPI device | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : should be "marvell,orion-spi". | ||
| 5 | - reg : offset and length of the register set for the device | ||
| 6 | - cell-index : Which of multiple SPI controllers is this. | ||
| 7 | Optional properties: | ||
| 8 | - interrupts : Is currently not used. | ||
| 9 | |||
| 10 | Example: | ||
| 11 | spi@10600 { | ||
| 12 | compatible = "marvell,orion-spi"; | ||
| 13 | #address-cells = <1>; | ||
| 14 | #size-cells = <0>; | ||
| 15 | cell-index = <0>; | ||
| 16 | reg = <0x10600 0x28>; | ||
| 17 | interrupts = <23>; | ||
| 18 | status = "disabled"; | ||
| 19 | }; | ||
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index cb90bc62d0a9..4cde4fb0cd6c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
| @@ -357,7 +357,7 @@ config SPI_STMP3XXX | |||
| 357 | 357 | ||
| 358 | config SPI_TEGRA | 358 | config SPI_TEGRA |
| 359 | tristate "Nvidia Tegra SPI controller" | 359 | tristate "Nvidia Tegra SPI controller" |
| 360 | depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA | 360 | depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA) |
| 361 | help | 361 | help |
| 362 | SPI driver for NVidia Tegra SoCs | 362 | SPI driver for NVidia Tegra SoCs |
| 363 | 363 | ||
| @@ -384,6 +384,13 @@ config SPI_TXX9 | |||
| 384 | help | 384 | help |
| 385 | SPI driver for Toshiba TXx9 MIPS SoCs | 385 | SPI driver for Toshiba TXx9 MIPS SoCs |
| 386 | 386 | ||
| 387 | config SPI_XCOMM | ||
| 388 | tristate "Analog Devices AD-FMCOMMS1-EBZ SPI-I2C-bridge driver" | ||
| 389 | depends on I2C | ||
| 390 | help | ||
| 391 | Support for the SPI-I2C bridge found on the Analog Devices | ||
| 392 | AD-FMCOMMS1-EBZ board. | ||
| 393 | |||
| 387 | config SPI_XILINX | 394 | config SPI_XILINX |
| 388 | tristate "Xilinx SPI controller common module" | 395 | tristate "Xilinx SPI controller common module" |
| 389 | depends on HAS_IOMEM && EXPERIMENTAL | 396 | depends on HAS_IOMEM && EXPERIMENTAL |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 9d75d2198ff5..273f50d1127a 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
| @@ -61,5 +61,6 @@ obj-$(CONFIG_SPI_TI_SSP) += spi-ti-ssp.o | |||
| 61 | obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o | 61 | obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o |
| 62 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o | 62 | obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o |
| 63 | obj-$(CONFIG_SPI_TXX9) += spi-txx9.o | 63 | obj-$(CONFIG_SPI_TXX9) += spi-txx9.o |
| 64 | obj-$(CONFIG_SPI_XCOMM) += spi-xcomm.o | ||
| 64 | obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o | 65 | obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o |
| 65 | 66 | ||
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 7491971139a6..6e25ef1bce91 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c | |||
| @@ -129,7 +129,7 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, | |||
| 129 | 129 | ||
| 130 | /* Find the closest clock configuration */ | 130 | /* Find the closest clock configuration */ |
| 131 | for (i = 0; i < SPI_CLK_MASK; i++) { | 131 | for (i = 0; i < SPI_CLK_MASK; i++) { |
| 132 | if (hz <= bcm63xx_spi_freq_table[i][0]) { | 132 | if (hz >= bcm63xx_spi_freq_table[i][0]) { |
| 133 | clk_cfg = bcm63xx_spi_freq_table[i][1]; | 133 | clk_cfg = bcm63xx_spi_freq_table[i][1]; |
| 134 | break; | 134 | break; |
| 135 | } | 135 | } |
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0094c645ff0d..0b56cfc71fab 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c | |||
| @@ -235,7 +235,8 @@ static int spi_gpio_setup(struct spi_device *spi) | |||
| 235 | status = gpio_request(cs, dev_name(&spi->dev)); | 235 | status = gpio_request(cs, dev_name(&spi->dev)); |
| 236 | if (status) | 236 | if (status) |
| 237 | return status; | 237 | return status; |
| 238 | status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); | 238 | status = gpio_direction_output(cs, |
| 239 | !(spi->mode & SPI_CS_HIGH)); | ||
| 239 | } | 240 | } |
| 240 | } | 241 | } |
| 241 | if (!status) | 242 | if (!status) |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 47877d687614..e834ff8c0188 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
| @@ -626,7 +626,7 @@ static void spi_imx_chipselect(struct spi_device *spi, int is_active) | |||
| 626 | int active = is_active != BITBANG_CS_INACTIVE; | 626 | int active = is_active != BITBANG_CS_INACTIVE; |
| 627 | int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH); | 627 | int dev_is_lowactive = !(spi->mode & SPI_CS_HIGH); |
| 628 | 628 | ||
| 629 | if (gpio < 0) | 629 | if (!gpio_is_valid(gpio)) |
| 630 | return; | 630 | return; |
| 631 | 631 | ||
| 632 | gpio_set_value(gpio, dev_is_lowactive ^ active); | 632 | gpio_set_value(gpio, dev_is_lowactive ^ active); |
| @@ -688,8 +688,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, | |||
| 688 | config.speed_hz = spi->max_speed_hz; | 688 | config.speed_hz = spi->max_speed_hz; |
| 689 | if (!config.bpw) | 689 | if (!config.bpw) |
| 690 | config.bpw = spi->bits_per_word; | 690 | config.bpw = spi->bits_per_word; |
| 691 | if (!config.speed_hz) | ||
| 692 | config.speed_hz = spi->max_speed_hz; | ||
| 693 | 691 | ||
| 694 | /* Initialize the functions for transfer */ | 692 | /* Initialize the functions for transfer */ |
| 695 | if (config.bpw <= 8) { | 693 | if (config.bpw <= 8) { |
| @@ -738,7 +736,7 @@ static int spi_imx_setup(struct spi_device *spi) | |||
| 738 | dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__, | 736 | dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", __func__, |
| 739 | spi->mode, spi->bits_per_word, spi->max_speed_hz); | 737 | spi->mode, spi->bits_per_word, spi->max_speed_hz); |
| 740 | 738 | ||
| 741 | if (gpio >= 0) | 739 | if (gpio_is_valid(gpio)) |
| 742 | gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); | 740 | gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); |
| 743 | 741 | ||
| 744 | spi_imx_chipselect(spi, BITBANG_CS_INACTIVE); | 742 | spi_imx_chipselect(spi, BITBANG_CS_INACTIVE); |
| @@ -791,11 +789,11 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
| 791 | 789 | ||
| 792 | for (i = 0; i < master->num_chipselect; i++) { | 790 | for (i = 0; i < master->num_chipselect; i++) { |
| 793 | int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); | 791 | int cs_gpio = of_get_named_gpio(np, "cs-gpios", i); |
| 794 | if (cs_gpio < 0 && mxc_platform_info) | 792 | if (!gpio_is_valid(cs_gpio) && mxc_platform_info) |
| 795 | cs_gpio = mxc_platform_info->chipselect[i]; | 793 | cs_gpio = mxc_platform_info->chipselect[i]; |
| 796 | 794 | ||
| 797 | spi_imx->chipselect[i] = cs_gpio; | 795 | spi_imx->chipselect[i] = cs_gpio; |
| 798 | if (cs_gpio < 0) | 796 | if (!gpio_is_valid(cs_gpio)) |
| 799 | continue; | 797 | continue; |
| 800 | 798 | ||
| 801 | ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); | 799 | ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); |
| @@ -897,7 +895,7 @@ out_release_mem: | |||
| 897 | release_mem_region(res->start, resource_size(res)); | 895 | release_mem_region(res->start, resource_size(res)); |
| 898 | out_gpio_free: | 896 | out_gpio_free: |
| 899 | while (--i >= 0) { | 897 | while (--i >= 0) { |
| 900 | if (spi_imx->chipselect[i] >= 0) | 898 | if (gpio_is_valid(spi_imx->chipselect[i])) |
| 901 | gpio_free(spi_imx->chipselect[i]); | 899 | gpio_free(spi_imx->chipselect[i]); |
| 902 | } | 900 | } |
| 903 | spi_master_put(master); | 901 | spi_master_put(master); |
| @@ -922,7 +920,7 @@ static int __devexit spi_imx_remove(struct platform_device *pdev) | |||
| 922 | iounmap(spi_imx->base); | 920 | iounmap(spi_imx->base); |
| 923 | 921 | ||
| 924 | for (i = 0; i < master->num_chipselect; i++) | 922 | for (i = 0; i < master->num_chipselect; i++) |
| 925 | if (spi_imx->chipselect[i] >= 0) | 923 | if (gpio_is_valid(spi_imx->chipselect[i])) |
| 926 | gpio_free(spi_imx->chipselect[i]); | 924 | gpio_free(spi_imx->chipselect[i]); |
| 927 | 925 | ||
| 928 | spi_master_put(master); | 926 | spi_master_put(master); |
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 0c73dd4f43a0..7d46b15e1520 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c | |||
| @@ -388,7 +388,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
| 388 | 388 | ||
| 389 | if (tx != NULL) { | 389 | if (tx != NULL) { |
| 390 | wait_for_completion(&mcspi_dma->dma_tx_completion); | 390 | wait_for_completion(&mcspi_dma->dma_tx_completion); |
| 391 | dma_unmap_single(&spi->dev, xfer->tx_dma, count, DMA_TO_DEVICE); | 391 | dma_unmap_single(mcspi->dev, xfer->tx_dma, count, |
| 392 | DMA_TO_DEVICE); | ||
| 392 | 393 | ||
| 393 | /* for TX_ONLY mode, be sure all words have shifted out */ | 394 | /* for TX_ONLY mode, be sure all words have shifted out */ |
| 394 | if (rx == NULL) { | 395 | if (rx == NULL) { |
| @@ -403,7 +404,8 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) | |||
| 403 | 404 | ||
| 404 | if (rx != NULL) { | 405 | if (rx != NULL) { |
| 405 | wait_for_completion(&mcspi_dma->dma_rx_completion); | 406 | wait_for_completion(&mcspi_dma->dma_rx_completion); |
| 406 | dma_unmap_single(&spi->dev, xfer->rx_dma, count, DMA_FROM_DEVICE); | 407 | dma_unmap_single(mcspi->dev, xfer->rx_dma, count, |
| 408 | DMA_FROM_DEVICE); | ||
| 407 | omap2_mcspi_set_enable(spi, 0); | 409 | omap2_mcspi_set_enable(spi, 0); |
| 408 | 410 | ||
| 409 | if (l & OMAP2_MCSPI_CHCONF_TURBO) { | 411 | if (l & OMAP2_MCSPI_CHCONF_TURBO) { |
| @@ -1032,7 +1034,7 @@ static int omap2_mcspi_transfer_one_message(struct spi_master *master, | |||
| 1032 | return 0; | 1034 | return 0; |
| 1033 | } | 1035 | } |
| 1034 | 1036 | ||
| 1035 | static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) | 1037 | static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) |
| 1036 | { | 1038 | { |
| 1037 | struct spi_master *master = mcspi->master; | 1039 | struct spi_master *master = mcspi->master; |
| 1038 | struct omap2_mcspi_regs *ctx = &mcspi->ctx; | 1040 | struct omap2_mcspi_regs *ctx = &mcspi->ctx; |
diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index dfd04e91fa6d..9b0caddce503 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
| 19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 20 | #include <linux/of.h> | ||
| 20 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
| 21 | #include <asm/unaligned.h> | 22 | #include <asm/unaligned.h> |
| 22 | 23 | ||
| @@ -45,7 +46,6 @@ struct orion_spi { | |||
| 45 | void __iomem *base; | 46 | void __iomem *base; |
| 46 | unsigned int max_speed; | 47 | unsigned int max_speed; |
| 47 | unsigned int min_speed; | 48 | unsigned int min_speed; |
| 48 | struct orion_spi_info *spi_info; | ||
| 49 | struct clk *clk; | 49 | struct clk *clk; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| @@ -450,11 +450,10 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
| 450 | struct spi_master *master; | 450 | struct spi_master *master; |
| 451 | struct orion_spi *spi; | 451 | struct orion_spi *spi; |
| 452 | struct resource *r; | 452 | struct resource *r; |
| 453 | struct orion_spi_info *spi_info; | ||
| 454 | unsigned long tclk_hz; | 453 | unsigned long tclk_hz; |
| 455 | int status = 0; | 454 | int status = 0; |
| 456 | 455 | const u32 *iprop; | |
| 457 | spi_info = pdev->dev.platform_data; | 456 | int size; |
| 458 | 457 | ||
| 459 | master = spi_alloc_master(&pdev->dev, sizeof *spi); | 458 | master = spi_alloc_master(&pdev->dev, sizeof *spi); |
| 460 | if (master == NULL) { | 459 | if (master == NULL) { |
| @@ -464,6 +463,12 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
| 464 | 463 | ||
| 465 | if (pdev->id != -1) | 464 | if (pdev->id != -1) |
| 466 | master->bus_num = pdev->id; | 465 | master->bus_num = pdev->id; |
| 466 | if (pdev->dev.of_node) { | ||
| 467 | iprop = of_get_property(pdev->dev.of_node, "cell-index", | ||
| 468 | &size); | ||
| 469 | if (iprop && size == sizeof(*iprop)) | ||
| 470 | master->bus_num = *iprop; | ||
| 471 | } | ||
| 467 | 472 | ||
| 468 | /* we support only mode 0, and no options */ | 473 | /* we support only mode 0, and no options */ |
| 469 | master->mode_bits = 0; | 474 | master->mode_bits = 0; |
| @@ -476,7 +481,6 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
| 476 | 481 | ||
| 477 | spi = spi_master_get_devdata(master); | 482 | spi = spi_master_get_devdata(master); |
| 478 | spi->master = master; | 483 | spi->master = master; |
| 479 | spi->spi_info = spi_info; | ||
| 480 | 484 | ||
| 481 | spi->clk = clk_get(&pdev->dev, NULL); | 485 | spi->clk = clk_get(&pdev->dev, NULL); |
| 482 | if (IS_ERR(spi->clk)) { | 486 | if (IS_ERR(spi->clk)) { |
| @@ -511,6 +515,7 @@ static int __init orion_spi_probe(struct platform_device *pdev) | |||
| 511 | if (orion_spi_reset(spi) < 0) | 515 | if (orion_spi_reset(spi) < 0) |
| 512 | goto out_rel_mem; | 516 | goto out_rel_mem; |
| 513 | 517 | ||
| 518 | master->dev.of_node = pdev->dev.of_node; | ||
| 514 | status = spi_register_master(master); | 519 | status = spi_register_master(master); |
| 515 | if (status < 0) | 520 | if (status < 0) |
| 516 | goto out_rel_mem; | 521 | goto out_rel_mem; |
| @@ -552,10 +557,17 @@ static int __exit orion_spi_remove(struct platform_device *pdev) | |||
| 552 | 557 | ||
| 553 | MODULE_ALIAS("platform:" DRIVER_NAME); | 558 | MODULE_ALIAS("platform:" DRIVER_NAME); |
| 554 | 559 | ||
| 560 | static const struct of_device_id orion_spi_of_match_table[] __devinitdata = { | ||
| 561 | { .compatible = "marvell,orion-spi", }, | ||
| 562 | {} | ||
| 563 | }; | ||
| 564 | MODULE_DEVICE_TABLE(of, orion_spi_of_match_table); | ||
| 565 | |||
| 555 | static struct platform_driver orion_spi_driver = { | 566 | static struct platform_driver orion_spi_driver = { |
| 556 | .driver = { | 567 | .driver = { |
| 557 | .name = DRIVER_NAME, | 568 | .name = DRIVER_NAME, |
| 558 | .owner = THIS_MODULE, | 569 | .owner = THIS_MODULE, |
| 570 | .of_match_table = of_match_ptr(orion_spi_of_match_table), | ||
| 559 | }, | 571 | }, |
| 560 | .remove = __exit_p(orion_spi_remove), | 572 | .remove = __exit_p(orion_spi_remove), |
| 561 | }; | 573 | }; |
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 400ae2121a2a..aab518ec2bbc 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c | |||
| @@ -489,6 +489,11 @@ static void giveback(struct pl022 *pl022) | |||
| 489 | pl022->cur_transfer = NULL; | 489 | pl022->cur_transfer = NULL; |
| 490 | pl022->cur_chip = NULL; | 490 | pl022->cur_chip = NULL; |
| 491 | spi_finalize_current_message(pl022->master); | 491 | spi_finalize_current_message(pl022->master); |
| 492 | |||
| 493 | /* disable the SPI/SSP operation */ | ||
| 494 | writew((readw(SSP_CR1(pl022->virtbase)) & | ||
| 495 | (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); | ||
| 496 | |||
| 492 | } | 497 | } |
| 493 | 498 | ||
| 494 | /** | 499 | /** |
| @@ -2048,6 +2053,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id) | |||
| 2048 | printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", | 2053 | printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n", |
| 2049 | adev->res.start, pl022->virtbase); | 2054 | adev->res.start, pl022->virtbase); |
| 2050 | 2055 | ||
| 2056 | pm_runtime_enable(dev); | ||
| 2057 | pm_runtime_resume(dev); | ||
| 2058 | |||
| 2051 | pl022->clk = clk_get(&adev->dev, NULL); | 2059 | pl022->clk = clk_get(&adev->dev, NULL); |
| 2052 | if (IS_ERR(pl022->clk)) { | 2060 | if (IS_ERR(pl022->clk)) { |
| 2053 | status = PTR_ERR(pl022->clk); | 2061 | status = PTR_ERR(pl022->clk); |
| @@ -2158,6 +2166,7 @@ pl022_remove(struct amba_device *adev) | |||
| 2158 | clk_disable(pl022->clk); | 2166 | clk_disable(pl022->clk); |
| 2159 | clk_unprepare(pl022->clk); | 2167 | clk_unprepare(pl022->clk); |
| 2160 | clk_put(pl022->clk); | 2168 | clk_put(pl022->clk); |
| 2169 | pm_runtime_disable(&adev->dev); | ||
| 2161 | iounmap(pl022->virtbase); | 2170 | iounmap(pl022->virtbase); |
| 2162 | amba_release_regions(adev); | 2171 | amba_release_regions(adev); |
| 2163 | tasklet_disable(&pl022->pump_transfers); | 2172 | tasklet_disable(&pl022->pump_transfers); |
| @@ -2251,15 +2260,6 @@ static struct vendor_data vendor_st_pl023 = { | |||
| 2251 | .loopback = false, | 2260 | .loopback = false, |
| 2252 | }; | 2261 | }; |
| 2253 | 2262 | ||
| 2254 | static struct vendor_data vendor_db5500_pl023 = { | ||
| 2255 | .fifodepth = 32, | ||
| 2256 | .max_bpw = 32, | ||
| 2257 | .unidir = false, | ||
| 2258 | .extended_cr = true, | ||
| 2259 | .pl023 = true, | ||
| 2260 | .loopback = true, | ||
| 2261 | }; | ||
| 2262 | |||
| 2263 | static struct amba_id pl022_ids[] = { | 2263 | static struct amba_id pl022_ids[] = { |
| 2264 | { | 2264 | { |
| 2265 | /* | 2265 | /* |
| @@ -2291,11 +2291,6 @@ static struct amba_id pl022_ids[] = { | |||
| 2291 | .mask = 0xffffffff, | 2291 | .mask = 0xffffffff, |
| 2292 | .data = &vendor_st_pl023, | 2292 | .data = &vendor_st_pl023, |
| 2293 | }, | 2293 | }, |
| 2294 | { | ||
| 2295 | .id = 0x10080023, | ||
| 2296 | .mask = 0xffffffff, | ||
| 2297 | .data = &vendor_db5500_pl023, | ||
| 2298 | }, | ||
| 2299 | { 0, 0 }, | 2294 | { 0, 0 }, |
| 2300 | }; | 2295 | }; |
| 2301 | 2296 | ||
diff --git a/drivers/spi/spi-tegra.c b/drivers/spi/spi-tegra.c index 7f99ff3553a6..ef52c1c6f5c5 100644 --- a/drivers/spi/spi-tegra.c +++ b/drivers/spi/spi-tegra.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 31 | 31 | ||
| 32 | #include <linux/spi/spi.h> | 32 | #include <linux/spi/spi.h> |
| 33 | #include <linux/dmaengine.h> | ||
| 33 | 34 | ||
| 34 | #include <mach/dma.h> | 35 | #include <mach/dma.h> |
| 35 | 36 | ||
| @@ -162,12 +163,23 @@ struct spi_tegra_data { | |||
| 162 | * require transfers to be 4 byte aligned we need a bounce buffer | 163 | * require transfers to be 4 byte aligned we need a bounce buffer |
| 163 | * for the generic case. | 164 | * for the generic case. |
| 164 | */ | 165 | */ |
| 166 | int dma_req_len; | ||
| 167 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 165 | struct tegra_dma_req rx_dma_req; | 168 | struct tegra_dma_req rx_dma_req; |
| 166 | struct tegra_dma_channel *rx_dma; | 169 | struct tegra_dma_channel *rx_dma; |
| 170 | #else | ||
| 171 | struct dma_chan *rx_dma; | ||
| 172 | struct dma_slave_config sconfig; | ||
| 173 | struct dma_async_tx_descriptor *rx_dma_desc; | ||
| 174 | dma_cookie_t rx_cookie; | ||
| 175 | #endif | ||
| 167 | u32 *rx_bb; | 176 | u32 *rx_bb; |
| 168 | dma_addr_t rx_bb_phys; | 177 | dma_addr_t rx_bb_phys; |
| 169 | }; | 178 | }; |
| 170 | 179 | ||
| 180 | #if !defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 181 | static void tegra_spi_rx_dma_complete(void *args); | ||
| 182 | #endif | ||
| 171 | 183 | ||
| 172 | static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi, | 184 | static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi, |
| 173 | unsigned long reg) | 185 | unsigned long reg) |
| @@ -190,10 +202,24 @@ static void spi_tegra_go(struct spi_tegra_data *tspi) | |||
| 190 | 202 | ||
| 191 | val = spi_tegra_readl(tspi, SLINK_DMA_CTL); | 203 | val = spi_tegra_readl(tspi, SLINK_DMA_CTL); |
| 192 | val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN; | 204 | val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN; |
| 193 | val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1); | 205 | val |= SLINK_DMA_BLOCK_SIZE(tspi->dma_req_len / 4 - 1); |
| 194 | spi_tegra_writel(tspi, val, SLINK_DMA_CTL); | 206 | spi_tegra_writel(tspi, val, SLINK_DMA_CTL); |
| 195 | 207 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | |
| 208 | tspi->rx_dma_req.size = tspi->dma_req_len; | ||
| 196 | tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req); | 209 | tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req); |
| 210 | #else | ||
| 211 | tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma, | ||
| 212 | tspi->rx_bb_phys, tspi->dma_req_len, | ||
| 213 | DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT); | ||
| 214 | if (!tspi->rx_dma_desc) { | ||
| 215 | dev_err(&tspi->pdev->dev, "dmaengine slave prep failed\n"); | ||
| 216 | return; | ||
| 217 | } | ||
| 218 | tspi->rx_dma_desc->callback = tegra_spi_rx_dma_complete; | ||
| 219 | tspi->rx_dma_desc->callback_param = tspi; | ||
| 220 | tspi->rx_cookie = dmaengine_submit(tspi->rx_dma_desc); | ||
| 221 | dma_async_issue_pending(tspi->rx_dma); | ||
| 222 | #endif | ||
| 197 | 223 | ||
| 198 | val |= SLINK_DMA_EN; | 224 | val |= SLINK_DMA_EN; |
| 199 | spi_tegra_writel(tspi, val, SLINK_DMA_CTL); | 225 | spi_tegra_writel(tspi, val, SLINK_DMA_CTL); |
| @@ -221,7 +247,7 @@ static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi, | |||
| 221 | spi_tegra_writel(tspi, val, SLINK_TX_FIFO); | 247 | spi_tegra_writel(tspi, val, SLINK_TX_FIFO); |
| 222 | } | 248 | } |
| 223 | 249 | ||
| 224 | tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4; | 250 | tspi->dma_req_len = len / tspi->cur_bytes_per_word * 4; |
| 225 | 251 | ||
| 226 | return len; | 252 | return len; |
| 227 | } | 253 | } |
| @@ -318,9 +344,8 @@ static void spi_tegra_start_message(struct spi_device *spi, | |||
| 318 | spi_tegra_start_transfer(spi, t); | 344 | spi_tegra_start_transfer(spi, t); |
| 319 | } | 345 | } |
| 320 | 346 | ||
| 321 | static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) | 347 | static void handle_spi_rx_dma_complete(struct spi_tegra_data *tspi) |
| 322 | { | 348 | { |
| 323 | struct spi_tegra_data *tspi = req->dev; | ||
| 324 | unsigned long flags; | 349 | unsigned long flags; |
| 325 | struct spi_message *m; | 350 | struct spi_message *m; |
| 326 | struct spi_device *spi; | 351 | struct spi_device *spi; |
| @@ -380,6 +405,19 @@ static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) | |||
| 380 | 405 | ||
| 381 | spin_unlock_irqrestore(&tspi->lock, flags); | 406 | spin_unlock_irqrestore(&tspi->lock, flags); |
| 382 | } | 407 | } |
| 408 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 409 | static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req) | ||
| 410 | { | ||
| 411 | struct spi_tegra_data *tspi = req->dev; | ||
| 412 | handle_spi_rx_dma_complete(tspi); | ||
| 413 | } | ||
| 414 | #else | ||
| 415 | static void tegra_spi_rx_dma_complete(void *args) | ||
| 416 | { | ||
| 417 | struct spi_tegra_data *tspi = args; | ||
| 418 | handle_spi_rx_dma_complete(tspi); | ||
| 419 | } | ||
| 420 | #endif | ||
| 383 | 421 | ||
| 384 | static int spi_tegra_setup(struct spi_device *spi) | 422 | static int spi_tegra_setup(struct spi_device *spi) |
| 385 | { | 423 | { |
| @@ -471,6 +509,9 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) | |||
| 471 | struct spi_tegra_data *tspi; | 509 | struct spi_tegra_data *tspi; |
| 472 | struct resource *r; | 510 | struct resource *r; |
| 473 | int ret; | 511 | int ret; |
| 512 | #if !defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 513 | dma_cap_mask_t mask; | ||
| 514 | #endif | ||
| 474 | 515 | ||
| 475 | master = spi_alloc_master(&pdev->dev, sizeof *tspi); | 516 | master = spi_alloc_master(&pdev->dev, sizeof *tspi); |
| 476 | if (master == NULL) { | 517 | if (master == NULL) { |
| @@ -522,12 +563,24 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) | |||
| 522 | 563 | ||
| 523 | INIT_LIST_HEAD(&tspi->queue); | 564 | INIT_LIST_HEAD(&tspi->queue); |
| 524 | 565 | ||
| 566 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 525 | tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); | 567 | tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); |
| 526 | if (!tspi->rx_dma) { | 568 | if (!tspi->rx_dma) { |
| 527 | dev_err(&pdev->dev, "can not allocate rx dma channel\n"); | 569 | dev_err(&pdev->dev, "can not allocate rx dma channel\n"); |
| 528 | ret = -ENODEV; | 570 | ret = -ENODEV; |
| 529 | goto err3; | 571 | goto err3; |
| 530 | } | 572 | } |
| 573 | #else | ||
| 574 | dma_cap_zero(mask); | ||
| 575 | dma_cap_set(DMA_SLAVE, mask); | ||
| 576 | tspi->rx_dma = dma_request_channel(mask, NULL, NULL); | ||
| 577 | if (!tspi->rx_dma) { | ||
| 578 | dev_err(&pdev->dev, "can not allocate rx dma channel\n"); | ||
| 579 | ret = -ENODEV; | ||
| 580 | goto err3; | ||
| 581 | } | ||
| 582 | |||
| 583 | #endif | ||
| 531 | 584 | ||
| 532 | tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | 585 | tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN, |
| 533 | &tspi->rx_bb_phys, GFP_KERNEL); | 586 | &tspi->rx_bb_phys, GFP_KERNEL); |
| @@ -537,6 +590,7 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) | |||
| 537 | goto err4; | 590 | goto err4; |
| 538 | } | 591 | } |
| 539 | 592 | ||
| 593 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 540 | tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete; | 594 | tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete; |
| 541 | tspi->rx_dma_req.to_memory = 1; | 595 | tspi->rx_dma_req.to_memory = 1; |
| 542 | tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys; | 596 | tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys; |
| @@ -546,6 +600,23 @@ static int __devinit spi_tegra_probe(struct platform_device *pdev) | |||
| 546 | tspi->rx_dma_req.source_wrap = 4; | 600 | tspi->rx_dma_req.source_wrap = 4; |
| 547 | tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id]; | 601 | tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id]; |
| 548 | tspi->rx_dma_req.dev = tspi; | 602 | tspi->rx_dma_req.dev = tspi; |
| 603 | #else | ||
| 604 | /* Dmaengine Dma slave config */ | ||
| 605 | tspi->sconfig.src_addr = tspi->phys + SLINK_RX_FIFO; | ||
| 606 | tspi->sconfig.dst_addr = tspi->phys + SLINK_RX_FIFO; | ||
| 607 | tspi->sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
| 608 | tspi->sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
| 609 | tspi->sconfig.slave_id = spi_tegra_req_sels[pdev->id]; | ||
| 610 | tspi->sconfig.src_maxburst = 1; | ||
| 611 | tspi->sconfig.dst_maxburst = 1; | ||
| 612 | ret = dmaengine_device_control(tspi->rx_dma, | ||
| 613 | DMA_SLAVE_CONFIG, (unsigned long) &tspi->sconfig); | ||
| 614 | if (ret < 0) { | ||
| 615 | dev_err(&pdev->dev, "can not do slave configure for dma %d\n", | ||
| 616 | ret); | ||
| 617 | goto err4; | ||
| 618 | } | ||
| 619 | #endif | ||
| 549 | 620 | ||
| 550 | master->dev.of_node = pdev->dev.of_node; | 621 | master->dev.of_node = pdev->dev.of_node; |
| 551 | ret = spi_register_master(master); | 622 | ret = spi_register_master(master); |
| @@ -559,7 +630,11 @@ err5: | |||
| 559 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | 630 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, |
| 560 | tspi->rx_bb, tspi->rx_bb_phys); | 631 | tspi->rx_bb, tspi->rx_bb_phys); |
| 561 | err4: | 632 | err4: |
| 633 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 562 | tegra_dma_free_channel(tspi->rx_dma); | 634 | tegra_dma_free_channel(tspi->rx_dma); |
| 635 | #else | ||
| 636 | dma_release_channel(tspi->rx_dma); | ||
| 637 | #endif | ||
| 563 | err3: | 638 | err3: |
| 564 | clk_put(tspi->clk); | 639 | clk_put(tspi->clk); |
| 565 | err2: | 640 | err2: |
| @@ -581,7 +656,11 @@ static int __devexit spi_tegra_remove(struct platform_device *pdev) | |||
| 581 | tspi = spi_master_get_devdata(master); | 656 | tspi = spi_master_get_devdata(master); |
| 582 | 657 | ||
| 583 | spi_unregister_master(master); | 658 | spi_unregister_master(master); |
| 659 | #if defined(CONFIG_TEGRA_SYSTEM_DMA) | ||
| 584 | tegra_dma_free_channel(tspi->rx_dma); | 660 | tegra_dma_free_channel(tspi->rx_dma); |
| 661 | #else | ||
| 662 | dma_release_channel(tspi->rx_dma); | ||
| 663 | #endif | ||
| 585 | 664 | ||
| 586 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, | 665 | dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN, |
| 587 | tspi->rx_bb, tspi->rx_bb_phys); | 666 | tspi->rx_bb, tspi->rx_bb_phys); |
diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c new file mode 100644 index 000000000000..266a847e2992 --- /dev/null +++ b/drivers/spi/spi-xcomm.c | |||
| @@ -0,0 +1,276 @@ | |||
| 1 | /* | ||
| 2 | * Analog Devices AD-FMCOMMS1-EBZ board I2C-SPI bridge driver | ||
| 3 | * | ||
| 4 | * Copyright 2012 Analog Devices Inc. | ||
| 5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
| 6 | * | ||
| 7 | * Licensed under the GPL-2 or later. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/spi/spi.h> | ||
| 16 | #include <asm/unaligned.h> | ||
| 17 | |||
| 18 | #define SPI_XCOMM_SETTINGS_LEN_OFFSET 10 | ||
| 19 | #define SPI_XCOMM_SETTINGS_3WIRE BIT(6) | ||
| 20 | #define SPI_XCOMM_SETTINGS_CS_HIGH BIT(5) | ||
| 21 | #define SPI_XCOMM_SETTINGS_SAMPLE_END BIT(4) | ||
| 22 | #define SPI_XCOMM_SETTINGS_CPHA BIT(3) | ||
| 23 | #define SPI_XCOMM_SETTINGS_CPOL BIT(2) | ||
| 24 | #define SPI_XCOMM_SETTINGS_CLOCK_DIV_MASK 0x3 | ||
| 25 | #define SPI_XCOMM_SETTINGS_CLOCK_DIV_64 0x2 | ||
| 26 | #define SPI_XCOMM_SETTINGS_CLOCK_DIV_16 0x1 | ||
| 27 | #define SPI_XCOMM_SETTINGS_CLOCK_DIV_4 0x0 | ||
| 28 | |||
| 29 | #define SPI_XCOMM_CMD_UPDATE_CONFIG 0x03 | ||
| 30 | #define SPI_XCOMM_CMD_WRITE 0x04 | ||
| 31 | |||
| 32 | #define SPI_XCOMM_CLOCK 48000000 | ||
| 33 | |||
| 34 | struct spi_xcomm { | ||
| 35 | struct i2c_client *i2c; | ||
| 36 | |||
| 37 | uint16_t settings; | ||
| 38 | uint16_t chipselect; | ||
| 39 | |||
| 40 | unsigned int current_speed; | ||
| 41 | |||
| 42 | uint8_t buf[63]; | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int spi_xcomm_sync_config(struct spi_xcomm *spi_xcomm, unsigned int len) | ||
| 46 | { | ||
| 47 | uint16_t settings; | ||
| 48 | uint8_t *buf = spi_xcomm->buf; | ||
| 49 | |||
| 50 | settings = spi_xcomm->settings; | ||
| 51 | settings |= len << SPI_XCOMM_SETTINGS_LEN_OFFSET; | ||
| 52 | |||
| 53 | buf[0] = SPI_XCOMM_CMD_UPDATE_CONFIG; | ||
| 54 | put_unaligned_be16(settings, &buf[1]); | ||
| 55 | put_unaligned_be16(spi_xcomm->chipselect, &buf[3]); | ||
| 56 | |||
| 57 | return i2c_master_send(spi_xcomm->i2c, buf, 5); | ||
| 58 | } | ||
| 59 | |||
| 60 | static void spi_xcomm_chipselect(struct spi_xcomm *spi_xcomm, | ||
| 61 | struct spi_device *spi, int is_active) | ||
| 62 | { | ||
| 63 | unsigned long cs = spi->chip_select; | ||
| 64 | uint16_t chipselect = spi_xcomm->chipselect; | ||
| 65 | |||
| 66 | if (is_active) | ||
| 67 | chipselect |= BIT(cs); | ||
| 68 | else | ||
| 69 | chipselect &= ~BIT(cs); | ||
| 70 | |||
| 71 | spi_xcomm->chipselect = chipselect; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int spi_xcomm_setup_transfer(struct spi_xcomm *spi_xcomm, | ||
| 75 | struct spi_device *spi, struct spi_transfer *t, unsigned int *settings) | ||
| 76 | { | ||
| 77 | unsigned int speed; | ||
| 78 | |||
| 79 | if ((t->bits_per_word && t->bits_per_word != 8) || t->len > 62) | ||
| 80 | return -EINVAL; | ||
| 81 | |||
| 82 | speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz; | ||
| 83 | |||
| 84 | if (speed != spi_xcomm->current_speed) { | ||
| 85 | unsigned int divider = DIV_ROUND_UP(SPI_XCOMM_CLOCK, speed); | ||
| 86 | if (divider >= 64) | ||
| 87 | *settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_64; | ||
| 88 | else if (divider >= 16) | ||
| 89 | *settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_16; | ||
| 90 | else | ||
| 91 | *settings |= SPI_XCOMM_SETTINGS_CLOCK_DIV_4; | ||
| 92 | |||
| 93 | spi_xcomm->current_speed = speed; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (spi->mode & SPI_CPOL) | ||
| 97 | *settings |= SPI_XCOMM_SETTINGS_CPOL; | ||
| 98 | else | ||
| 99 | *settings &= ~SPI_XCOMM_SETTINGS_CPOL; | ||
| 100 | |||
| 101 | if (spi->mode & SPI_CPHA) | ||
| 102 | *settings &= ~SPI_XCOMM_SETTINGS_CPHA; | ||
| 103 | else | ||
| 104 | *settings |= SPI_XCOMM_SETTINGS_CPHA; | ||
| 105 | |||
| 106 | if (spi->mode & SPI_3WIRE) | ||
| 107 | *settings |= SPI_XCOMM_SETTINGS_3WIRE; | ||
| 108 | else | ||
| 109 | *settings &= ~SPI_XCOMM_SETTINGS_3WIRE; | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int spi_xcomm_txrx_bufs(struct spi_xcomm *spi_xcomm, | ||
| 115 | struct spi_device *spi, struct spi_transfer *t) | ||
| 116 | { | ||
| 117 | int ret; | ||
| 118 | |||
| 119 | if (t->tx_buf) { | ||
| 120 | spi_xcomm->buf[0] = SPI_XCOMM_CMD_WRITE; | ||
| 121 | memcpy(spi_xcomm->buf + 1, t->tx_buf, t->len); | ||
| 122 | |||
| 123 | ret = i2c_master_send(spi_xcomm->i2c, spi_xcomm->buf, t->len + 1); | ||
| 124 | if (ret < 0) | ||
| 125 | return ret; | ||
| 126 | else if (ret != t->len + 1) | ||
| 127 | return -EIO; | ||
| 128 | } else if (t->rx_buf) { | ||
| 129 | ret = i2c_master_recv(spi_xcomm->i2c, t->rx_buf, t->len); | ||
| 130 | if (ret < 0) | ||
| 131 | return ret; | ||
| 132 | else if (ret != t->len) | ||
| 133 | return -EIO; | ||
| 134 | } | ||
| 135 | |||
| 136 | return t->len; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int spi_xcomm_transfer_one(struct spi_master *master, | ||
| 140 | struct spi_message *msg) | ||
| 141 | { | ||
| 142 | struct spi_xcomm *spi_xcomm = spi_master_get_devdata(master); | ||
| 143 | unsigned int settings = spi_xcomm->settings; | ||
| 144 | struct spi_device *spi = msg->spi; | ||
| 145 | unsigned cs_change = 0; | ||
| 146 | struct spi_transfer *t; | ||
| 147 | bool is_first = true; | ||
| 148 | int status = 0; | ||
| 149 | bool is_last; | ||
| 150 | |||
| 151 | is_first = true; | ||
| 152 | |||
| 153 | spi_xcomm_chipselect(spi_xcomm, spi, true); | ||
| 154 | |||
| 155 | list_for_each_entry(t, &msg->transfers, transfer_list) { | ||
| 156 | |||
| 157 | if (!t->tx_buf && !t->rx_buf && t->len) { | ||
| 158 | status = -EINVAL; | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 162 | status = spi_xcomm_setup_transfer(spi_xcomm, spi, t, &settings); | ||
| 163 | if (status < 0) | ||
| 164 | break; | ||
| 165 | |||
| 166 | is_last = list_is_last(&t->transfer_list, &msg->transfers); | ||
| 167 | cs_change = t->cs_change; | ||
| 168 | |||
| 169 | if (cs_change ^ is_last) | ||
| 170 | settings |= BIT(5); | ||
| 171 | else | ||
| 172 | settings &= ~BIT(5); | ||
| 173 | |||
| 174 | if (t->rx_buf) { | ||
| 175 | spi_xcomm->settings = settings; | ||
| 176 | status = spi_xcomm_sync_config(spi_xcomm, t->len); | ||
| 177 | if (status < 0) | ||
| 178 | break; | ||
| 179 | } else if (settings != spi_xcomm->settings || is_first) { | ||
| 180 | spi_xcomm->settings = settings; | ||
| 181 | status = spi_xcomm_sync_config(spi_xcomm, 0); | ||
| 182 | if (status < 0) | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | if (t->len) { | ||
| 187 | status = spi_xcomm_txrx_bufs(spi_xcomm, spi, t); | ||
| 188 | |||
| 189 | if (status < 0) | ||
| 190 | break; | ||
| 191 | |||
| 192 | if (status > 0) | ||
| 193 | msg->actual_length += status; | ||
| 194 | } | ||
| 195 | status = 0; | ||
| 196 | |||
| 197 | if (t->delay_usecs) | ||
| 198 | udelay(t->delay_usecs); | ||
| 199 | |||
| 200 | is_first = false; | ||
| 201 | } | ||
| 202 | |||
| 203 | if (status != 0 || !cs_change) | ||
| 204 | spi_xcomm_chipselect(spi_xcomm, spi, false); | ||
| 205 | |||
| 206 | msg->status = status; | ||
| 207 | spi_finalize_current_message(master); | ||
| 208 | |||
| 209 | return status; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int spi_xcomm_setup(struct spi_device *spi) | ||
| 213 | { | ||
| 214 | if (spi->bits_per_word != 8) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int __devinit spi_xcomm_probe(struct i2c_client *i2c, | ||
| 221 | const struct i2c_device_id *id) | ||
| 222 | { | ||
| 223 | struct spi_xcomm *spi_xcomm; | ||
| 224 | struct spi_master *master; | ||
| 225 | int ret; | ||
| 226 | |||
| 227 | master = spi_alloc_master(&i2c->dev, sizeof(*spi_xcomm)); | ||
| 228 | if (!master) | ||
| 229 | return -ENOMEM; | ||
| 230 | |||
| 231 | spi_xcomm = spi_master_get_devdata(master); | ||
| 232 | spi_xcomm->i2c = i2c; | ||
| 233 | |||
| 234 | master->num_chipselect = 16; | ||
| 235 | master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_3WIRE; | ||
| 236 | master->flags = SPI_MASTER_HALF_DUPLEX; | ||
| 237 | master->setup = spi_xcomm_setup; | ||
| 238 | master->transfer_one_message = spi_xcomm_transfer_one; | ||
| 239 | master->dev.of_node = i2c->dev.of_node; | ||
| 240 | i2c_set_clientdata(i2c, master); | ||
| 241 | |||
| 242 | ret = spi_register_master(master); | ||
| 243 | if (ret < 0) | ||
| 244 | spi_master_put(master); | ||
| 245 | |||
| 246 | return ret; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int __devexit spi_xcomm_remove(struct i2c_client *i2c) | ||
| 250 | { | ||
| 251 | struct spi_master *master = i2c_get_clientdata(i2c); | ||
| 252 | |||
| 253 | spi_unregister_master(master); | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static const struct i2c_device_id spi_xcomm_ids[] = { | ||
| 259 | { "spi-xcomm" }, | ||
| 260 | { }, | ||
| 261 | }; | ||
| 262 | |||
| 263 | static struct i2c_driver spi_xcomm_driver = { | ||
| 264 | .driver = { | ||
| 265 | .name = "spi-xcomm", | ||
| 266 | .owner = THIS_MODULE, | ||
| 267 | }, | ||
| 268 | .id_table = spi_xcomm_ids, | ||
| 269 | .probe = spi_xcomm_probe, | ||
| 270 | .remove = __devexit_p(spi_xcomm_remove), | ||
| 271 | }; | ||
| 272 | module_i2c_driver(spi_xcomm_driver); | ||
| 273 | |||
| 274 | MODULE_LICENSE("GPL"); | ||
| 275 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
| 276 | MODULE_DESCRIPTION("Analog Devices AD-FMCOMMS1-EBZ board I2C-SPI bridge driver"); | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1041cb83d67a..84c2861d6f4d 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -53,7 +53,7 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) | |||
| 53 | { | 53 | { |
| 54 | const struct spi_device *spi = to_spi_device(dev); | 54 | const struct spi_device *spi = to_spi_device(dev); |
| 55 | 55 | ||
| 56 | return sprintf(buf, "%s\n", spi->modalias); | 56 | return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static struct device_attribute spi_dev_attrs[] = { | 59 | static struct device_attribute spi_dev_attrs[] = { |
diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h index 76dd1b199a1b..fe1d7b283cb6 100644 --- a/include/linux/amba/pl022.h +++ b/include/linux/amba/pl022.h | |||
| @@ -231,6 +231,7 @@ enum ssp_chip_select { | |||
| 231 | struct dma_chan; | 231 | struct dma_chan; |
| 232 | /** | 232 | /** |
| 233 | * struct pl022_ssp_master - device.platform_data for SPI controller devices. | 233 | * struct pl022_ssp_master - device.platform_data for SPI controller devices. |
| 234 | * @bus_id: identifier for this bus | ||
| 234 | * @num_chipselect: chipselects are used to distinguish individual | 235 | * @num_chipselect: chipselects are used to distinguish individual |
| 235 | * SPI slaves, and are numbered from zero to num_chipselects - 1. | 236 | * SPI slaves, and are numbered from zero to num_chipselects - 1. |
| 236 | * each slave has a chipselect signal, but it's common that not | 237 | * each slave has a chipselect signal, but it's common that not |
| @@ -259,19 +260,13 @@ struct pl022_ssp_controller { | |||
| 259 | * struct ssp_config_chip - spi_board_info.controller_data for SPI | 260 | * struct ssp_config_chip - spi_board_info.controller_data for SPI |
| 260 | * slave devices, copied to spi_device.controller_data. | 261 | * slave devices, copied to spi_device.controller_data. |
| 261 | * | 262 | * |
| 262 | * @lbm: used for test purpose to internally connect RX and TX | ||
| 263 | * @iface: Interface type(Motorola, TI, Microwire, Universal) | 263 | * @iface: Interface type(Motorola, TI, Microwire, Universal) |
| 264 | * @hierarchy: sets whether interface is master or slave | 264 | * @hierarchy: sets whether interface is master or slave |
| 265 | * @slave_tx_disable: SSPTXD is disconnected (in slave mode only) | 265 | * @slave_tx_disable: SSPTXD is disconnected (in slave mode only) |
| 266 | * @clk_freq: Tune freq parameters of SSP(when in master mode) | 266 | * @clk_freq: Tune freq parameters of SSP(when in master mode) |
| 267 | * @endian_rx: Endianess of Data in Rx FIFO | ||
| 268 | * @endian_tx: Endianess of Data in Tx FIFO | ||
| 269 | * @data_size: Width of data element(4 to 32 bits) | ||
| 270 | * @com_mode: communication mode: polling, Interrupt or DMA | 267 | * @com_mode: communication mode: polling, Interrupt or DMA |
| 271 | * @rx_lev_trig: Rx FIFO watermark level (for IT & DMA mode) | 268 | * @rx_lev_trig: Rx FIFO watermark level (for IT & DMA mode) |
| 272 | * @tx_lev_trig: Tx FIFO watermark level (for IT & DMA mode) | 269 | * @tx_lev_trig: Tx FIFO watermark level (for IT & DMA mode) |
| 273 | * @clk_phase: Motorola SPI interface Clock phase | ||
| 274 | * @clk_pol: Motorola SPI interface Clock polarity | ||
| 275 | * @ctrl_len: Microwire interface: Control length | 270 | * @ctrl_len: Microwire interface: Control length |
| 276 | * @wait_state: Microwire interface: Wait state | 271 | * @wait_state: Microwire interface: Wait state |
| 277 | * @duplex: Microwire interface: Full/Half duplex | 272 | * @duplex: Microwire interface: Full/Half duplex |
| @@ -279,8 +274,6 @@ struct pl022_ssp_controller { | |||
| 279 | * before sampling the incoming line | 274 | * before sampling the incoming line |
| 280 | * @cs_control: function pointer to board-specific function to | 275 | * @cs_control: function pointer to board-specific function to |
| 281 | * assert/deassert I/O port to control HW generation of devices chip-select. | 276 | * assert/deassert I/O port to control HW generation of devices chip-select. |
| 282 | * @dma_xfer_type: Type of DMA xfer (Mem-to-periph or Periph-to-Periph) | ||
| 283 | * @dma_config: DMA configuration for SSP controller and peripheral | ||
| 284 | */ | 277 | */ |
| 285 | struct pl022_config_chip { | 278 | struct pl022_config_chip { |
| 286 | enum ssp_interface iface; | 279 | enum ssp_interface iface; |
