diff options
| -rw-r--r-- | drivers/spi/spi-dw-mmio.c | 22 | ||||
| -rw-r--r-- | drivers/spi/spi-dw.c | 18 | ||||
| -rw-r--r-- | drivers/spi/spi-dw.h | 16 |
3 files changed, 45 insertions, 11 deletions
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 1492f5ee9aaa..a5cba14ac3d2 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
| 17 | #include <linux/scatterlist.h> | 17 | #include <linux/scatterlist.h> |
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/of_gpio.h> | ||
| 19 | 20 | ||
| 20 | #include "spi-dw.h" | 21 | #include "spi-dw.h" |
| 21 | 22 | ||
| @@ -70,6 +71,27 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) | |||
| 70 | dws->num_cs = 4; | 71 | dws->num_cs = 4; |
| 71 | dws->max_freq = clk_get_rate(dwsmmio->clk); | 72 | dws->max_freq = clk_get_rate(dwsmmio->clk); |
| 72 | 73 | ||
| 74 | if (pdev->dev.of_node) { | ||
| 75 | int i; | ||
| 76 | |||
| 77 | for (i = 0; i < dws->num_cs; i++) { | ||
| 78 | int cs_gpio = of_get_named_gpio(pdev->dev.of_node, | ||
| 79 | "cs-gpios", i); | ||
| 80 | |||
| 81 | if (cs_gpio == -EPROBE_DEFER) { | ||
| 82 | ret = cs_gpio; | ||
| 83 | goto out; | ||
| 84 | } | ||
| 85 | |||
| 86 | if (gpio_is_valid(cs_gpio)) { | ||
| 87 | ret = devm_gpio_request(&pdev->dev, cs_gpio, | ||
| 88 | dev_name(&pdev->dev)); | ||
| 89 | if (ret) | ||
| 90 | goto out; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 73 | ret = dw_spi_add_host(&pdev->dev, dws); | 95 | ret = dw_spi_add_host(&pdev->dev, dws); |
| 74 | if (ret) | 96 | if (ret) |
| 75 | goto out; | 97 | goto out; |
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c index 357869a704d6..9965e1b84832 100644 --- a/drivers/spi/spi-dw.c +++ b/drivers/spi/spi-dw.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/spi/spi.h> | 26 | #include <linux/spi/spi.h> |
| 27 | #include <linux/gpio.h> | ||
| 27 | 28 | ||
| 28 | #include "spi-dw.h" | 29 | #include "spi-dw.h" |
| 29 | 30 | ||
| @@ -36,9 +37,6 @@ | |||
| 36 | #define DONE_STATE ((void *)2) | 37 | #define DONE_STATE ((void *)2) |
| 37 | #define ERROR_STATE ((void *)-1) | 38 | #define ERROR_STATE ((void *)-1) |
| 38 | 39 | ||
| 39 | #define MRST_SPI_DEASSERT 0 | ||
| 40 | #define MRST_SPI_ASSERT 1 | ||
| 41 | |||
| 42 | /* Slave spi_dev related */ | 40 | /* Slave spi_dev related */ |
| 43 | struct chip_data { | 41 | struct chip_data { |
| 44 | u16 cr0; | 42 | u16 cr0; |
| @@ -272,8 +270,8 @@ static void giveback(struct dw_spi *dws) | |||
| 272 | last_transfer = list_last_entry(&msg->transfers, struct spi_transfer, | 270 | last_transfer = list_last_entry(&msg->transfers, struct spi_transfer, |
| 273 | transfer_list); | 271 | transfer_list); |
| 274 | 272 | ||
| 275 | if (!last_transfer->cs_change && dws->cs_control) | 273 | if (!last_transfer->cs_change) |
| 276 | dws->cs_control(MRST_SPI_DEASSERT); | 274 | spi_chip_sel(dws, dws->cur_msg->spi, 0); |
| 277 | 275 | ||
| 278 | spi_finalize_current_message(dws->master); | 276 | spi_finalize_current_message(dws->master); |
| 279 | } | 277 | } |
| @@ -493,7 +491,7 @@ static void pump_transfers(unsigned long data) | |||
| 493 | dw_writew(dws, DW_SPI_CTRL0, cr0); | 491 | dw_writew(dws, DW_SPI_CTRL0, cr0); |
| 494 | 492 | ||
| 495 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); | 493 | spi_set_clk(dws, clk_div ? clk_div : chip->clk_div); |
| 496 | spi_chip_sel(dws, spi->chip_select); | 494 | spi_chip_sel(dws, spi, 1); |
| 497 | 495 | ||
| 498 | /* Set the interrupt mask, for poll mode just disable all int */ | 496 | /* Set the interrupt mask, for poll mode just disable all int */ |
| 499 | spi_mask_intr(dws, 0xff); | 497 | spi_mask_intr(dws, 0xff); |
| @@ -544,6 +542,7 @@ static int dw_spi_setup(struct spi_device *spi) | |||
| 544 | { | 542 | { |
| 545 | struct dw_spi_chip *chip_info = NULL; | 543 | struct dw_spi_chip *chip_info = NULL; |
| 546 | struct chip_data *chip; | 544 | struct chip_data *chip; |
| 545 | int ret; | ||
| 547 | 546 | ||
| 548 | /* Only alloc on first setup */ | 547 | /* Only alloc on first setup */ |
| 549 | chip = spi_get_ctldata(spi); | 548 | chip = spi_get_ctldata(spi); |
| @@ -597,6 +596,13 @@ static int dw_spi_setup(struct spi_device *spi) | |||
| 597 | | (spi->mode << SPI_MODE_OFFSET) | 596 | | (spi->mode << SPI_MODE_OFFSET) |
| 598 | | (chip->tmode << SPI_TMOD_OFFSET); | 597 | | (chip->tmode << SPI_TMOD_OFFSET); |
| 599 | 598 | ||
| 599 | if (gpio_is_valid(spi->cs_gpio)) { | ||
| 600 | ret = gpio_direction_output(spi->cs_gpio, | ||
| 601 | !(spi->mode & SPI_CS_HIGH)); | ||
| 602 | if (ret) | ||
| 603 | return ret; | ||
| 604 | } | ||
| 605 | |||
| 600 | return 0; | 606 | return 0; |
| 601 | } | 607 | } |
| 602 | 608 | ||
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 3fd7ab599ab4..6d2acad34f64 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
| 5 | #include <linux/scatterlist.h> | 5 | #include <linux/scatterlist.h> |
| 6 | #include <linux/gpio.h> | ||
| 6 | 7 | ||
| 7 | /* Register offsets */ | 8 | /* Register offsets */ |
| 8 | #define DW_SPI_CTRL0 0x00 | 9 | #define DW_SPI_CTRL0 0x00 |
| @@ -178,15 +179,20 @@ static inline void spi_set_clk(struct dw_spi *dws, u16 div) | |||
| 178 | dw_writel(dws, DW_SPI_BAUDR, div); | 179 | dw_writel(dws, DW_SPI_BAUDR, div); |
| 179 | } | 180 | } |
| 180 | 181 | ||
| 181 | static inline void spi_chip_sel(struct dw_spi *dws, u16 cs) | 182 | static inline void spi_chip_sel(struct dw_spi *dws, struct spi_device *spi, |
| 183 | int active) | ||
| 182 | { | 184 | { |
| 183 | if (cs > dws->num_cs) | 185 | u16 cs = spi->chip_select; |
| 184 | return; | 186 | int gpio_val = active ? (spi->mode & SPI_CS_HIGH) : |
| 187 | !(spi->mode & SPI_CS_HIGH); | ||
| 185 | 188 | ||
| 186 | if (dws->cs_control) | 189 | if (dws->cs_control) |
| 187 | dws->cs_control(1); | 190 | dws->cs_control(active); |
| 191 | if (gpio_is_valid(spi->cs_gpio)) | ||
| 192 | gpio_set_value(spi->cs_gpio, gpio_val); | ||
| 188 | 193 | ||
| 189 | dw_writel(dws, DW_SPI_SER, 1 << cs); | 194 | if (active) |
| 195 | dw_writel(dws, DW_SPI_SER, 1 << cs); | ||
| 190 | } | 196 | } |
| 191 | 197 | ||
| 192 | /* Disable IRQ bits */ | 198 | /* Disable IRQ bits */ |
