Lines Matching +full:fiq +full:- +full:based

1 // SPDX-License-Identifier: GPL-2.0-only
4 * Copyright 2006-2009 Simtec Electronics
21 #include <linux/spi/s3c24xx-fiq.h>
24 #include <asm/fiq.h>
26 #include "spi-s3c24xx-regs.h"
29 * struct s3c24xx_spi_devstate - per device data
80 return spi_master_get_devdata(sdev->master); in to_hw()
85 struct s3c24xx_spi_devstate *cs = spi->controller_state; in s3c24xx_spi_chipsel()
92 writeb(cs->spcon, hw->regs + S3C2410_SPCON); in s3c24xx_spi_chipsel()
96 writeb(cs->spcon | S3C2410_SPCON_ENSCK, in s3c24xx_spi_chipsel()
97 hw->regs + S3C2410_SPCON); in s3c24xx_spi_chipsel()
106 struct s3c24xx_spi_devstate *cs = spi->controller_state; in s3c24xx_spi_update_state()
111 hz = t ? t->speed_hz : spi->max_speed_hz; in s3c24xx_spi_update_state()
114 hz = spi->max_speed_hz; in s3c24xx_spi_update_state()
116 if (spi->mode != cs->mode) { in s3c24xx_spi_update_state()
119 if (spi->mode & SPI_CPHA) in s3c24xx_spi_update_state()
122 if (spi->mode & SPI_CPOL) in s3c24xx_spi_update_state()
125 cs->mode = spi->mode; in s3c24xx_spi_update_state()
126 cs->spcon = spcon; in s3c24xx_spi_update_state()
129 if (cs->hz != hz) { in s3c24xx_spi_update_state()
130 clk = clk_get_rate(hw->clk); in s3c24xx_spi_update_state()
131 div = DIV_ROUND_UP(clk, hz * 2) - 1; in s3c24xx_spi_update_state()
136 dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n", in s3c24xx_spi_update_state()
139 cs->hz = hz; in s3c24xx_spi_update_state()
140 cs->sppre = div; in s3c24xx_spi_update_state()
149 struct s3c24xx_spi_devstate *cs = spi->controller_state; in s3c24xx_spi_setupxfer()
155 writeb(cs->sppre, hw->regs + S3C2410_SPPRE); in s3c24xx_spi_setupxfer()
162 struct s3c24xx_spi_devstate *cs = spi->controller_state; in s3c24xx_spi_setup()
168 cs = devm_kzalloc(&spi->dev, in s3c24xx_spi_setup()
172 return -ENOMEM; in s3c24xx_spi_setup()
174 cs->spcon = SPCON_DEFAULT; in s3c24xx_spi_setup()
175 cs->hz = -1; in s3c24xx_spi_setup()
176 spi->controller_state = cs; in s3c24xx_spi_setup()
184 mutex_lock(&hw->bitbang.lock); in s3c24xx_spi_setup()
185 if (!hw->bitbang.busy) { in s3c24xx_spi_setup()
186 hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); in s3c24xx_spi_setup()
189 mutex_unlock(&hw->bitbang.lock); in s3c24xx_spi_setup()
196 return hw->tx ? hw->tx[count] : 0; in hw_txbyte()
200 /* Support for FIQ based pseudo-DMA to improve the transfer speed.
203 * used by the FIQ core to move data between main memory and the peripheral
209 * struct spi_fiq_code - FIQ code and header
212 * @data: The code itself to install as a FIQ handler.
221 * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
224 * Claim the FIQ handler (only one can be active at any one time) and
229 * as normal, since the IRQ will have been re-routed to the FIQ handler.
239 if (!hw->fiq_claimed) { in s3c24xx_spi_tryfiq()
240 /* try and claim fiq if we haven't got it, and if not in s3c24xx_spi_tryfiq()
243 ret = claim_fiq(&hw->fiq_handler); in s3c24xx_spi_tryfiq()
248 if (hw->tx && !hw->rx) in s3c24xx_spi_tryfiq()
250 else if (hw->rx && !hw->tx) in s3c24xx_spi_tryfiq()
255 regs.uregs[fiq_rspi] = (long)hw->regs; in s3c24xx_spi_tryfiq()
256 regs.uregs[fiq_rrx] = (long)hw->rx; in s3c24xx_spi_tryfiq()
257 regs.uregs[fiq_rtx] = (long)hw->tx + 1; in s3c24xx_spi_tryfiq()
258 regs.uregs[fiq_rcount] = hw->len - 1; in s3c24xx_spi_tryfiq()
262 if (hw->fiq_mode != mode) { in s3c24xx_spi_tryfiq()
263 hw->fiq_mode = mode; in s3c24xx_spi_tryfiq()
281 ack_ptr = (u32 *)&code->data[code->ack_offset]; in s3c24xx_spi_tryfiq()
282 set_fiq_handler(&code->data, code->length); in s3c24xx_spi_tryfiq()
285 s3c24xx_set_fiq(hw->irq, ack_ptr, true); in s3c24xx_spi_tryfiq()
287 hw->fiq_mode = mode; in s3c24xx_spi_tryfiq()
288 hw->fiq_inuse = 1; in s3c24xx_spi_tryfiq()
292 * s3c24xx_spi_fiqop - FIQ core code callback
296 * Called by the FIQ code when another module wants to use the FIQ, so
306 if (hw->fiq_inuse) in s3c24xx_spi_fiqop()
307 ret = -EBUSY; in s3c24xx_spi_fiqop()
309 /* note, we do not need to unroute the FIQ, as the FIQ in s3c24xx_spi_fiqop()
310 * vector code de-routes it to signal the end of transfer */ in s3c24xx_spi_fiqop()
312 hw->fiq_mode = FIQ_MODE_NONE; in s3c24xx_spi_fiqop()
313 hw->fiq_claimed = 0; in s3c24xx_spi_fiqop()
315 hw->fiq_claimed = 1; in s3c24xx_spi_fiqop()
322 * s3c24xx_spi_initfiq - setup the information for the FIQ core
325 * Setup the fiq_handler block to pass to the FIQ core.
329 hw->fiq_handler.dev_id = hw; in s3c24xx_spi_initfiq()
330 hw->fiq_handler.name = dev_name(hw->dev); in s3c24xx_spi_initfiq()
331 hw->fiq_handler.fiq_op = s3c24xx_spi_fiqop; in s3c24xx_spi_initfiq()
335 * s3c24xx_spi_usefiq - return if we should be using FIQ.
339 * allowed to use the FIQ.
343 return hw->pdata->use_fiq; in s3c24xx_spi_usefiq()
347 * s3c24xx_spi_usingfiq - return if channel is using FIQ
350 * Return whether the channel is currently using the FIQ (separate from
351 * whether the FIQ is claimed).
355 return spi->fiq_inuse; in s3c24xx_spi_usingfiq()
370 hw->tx = t->tx_buf; in s3c24xx_spi_txrx()
371 hw->rx = t->rx_buf; in s3c24xx_spi_txrx()
372 hw->len = t->len; in s3c24xx_spi_txrx()
373 hw->count = 0; in s3c24xx_spi_txrx()
375 init_completion(&hw->done); in s3c24xx_spi_txrx()
377 hw->fiq_inuse = 0; in s3c24xx_spi_txrx()
378 if (s3c24xx_spi_usefiq(hw) && t->len >= 3) in s3c24xx_spi_txrx()
382 writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT); in s3c24xx_spi_txrx()
384 wait_for_completion(&hw->done); in s3c24xx_spi_txrx()
385 return hw->count; in s3c24xx_spi_txrx()
391 unsigned int spsta = readb(hw->regs + S3C2410_SPSTA); in s3c24xx_spi_irq()
392 unsigned int count = hw->count; in s3c24xx_spi_irq()
395 dev_dbg(hw->dev, "data-collision\n"); in s3c24xx_spi_irq()
396 complete(&hw->done); in s3c24xx_spi_irq()
401 dev_dbg(hw->dev, "spi not ready for tx?\n"); in s3c24xx_spi_irq()
402 complete(&hw->done); in s3c24xx_spi_irq()
407 hw->count++; in s3c24xx_spi_irq()
409 if (hw->rx) in s3c24xx_spi_irq()
410 hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT); in s3c24xx_spi_irq()
414 if (count < hw->len) in s3c24xx_spi_irq()
415 writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT); in s3c24xx_spi_irq()
417 complete(&hw->done); in s3c24xx_spi_irq()
419 hw->count = hw->len; in s3c24xx_spi_irq()
420 hw->fiq_inuse = 0; in s3c24xx_spi_irq()
422 if (hw->rx) in s3c24xx_spi_irq()
423 hw->rx[hw->len-1] = readb(hw->regs + S3C2410_SPRDAT); in s3c24xx_spi_irq()
425 complete(&hw->done); in s3c24xx_spi_irq()
436 clk_enable(hw->clk); in s3c24xx_spi_initialsetup()
440 writeb(0xff, hw->regs + S3C2410_SPPRE); in s3c24xx_spi_initialsetup()
441 writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); in s3c24xx_spi_initialsetup()
442 writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); in s3c24xx_spi_initialsetup()
452 master = devm_spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); in s3c24xx_spi_probe()
454 dev_err(&pdev->dev, "No memory for spi_master\n"); in s3c24xx_spi_probe()
455 return -ENOMEM; in s3c24xx_spi_probe()
460 hw->master = master; in s3c24xx_spi_probe()
461 hw->pdata = pdata = dev_get_platdata(&pdev->dev); in s3c24xx_spi_probe()
462 hw->dev = &pdev->dev; in s3c24xx_spi_probe()
465 dev_err(&pdev->dev, "No platform data supplied\n"); in s3c24xx_spi_probe()
466 return -ENOENT; in s3c24xx_spi_probe()
470 init_completion(&hw->done); in s3c24xx_spi_probe()
472 /* initialise fiq handler */ in s3c24xx_spi_probe()
478 /* the spi->mode bits understood by this driver: */ in s3c24xx_spi_probe()
479 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; in s3c24xx_spi_probe()
481 master->num_chipselect = hw->pdata->num_cs; in s3c24xx_spi_probe()
482 master->bus_num = pdata->bus_num; in s3c24xx_spi_probe()
483 master->bits_per_word_mask = SPI_BPW_MASK(8); in s3c24xx_spi_probe()
485 master->flags = SPI_MASTER_GPIO_SS; in s3c24xx_spi_probe()
486 master->use_gpio_descriptors = true; in s3c24xx_spi_probe()
490 hw->bitbang.master = hw->master; in s3c24xx_spi_probe()
491 hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer; in s3c24xx_spi_probe()
492 hw->bitbang.chipselect = s3c24xx_spi_chipsel; in s3c24xx_spi_probe()
493 hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; in s3c24xx_spi_probe()
495 hw->master->setup = s3c24xx_spi_setup; in s3c24xx_spi_probe()
497 dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); in s3c24xx_spi_probe()
500 hw->regs = devm_platform_ioremap_resource(pdev, 0); in s3c24xx_spi_probe()
501 if (IS_ERR(hw->regs)) in s3c24xx_spi_probe()
502 return PTR_ERR(hw->regs); in s3c24xx_spi_probe()
504 hw->irq = platform_get_irq(pdev, 0); in s3c24xx_spi_probe()
505 if (hw->irq < 0) in s3c24xx_spi_probe()
506 return -ENOENT; in s3c24xx_spi_probe()
508 err = devm_request_irq(&pdev->dev, hw->irq, s3c24xx_spi_irq, 0, in s3c24xx_spi_probe()
509 pdev->name, hw); in s3c24xx_spi_probe()
511 dev_err(&pdev->dev, "Cannot claim IRQ\n"); in s3c24xx_spi_probe()
515 hw->clk = devm_clk_get(&pdev->dev, "spi"); in s3c24xx_spi_probe()
516 if (IS_ERR(hw->clk)) { in s3c24xx_spi_probe()
517 dev_err(&pdev->dev, "No clock for device\n"); in s3c24xx_spi_probe()
518 return PTR_ERR(hw->clk); in s3c24xx_spi_probe()
525 err = spi_bitbang_start(&hw->bitbang); in s3c24xx_spi_probe()
527 dev_err(&pdev->dev, "Failed to register SPI master\n"); in s3c24xx_spi_probe()
534 clk_disable(hw->clk); in s3c24xx_spi_probe()
543 spi_bitbang_stop(&hw->bitbang); in s3c24xx_spi_remove()
544 clk_disable(hw->clk); in s3c24xx_spi_remove()
545 spi_master_put(hw->master); in s3c24xx_spi_remove()
557 ret = spi_master_suspend(hw->master); in s3c24xx_spi_suspend()
561 clk_disable(hw->clk); in s3c24xx_spi_suspend()
570 return spi_master_resume(hw->master); in s3c24xx_spi_resume()
583 MODULE_ALIAS("platform:s3c2410-spi");
588 .name = "s3c2410-spi",