diff options
-rw-r--r-- | Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | 2 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 80 |
3 files changed, 56 insertions, 27 deletions
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt index a1fb3035a42b..5376de40f10b 100644 --- a/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt +++ b/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt | |||
@@ -10,6 +10,7 @@ Required properties: | |||
10 | - pinctrl-names: must contain a "default" entry. | 10 | - pinctrl-names: must contain a "default" entry. |
11 | - spi-num-chipselects : the number of the chipselect signals. | 11 | - spi-num-chipselects : the number of the chipselect signals. |
12 | - bus-num : the slave chip chipselect signal number. | 12 | - bus-num : the slave chip chipselect signal number. |
13 | - big-endian : if DSPI modudle is big endian, the bool will be set in node. | ||
13 | Example: | 14 | Example: |
14 | 15 | ||
15 | dspi0@4002c000 { | 16 | dspi0@4002c000 { |
@@ -24,6 +25,7 @@ dspi0@4002c000 { | |||
24 | bus-num = <0>; | 25 | bus-num = <0>; |
25 | pinctrl-names = "default"; | 26 | pinctrl-names = "default"; |
26 | pinctrl-0 = <&pinctrl_dspi0_1>; | 27 | pinctrl-0 = <&pinctrl_dspi0_1>; |
28 | big-endian; | ||
27 | status = "okay"; | 29 | status = "okay"; |
28 | 30 | ||
29 | sflash: at26df081a@0 { | 31 | sflash: at26df081a@0 { |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ba9310bc9acb..00e951045aac 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -270,6 +270,7 @@ config SPI_FSL_SPI | |||
270 | config SPI_FSL_DSPI | 270 | config SPI_FSL_DSPI |
271 | tristate "Freescale DSPI controller" | 271 | tristate "Freescale DSPI controller" |
272 | select SPI_BITBANG | 272 | select SPI_BITBANG |
273 | select REGMAP_MMIO | ||
273 | depends on SOC_VF610 || COMPILE_TEST | 274 | depends on SOC_VF610 || COMPILE_TEST |
274 | help | 275 | help |
275 | This enables support for the Freescale DSPI controller in master | 276 | This enables support for the Freescale DSPI controller in master |
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index ec79f726672a..fb16575d233f 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/regmap.h> | ||
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
22 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
@@ -108,7 +109,7 @@ struct fsl_dspi { | |||
108 | struct spi_bitbang bitbang; | 109 | struct spi_bitbang bitbang; |
109 | struct platform_device *pdev; | 110 | struct platform_device *pdev; |
110 | 111 | ||
111 | void __iomem *base; | 112 | struct regmap *regmap; |
112 | int irq; | 113 | int irq; |
113 | struct clk *clk; | 114 | struct clk *clk; |
114 | 115 | ||
@@ -129,18 +130,11 @@ struct fsl_dspi { | |||
129 | 130 | ||
130 | static inline int is_double_byte_mode(struct fsl_dspi *dspi) | 131 | static inline int is_double_byte_mode(struct fsl_dspi *dspi) |
131 | { | 132 | { |
132 | return ((readl(dspi->base + SPI_CTAR(dspi->cs)) & SPI_FRAME_BITS_MASK) | 133 | unsigned int val; |
133 | == SPI_FRAME_BITS(8)) ? 0 : 1; | ||
134 | } | ||
135 | 134 | ||
136 | static void set_bit_mode(struct fsl_dspi *dspi, unsigned char bits) | 135 | regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val); |
137 | { | ||
138 | u32 temp; | ||
139 | 136 | ||
140 | temp = readl(dspi->base + SPI_CTAR(dspi->cs)); | 137 | return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1; |
141 | temp &= ~SPI_FRAME_BITS_MASK; | ||
142 | temp |= SPI_FRAME_BITS(bits); | ||
143 | writel(temp, dspi->base + SPI_CTAR(dspi->cs)); | ||
144 | } | 138 | } |
145 | 139 | ||
146 | static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, | 140 | static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, |
@@ -188,7 +182,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) | |||
188 | */ | 182 | */ |
189 | if (tx_word && (dspi->len == 1)) { | 183 | if (tx_word && (dspi->len == 1)) { |
190 | dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; | 184 | dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM; |
191 | set_bit_mode(dspi, 8); | 185 | regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), |
186 | SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8)); | ||
192 | tx_word = 0; | 187 | tx_word = 0; |
193 | } | 188 | } |
194 | 189 | ||
@@ -238,7 +233,8 @@ static int dspi_transfer_write(struct fsl_dspi *dspi) | |||
238 | dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ | 233 | dspi_pushr |= SPI_PUSHR_CTCNT; /* clear counter */ |
239 | } | 234 | } |
240 | 235 | ||
241 | writel(dspi_pushr, dspi->base + SPI_PUSHR); | 236 | regmap_write(dspi->regmap, SPI_PUSHR, dspi_pushr); |
237 | |||
242 | tx_count++; | 238 | tx_count++; |
243 | } | 239 | } |
244 | 240 | ||
@@ -253,17 +249,23 @@ static int dspi_transfer_read(struct fsl_dspi *dspi) | |||
253 | while ((dspi->rx < dspi->rx_end) | 249 | while ((dspi->rx < dspi->rx_end) |
254 | && (rx_count < DSPI_FIFO_SIZE)) { | 250 | && (rx_count < DSPI_FIFO_SIZE)) { |
255 | if (rx_word) { | 251 | if (rx_word) { |
252 | unsigned int val; | ||
253 | |||
256 | if ((dspi->rx_end - dspi->rx) == 1) | 254 | if ((dspi->rx_end - dspi->rx) == 1) |
257 | break; | 255 | break; |
258 | 256 | ||
259 | d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); | 257 | regmap_read(dspi->regmap, SPI_POPR, &val); |
258 | d = SPI_POPR_RXDATA(val); | ||
260 | 259 | ||
261 | if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) | 260 | if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) |
262 | *(u16 *)dspi->rx = d; | 261 | *(u16 *)dspi->rx = d; |
263 | dspi->rx += 2; | 262 | dspi->rx += 2; |
264 | 263 | ||
265 | } else { | 264 | } else { |
266 | d = SPI_POPR_RXDATA(readl(dspi->base + SPI_POPR)); | 265 | unsigned int val; |
266 | |||
267 | regmap_read(dspi->regmap, SPI_POPR, &val); | ||
268 | d = SPI_POPR_RXDATA(val); | ||
267 | if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) | 269 | if (!(dspi->dataflags & TRAN_STATE_RX_VOID)) |
268 | *(u8 *)dspi->rx = d; | 270 | *(u8 *)dspi->rx = d; |
269 | dspi->rx++; | 271 | dspi->rx++; |
@@ -295,13 +297,13 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
295 | if (!dspi->tx) | 297 | if (!dspi->tx) |
296 | dspi->dataflags |= TRAN_STATE_TX_VOID; | 298 | dspi->dataflags |= TRAN_STATE_TX_VOID; |
297 | 299 | ||
298 | writel(dspi->cur_chip->mcr_val, dspi->base + SPI_MCR); | 300 | regmap_write(dspi->regmap, SPI_MCR, dspi->cur_chip->mcr_val); |
299 | writel(dspi->cur_chip->ctar_val, dspi->base + SPI_CTAR(dspi->cs)); | 301 | regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), dspi->cur_chip->ctar_val); |
300 | writel(SPI_RSER_EOQFE, dspi->base + SPI_RSER); | 302 | regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_EOQFE); |
301 | 303 | ||
302 | if (t->speed_hz) | 304 | if (t->speed_hz) |
303 | writel(dspi->cur_chip->ctar_val, | 305 | regmap_write(dspi->regmap, SPI_CTAR(dspi->cs), |
304 | dspi->base + SPI_CTAR(dspi->cs)); | 306 | dspi->cur_chip->ctar_val); |
305 | 307 | ||
306 | dspi_transfer_write(dspi); | 308 | dspi_transfer_write(dspi); |
307 | 309 | ||
@@ -315,7 +317,9 @@ static int dspi_txrx_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
315 | static void dspi_chipselect(struct spi_device *spi, int value) | 317 | static void dspi_chipselect(struct spi_device *spi, int value) |
316 | { | 318 | { |
317 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); | 319 | struct fsl_dspi *dspi = spi_master_get_devdata(spi->master); |
318 | u32 pushr = readl(dspi->base + SPI_PUSHR); | 320 | unsigned int pushr; |
321 | |||
322 | regmap_read(dspi->regmap, SPI_PUSHR, &pushr); | ||
319 | 323 | ||
320 | switch (value) { | 324 | switch (value) { |
321 | case BITBANG_CS_ACTIVE: | 325 | case BITBANG_CS_ACTIVE: |
@@ -326,7 +330,7 @@ static void dspi_chipselect(struct spi_device *spi, int value) | |||
326 | break; | 330 | break; |
327 | } | 331 | } |
328 | 332 | ||
329 | writel(pushr, dspi->base + SPI_PUSHR); | 333 | regmap_write(dspi->regmap, SPI_PUSHR, pushr); |
330 | } | 334 | } |
331 | 335 | ||
332 | static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | 336 | static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) |
@@ -382,13 +386,15 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id) | |||
382 | { | 386 | { |
383 | struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; | 387 | struct fsl_dspi *dspi = (struct fsl_dspi *)dev_id; |
384 | 388 | ||
385 | writel(SPI_SR_EOQF, dspi->base + SPI_SR); | 389 | regmap_write(dspi->regmap, SPI_SR, SPI_SR_EOQF); |
386 | 390 | ||
387 | dspi_transfer_read(dspi); | 391 | dspi_transfer_read(dspi); |
388 | 392 | ||
389 | if (!dspi->len) { | 393 | if (!dspi->len) { |
390 | if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) | 394 | if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) |
391 | set_bit_mode(dspi, 16); | 395 | regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs), |
396 | SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(16)); | ||
397 | |||
392 | dspi->waitflags = 1; | 398 | dspi->waitflags = 1; |
393 | wake_up_interruptible(&dspi->waitq); | 399 | wake_up_interruptible(&dspi->waitq); |
394 | } else { | 400 | } else { |
@@ -435,12 +441,20 @@ static const struct dev_pm_ops dspi_pm = { | |||
435 | SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) | 441 | SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) |
436 | }; | 442 | }; |
437 | 443 | ||
444 | static struct regmap_config dspi_regmap_config = { | ||
445 | .reg_bits = 32, | ||
446 | .val_bits = 32, | ||
447 | .reg_stride = 4, | ||
448 | .max_register = 0x88, | ||
449 | }; | ||
450 | |||
438 | static int dspi_probe(struct platform_device *pdev) | 451 | static int dspi_probe(struct platform_device *pdev) |
439 | { | 452 | { |
440 | struct device_node *np = pdev->dev.of_node; | 453 | struct device_node *np = pdev->dev.of_node; |
441 | struct spi_master *master; | 454 | struct spi_master *master; |
442 | struct fsl_dspi *dspi; | 455 | struct fsl_dspi *dspi; |
443 | struct resource *res; | 456 | struct resource *res; |
457 | void __iomem *base; | ||
444 | int ret = 0, cs_num, bus_num; | 458 | int ret = 0, cs_num, bus_num; |
445 | 459 | ||
446 | master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); | 460 | master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); |
@@ -475,12 +489,24 @@ static int dspi_probe(struct platform_device *pdev) | |||
475 | master->bus_num = bus_num; | 489 | master->bus_num = bus_num; |
476 | 490 | ||
477 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 491 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
478 | dspi->base = devm_ioremap_resource(&pdev->dev, res); | 492 | base = devm_ioremap_resource(&pdev->dev, res); |
479 | if (IS_ERR(dspi->base)) { | 493 | if (IS_ERR(base)) { |
480 | ret = PTR_ERR(dspi->base); | 494 | ret = PTR_ERR(base); |
481 | goto out_master_put; | 495 | goto out_master_put; |
482 | } | 496 | } |
483 | 497 | ||
498 | dspi_regmap_config.lock_arg = dspi; | ||
499 | dspi_regmap_config.val_format_endian = | ||
500 | of_property_read_bool(np, "big-endian") | ||
501 | ? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT; | ||
502 | dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, | ||
503 | &dspi_regmap_config); | ||
504 | if (IS_ERR(dspi->regmap)) { | ||
505 | dev_err(&pdev->dev, "failed to init regmap: %ld\n", | ||
506 | PTR_ERR(dspi->regmap)); | ||
507 | return PTR_ERR(dspi->regmap); | ||
508 | } | ||
509 | |||
484 | dspi->irq = platform_get_irq(pdev, 0); | 510 | dspi->irq = platform_get_irq(pdev, 0); |
485 | if (dspi->irq < 0) { | 511 | if (dspi->irq < 0) { |
486 | dev_err(&pdev->dev, "can't get platform irq\n"); | 512 | dev_err(&pdev->dev, "can't get platform irq\n"); |