diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-28 14:32:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-28 14:32:32 -0400 |
commit | 24b414d5a7d3e6a716350464dfdb44da610ed142 (patch) | |
tree | cb2b2ffa7f7feb09fbbab66a4e760a44ebc39f3a | |
parent | 4194976b0900efcabbc93cc313ab12abad27d8a8 (diff) | |
parent | 7216a4183947853f359b41ba1edb5db9b3091acc (diff) |
Merge tag 'spi-v3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi fixes from Mark Brown:
"A few driver specific fixes, the biggest one being a fix for the newly
added Qualcomm SPI controller driver to make it not use its internal
chip select due to hardware bugs, replacing it with GPIOs"
* tag 'spi-v3.16-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi:
spi: qup: Remove chip select function
spi: qup: Fix order of spi_register_master
spi: sh-sci: fix use-after-free in sh_sci_spi_remove()
spi/pxa2xx: fix incorrect SW mode chipselect setting for BayTrail LPSS SPI
-rw-r--r-- | Documentation/devicetree/bindings/spi/qcom,spi-qup.txt | 6 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 8 | ||||
-rw-r--r-- | drivers/spi/spi-qup.c | 44 | ||||
-rw-r--r-- | drivers/spi/spi-sh-sci.c | 4 |
4 files changed, 27 insertions, 35 deletions
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt index b82a268f1bd4..bee6ff204baf 100644 --- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt +++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt | |||
@@ -23,6 +23,12 @@ Optional properties: | |||
23 | - spi-max-frequency: Specifies maximum SPI clock frequency, | 23 | - spi-max-frequency: Specifies maximum SPI clock frequency, |
24 | Units - Hz. Definition as per | 24 | Units - Hz. Definition as per |
25 | Documentation/devicetree/bindings/spi/spi-bus.txt | 25 | Documentation/devicetree/bindings/spi/spi-bus.txt |
26 | - num-cs: total number of chipselects | ||
27 | - cs-gpios: should specify GPIOs used for chipselects. | ||
28 | The gpios will be referred to as reg = <index> in the SPI child | ||
29 | nodes. If unspecified, a single SPI device without a chip | ||
30 | select can be used. | ||
31 | |||
26 | 32 | ||
27 | SPI slave nodes must be children of the SPI master node and can contain | 33 | SPI slave nodes must be children of the SPI master node and can contain |
28 | properties described in Documentation/devicetree/bindings/spi/spi-bus.txt | 34 | properties described in Documentation/devicetree/bindings/spi/spi-bus.txt |
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index a98df7eeb42d..fe792106bdc5 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c | |||
@@ -118,6 +118,7 @@ static void lpss_ssp_setup(struct driver_data *drv_data) | |||
118 | */ | 118 | */ |
119 | orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); | 119 | orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); |
120 | 120 | ||
121 | /* Test SPI_CS_CONTROL_SW_MODE bit enabling */ | ||
121 | value = orig | SPI_CS_CONTROL_SW_MODE; | 122 | value = orig | SPI_CS_CONTROL_SW_MODE; |
122 | writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); | 123 | writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); |
123 | value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); | 124 | value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); |
@@ -126,10 +127,13 @@ static void lpss_ssp_setup(struct driver_data *drv_data) | |||
126 | goto detection_done; | 127 | goto detection_done; |
127 | } | 128 | } |
128 | 129 | ||
129 | value &= ~SPI_CS_CONTROL_SW_MODE; | 130 | orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); |
131 | |||
132 | /* Test SPI_CS_CONTROL_SW_MODE bit disabling */ | ||
133 | value = orig & ~SPI_CS_CONTROL_SW_MODE; | ||
130 | writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); | 134 | writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); |
131 | value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); | 135 | value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); |
132 | if (value != orig) { | 136 | if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) { |
133 | offset = 0x800; | 137 | offset = 0x800; |
134 | goto detection_done; | 138 | goto detection_done; |
135 | } | 139 | } |
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index fc1de86d3c8a..c08da380cb23 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c | |||
@@ -424,31 +424,6 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) | |||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | static void spi_qup_set_cs(struct spi_device *spi, bool enable) | ||
428 | { | ||
429 | struct spi_qup *controller = spi_master_get_devdata(spi->master); | ||
430 | |||
431 | u32 iocontol, mask; | ||
432 | |||
433 | iocontol = readl_relaxed(controller->base + SPI_IO_CONTROL); | ||
434 | |||
435 | /* Disable auto CS toggle and use manual */ | ||
436 | iocontol &= ~SPI_IO_C_MX_CS_MODE; | ||
437 | iocontol |= SPI_IO_C_FORCE_CS; | ||
438 | |||
439 | iocontol &= ~SPI_IO_C_CS_SELECT_MASK; | ||
440 | iocontol |= SPI_IO_C_CS_SELECT(spi->chip_select); | ||
441 | |||
442 | mask = SPI_IO_C_CS_N_POLARITY_0 << spi->chip_select; | ||
443 | |||
444 | if (enable) | ||
445 | iocontol |= mask; | ||
446 | else | ||
447 | iocontol &= ~mask; | ||
448 | |||
449 | writel_relaxed(iocontol, controller->base + SPI_IO_CONTROL); | ||
450 | } | ||
451 | |||
452 | static int spi_qup_transfer_one(struct spi_master *master, | 427 | static int spi_qup_transfer_one(struct spi_master *master, |
453 | struct spi_device *spi, | 428 | struct spi_device *spi, |
454 | struct spi_transfer *xfer) | 429 | struct spi_transfer *xfer) |
@@ -571,12 +546,16 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
571 | return -ENOMEM; | 546 | return -ENOMEM; |
572 | } | 547 | } |
573 | 548 | ||
549 | /* use num-cs unless not present or out of range */ | ||
550 | if (of_property_read_u16(dev->of_node, "num-cs", | ||
551 | &master->num_chipselect) || | ||
552 | (master->num_chipselect > SPI_NUM_CHIPSELECTS)) | ||
553 | master->num_chipselect = SPI_NUM_CHIPSELECTS; | ||
554 | |||
574 | master->bus_num = pdev->id; | 555 | master->bus_num = pdev->id; |
575 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; | 556 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; |
576 | master->num_chipselect = SPI_NUM_CHIPSELECTS; | ||
577 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); | 557 | master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); |
578 | master->max_speed_hz = max_freq; | 558 | master->max_speed_hz = max_freq; |
579 | master->set_cs = spi_qup_set_cs; | ||
580 | master->transfer_one = spi_qup_transfer_one; | 559 | master->transfer_one = spi_qup_transfer_one; |
581 | master->dev.of_node = pdev->dev.of_node; | 560 | master->dev.of_node = pdev->dev.of_node; |
582 | master->auto_runtime_pm = true; | 561 | master->auto_runtime_pm = true; |
@@ -640,16 +619,19 @@ static int spi_qup_probe(struct platform_device *pdev) | |||
640 | if (ret) | 619 | if (ret) |
641 | goto error; | 620 | goto error; |
642 | 621 | ||
643 | ret = devm_spi_register_master(dev, master); | ||
644 | if (ret) | ||
645 | goto error; | ||
646 | |||
647 | pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); | 622 | pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); |
648 | pm_runtime_use_autosuspend(dev); | 623 | pm_runtime_use_autosuspend(dev); |
649 | pm_runtime_set_active(dev); | 624 | pm_runtime_set_active(dev); |
650 | pm_runtime_enable(dev); | 625 | pm_runtime_enable(dev); |
626 | |||
627 | ret = devm_spi_register_master(dev, master); | ||
628 | if (ret) | ||
629 | goto disable_pm; | ||
630 | |||
651 | return 0; | 631 | return 0; |
652 | 632 | ||
633 | disable_pm: | ||
634 | pm_runtime_disable(&pdev->dev); | ||
653 | error: | 635 | error: |
654 | clk_disable_unprepare(cclk); | 636 | clk_disable_unprepare(cclk); |
655 | clk_disable_unprepare(iclk); | 637 | clk_disable_unprepare(iclk); |
diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 1f56ef651d1a..b83dd733684c 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c | |||
@@ -175,9 +175,9 @@ static int sh_sci_spi_remove(struct platform_device *dev) | |||
175 | { | 175 | { |
176 | struct sh_sci_spi *sp = platform_get_drvdata(dev); | 176 | struct sh_sci_spi *sp = platform_get_drvdata(dev); |
177 | 177 | ||
178 | iounmap(sp->membase); | ||
179 | setbits(sp, PIN_INIT, 0); | ||
180 | spi_bitbang_stop(&sp->bitbang); | 178 | spi_bitbang_stop(&sp->bitbang); |
179 | setbits(sp, PIN_INIT, 0); | ||
180 | iounmap(sp->membase); | ||
181 | spi_master_put(sp->bitbang.master); | 181 | spi_master_put(sp->bitbang.master); |
182 | return 0; | 182 | return 0; |
183 | } | 183 | } |