diff options
Diffstat (limited to 'drivers/spi/spi-fsl-dspi.c')
-rw-r--r-- | drivers/spi/spi-fsl-dspi.c | 100 |
1 files changed, 62 insertions, 38 deletions
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index ec79f726672a..d565eeee3bd8 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,11 +109,11 @@ 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 | ||
115 | struct spi_transfer *cur_transfer; | 116 | struct spi_transfer *cur_transfer; |
116 | struct chip_data *cur_chip; | 117 | struct chip_data *cur_chip; |
117 | size_t len; | 118 | size_t len; |
118 | void *tx; | 119 | void *tx; |
@@ -123,24 +124,17 @@ struct fsl_dspi { | |||
123 | u8 cs; | 124 | u8 cs; |
124 | u16 void_write_data; | 125 | u16 void_write_data; |
125 | 126 | ||
126 | wait_queue_head_t waitq; | 127 | wait_queue_head_t waitq; |
127 | u32 waitflags; | 128 | u32 waitflags; |
128 | }; | 129 | }; |
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) |
@@ -338,7 +342,8 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
338 | /* Only alloc on first setup */ | 342 | /* Only alloc on first setup */ |
339 | chip = spi_get_ctldata(spi); | 343 | chip = spi_get_ctldata(spi); |
340 | if (chip == NULL) { | 344 | if (chip == NULL) { |
341 | chip = kcalloc(1, sizeof(struct chip_data), GFP_KERNEL); | 345 | chip = devm_kzalloc(&spi->dev, sizeof(struct chip_data), |
346 | GFP_KERNEL); | ||
342 | if (!chip) | 347 | if (!chip) |
343 | return -ENOMEM; | 348 | return -ENOMEM; |
344 | } | 349 | } |
@@ -349,7 +354,6 @@ static int dspi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
349 | fmsz = spi->bits_per_word - 1; | 354 | fmsz = spi->bits_per_word - 1; |
350 | } else { | 355 | } else { |
351 | pr_err("Invalid wordsize\n"); | 356 | pr_err("Invalid wordsize\n"); |
352 | kfree(chip); | ||
353 | return -ENODEV; | 357 | return -ENODEV; |
354 | } | 358 | } |
355 | 359 | ||
@@ -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 { |
@@ -420,7 +426,6 @@ static int dspi_suspend(struct device *dev) | |||
420 | 426 | ||
421 | static int dspi_resume(struct device *dev) | 427 | static int dspi_resume(struct device *dev) |
422 | { | 428 | { |
423 | |||
424 | struct spi_master *master = dev_get_drvdata(dev); | 429 | struct spi_master *master = dev_get_drvdata(dev); |
425 | struct fsl_dspi *dspi = spi_master_get_devdata(master); | 430 | struct fsl_dspi *dspi = spi_master_get_devdata(master); |
426 | 431 | ||
@@ -431,8 +436,13 @@ static int dspi_resume(struct device *dev) | |||
431 | } | 436 | } |
432 | #endif /* CONFIG_PM_SLEEP */ | 437 | #endif /* CONFIG_PM_SLEEP */ |
433 | 438 | ||
434 | static const struct dev_pm_ops dspi_pm = { | 439 | static SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume); |
435 | SET_SYSTEM_SLEEP_PM_OPS(dspi_suspend, dspi_resume) | 440 | |
441 | static struct regmap_config dspi_regmap_config = { | ||
442 | .reg_bits = 32, | ||
443 | .val_bits = 32, | ||
444 | .reg_stride = 4, | ||
445 | .max_register = 0x88, | ||
436 | }; | 446 | }; |
437 | 447 | ||
438 | static int dspi_probe(struct platform_device *pdev) | 448 | static int dspi_probe(struct platform_device *pdev) |
@@ -441,6 +451,7 @@ static int dspi_probe(struct platform_device *pdev) | |||
441 | struct spi_master *master; | 451 | struct spi_master *master; |
442 | struct fsl_dspi *dspi; | 452 | struct fsl_dspi *dspi; |
443 | struct resource *res; | 453 | struct resource *res; |
454 | void __iomem *base; | ||
444 | int ret = 0, cs_num, bus_num; | 455 | int ret = 0, cs_num, bus_num; |
445 | 456 | ||
446 | master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); | 457 | master = spi_alloc_master(&pdev->dev, sizeof(struct fsl_dspi)); |
@@ -475,12 +486,24 @@ static int dspi_probe(struct platform_device *pdev) | |||
475 | master->bus_num = bus_num; | 486 | master->bus_num = bus_num; |
476 | 487 | ||
477 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 488 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
478 | dspi->base = devm_ioremap_resource(&pdev->dev, res); | 489 | base = devm_ioremap_resource(&pdev->dev, res); |
479 | if (IS_ERR(dspi->base)) { | 490 | if (IS_ERR(base)) { |
480 | ret = PTR_ERR(dspi->base); | 491 | ret = PTR_ERR(base); |
481 | goto out_master_put; | 492 | goto out_master_put; |
482 | } | 493 | } |
483 | 494 | ||
495 | dspi_regmap_config.lock_arg = dspi; | ||
496 | dspi_regmap_config.val_format_endian = | ||
497 | of_property_read_bool(np, "big-endian") | ||
498 | ? REGMAP_ENDIAN_BIG : REGMAP_ENDIAN_DEFAULT; | ||
499 | dspi->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dspi", base, | ||
500 | &dspi_regmap_config); | ||
501 | if (IS_ERR(dspi->regmap)) { | ||
502 | dev_err(&pdev->dev, "failed to init regmap: %ld\n", | ||
503 | PTR_ERR(dspi->regmap)); | ||
504 | return PTR_ERR(dspi->regmap); | ||
505 | } | ||
506 | |||
484 | dspi->irq = platform_get_irq(pdev, 0); | 507 | dspi->irq = platform_get_irq(pdev, 0); |
485 | if (dspi->irq < 0) { | 508 | if (dspi->irq < 0) { |
486 | dev_err(&pdev->dev, "can't get platform irq\n"); | 509 | dev_err(&pdev->dev, "can't get platform irq\n"); |
@@ -504,7 +527,7 @@ static int dspi_probe(struct platform_device *pdev) | |||
504 | clk_prepare_enable(dspi->clk); | 527 | clk_prepare_enable(dspi->clk); |
505 | 528 | ||
506 | init_waitqueue_head(&dspi->waitq); | 529 | init_waitqueue_head(&dspi->waitq); |
507 | platform_set_drvdata(pdev, dspi); | 530 | platform_set_drvdata(pdev, master); |
508 | 531 | ||
509 | ret = spi_bitbang_start(&dspi->bitbang); | 532 | ret = spi_bitbang_start(&dspi->bitbang); |
510 | if (ret != 0) { | 533 | if (ret != 0) { |
@@ -525,7 +548,8 @@ out_master_put: | |||
525 | 548 | ||
526 | static int dspi_remove(struct platform_device *pdev) | 549 | static int dspi_remove(struct platform_device *pdev) |
527 | { | 550 | { |
528 | struct fsl_dspi *dspi = platform_get_drvdata(pdev); | 551 | struct spi_master *master = platform_get_drvdata(pdev); |
552 | struct fsl_dspi *dspi = spi_master_get_devdata(master); | ||
529 | 553 | ||
530 | /* Disconnect from the SPI framework */ | 554 | /* Disconnect from the SPI framework */ |
531 | spi_bitbang_stop(&dspi->bitbang); | 555 | spi_bitbang_stop(&dspi->bitbang); |