Lines Matching refs:bs
167 static void bcm2835_debugfs_create(struct bcm2835_spi *bs, in bcm2835_debugfs_create() argument
178 bs->debugfs_dir = dir; in bcm2835_debugfs_create()
182 &bs->count_transfer_polling); in bcm2835_debugfs_create()
184 &bs->count_transfer_irq); in bcm2835_debugfs_create()
186 &bs->count_transfer_irq_after_polling); in bcm2835_debugfs_create()
188 &bs->count_transfer_dma); in bcm2835_debugfs_create()
191 static void bcm2835_debugfs_remove(struct bcm2835_spi *bs) in bcm2835_debugfs_remove() argument
193 debugfs_remove_recursive(bs->debugfs_dir); in bcm2835_debugfs_remove()
194 bs->debugfs_dir = NULL; in bcm2835_debugfs_remove()
197 static void bcm2835_debugfs_create(struct bcm2835_spi *bs, in bcm2835_debugfs_create() argument
202 static void bcm2835_debugfs_remove(struct bcm2835_spi *bs) in bcm2835_debugfs_remove() argument
207 static inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned int reg) in bcm2835_rd() argument
209 return readl(bs->regs + reg); in bcm2835_rd()
212 static inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned int reg, u32 val) in bcm2835_wr() argument
214 writel(val, bs->regs + reg); in bcm2835_wr()
217 static inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) in bcm2835_rd_fifo() argument
221 while ((bs->rx_len) && in bcm2835_rd_fifo()
222 (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) { in bcm2835_rd_fifo()
223 byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); in bcm2835_rd_fifo()
224 if (bs->rx_buf) in bcm2835_rd_fifo()
225 *bs->rx_buf++ = byte; in bcm2835_rd_fifo()
226 bs->rx_len--; in bcm2835_rd_fifo()
230 static inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) in bcm2835_wr_fifo() argument
234 while ((bs->tx_len) && in bcm2835_wr_fifo()
235 (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { in bcm2835_wr_fifo()
236 byte = bs->tx_buf ? *bs->tx_buf++ : 0; in bcm2835_wr_fifo()
237 bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); in bcm2835_wr_fifo()
238 bs->tx_len--; in bcm2835_wr_fifo()
252 static inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) in bcm2835_rd_fifo_count() argument
257 bs->rx_len -= count; in bcm2835_rd_fifo_count()
260 val = bcm2835_rd(bs, BCM2835_SPI_FIFO); in bcm2835_rd_fifo_count()
262 memcpy(bs->rx_buf, &val, len); in bcm2835_rd_fifo_count()
263 bs->rx_buf += len; in bcm2835_rd_fifo_count()
278 static inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) in bcm2835_wr_fifo_count() argument
283 bs->tx_len -= count; in bcm2835_wr_fifo_count()
286 if (bs->tx_buf) { in bcm2835_wr_fifo_count()
288 memcpy(&val, bs->tx_buf, len); in bcm2835_wr_fifo_count()
289 bs->tx_buf += len; in bcm2835_wr_fifo_count()
293 bcm2835_wr(bs, BCM2835_SPI_FIFO, val); in bcm2835_wr_fifo_count()
306 static inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) in bcm2835_wait_tx_fifo_empty() argument
308 while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) in bcm2835_wait_tx_fifo_empty()
317 static inline void bcm2835_rd_fifo_blind(struct bcm2835_spi *bs, int count) in bcm2835_rd_fifo_blind() argument
321 count = min(count, bs->rx_len); in bcm2835_rd_fifo_blind()
322 bs->rx_len -= count; in bcm2835_rd_fifo_blind()
325 val = bcm2835_rd(bs, BCM2835_SPI_FIFO); in bcm2835_rd_fifo_blind()
326 if (bs->rx_buf) in bcm2835_rd_fifo_blind()
327 *bs->rx_buf++ = val; in bcm2835_rd_fifo_blind()
336 static inline void bcm2835_wr_fifo_blind(struct bcm2835_spi *bs, int count) in bcm2835_wr_fifo_blind() argument
340 count = min(count, bs->tx_len); in bcm2835_wr_fifo_blind()
341 bs->tx_len -= count; in bcm2835_wr_fifo_blind()
344 val = bs->tx_buf ? *bs->tx_buf++ : 0; in bcm2835_wr_fifo_blind()
345 bcm2835_wr(bs, BCM2835_SPI_FIFO, val); in bcm2835_wr_fifo_blind()
349 static void bcm2835_spi_reset_hw(struct bcm2835_spi *bs) in bcm2835_spi_reset_hw() argument
351 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); in bcm2835_spi_reset_hw()
369 bcm2835_wr(bs, BCM2835_SPI_CS, cs); in bcm2835_spi_reset_hw()
371 bcm2835_wr(bs, BCM2835_SPI_DLEN, 0); in bcm2835_spi_reset_hw()
376 struct bcm2835_spi *bs = dev_id; in bcm2835_spi_interrupt() local
377 u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); in bcm2835_spi_interrupt()
388 bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); in bcm2835_spi_interrupt()
390 bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE_3_4); in bcm2835_spi_interrupt()
392 if (bs->tx_len && cs & BCM2835_SPI_CS_DONE) in bcm2835_spi_interrupt()
393 bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); in bcm2835_spi_interrupt()
396 bcm2835_rd_fifo(bs); in bcm2835_spi_interrupt()
398 bcm2835_wr_fifo(bs); in bcm2835_spi_interrupt()
400 if (!bs->rx_len) { in bcm2835_spi_interrupt()
402 bcm2835_spi_reset_hw(bs); in bcm2835_spi_interrupt()
404 spi_finalize_current_transfer(bs->ctlr); in bcm2835_spi_interrupt()
415 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_transfer_one_irq() local
418 bs->count_transfer_irq++; in bcm2835_spi_transfer_one_irq()
424 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); in bcm2835_spi_transfer_one_irq()
428 bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); in bcm2835_spi_transfer_one_irq()
429 bcm2835_wr_fifo(bs); in bcm2835_spi_transfer_one_irq()
433 bcm2835_wr(bs, BCM2835_SPI_CS, cs); in bcm2835_spi_transfer_one_irq()
487 struct bcm2835_spi *bs, in bcm2835_spi_transfer_prologue() argument
492 bs->tfr = tfr; in bcm2835_spi_transfer_prologue()
493 bs->tx_prologue = 0; in bcm2835_spi_transfer_prologue()
494 bs->rx_prologue = 0; in bcm2835_spi_transfer_prologue()
495 bs->tx_spillover = false; in bcm2835_spi_transfer_prologue()
497 if (bs->tx_buf && !sg_is_last(&tfr->tx_sg.sgl[0])) in bcm2835_spi_transfer_prologue()
498 bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3; in bcm2835_spi_transfer_prologue()
500 if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) { in bcm2835_spi_transfer_prologue()
501 bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3; in bcm2835_spi_transfer_prologue()
503 if (bs->rx_prologue > bs->tx_prologue) { in bcm2835_spi_transfer_prologue()
504 if (!bs->tx_buf || sg_is_last(&tfr->tx_sg.sgl[0])) { in bcm2835_spi_transfer_prologue()
505 bs->tx_prologue = bs->rx_prologue; in bcm2835_spi_transfer_prologue()
507 bs->tx_prologue += 4; in bcm2835_spi_transfer_prologue()
508 bs->tx_spillover = in bcm2835_spi_transfer_prologue()
515 if (!bs->tx_prologue) in bcm2835_spi_transfer_prologue()
519 if (bs->rx_prologue) { in bcm2835_spi_transfer_prologue()
520 bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->rx_prologue); in bcm2835_spi_transfer_prologue()
521 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA in bcm2835_spi_transfer_prologue()
523 bcm2835_wr_fifo_count(bs, bs->rx_prologue); in bcm2835_spi_transfer_prologue()
524 bcm2835_wait_tx_fifo_empty(bs); in bcm2835_spi_transfer_prologue()
525 bcm2835_rd_fifo_count(bs, bs->rx_prologue); in bcm2835_spi_transfer_prologue()
526 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_RX in bcm2835_spi_transfer_prologue()
532 bs->rx_prologue, DMA_FROM_DEVICE); in bcm2835_spi_transfer_prologue()
534 sg_dma_address(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; in bcm2835_spi_transfer_prologue()
535 sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; in bcm2835_spi_transfer_prologue()
538 if (!bs->tx_buf) in bcm2835_spi_transfer_prologue()
545 tx_remaining = bs->tx_prologue - bs->rx_prologue; in bcm2835_spi_transfer_prologue()
547 bcm2835_wr(bs, BCM2835_SPI_DLEN, tx_remaining); in bcm2835_spi_transfer_prologue()
548 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA in bcm2835_spi_transfer_prologue()
550 bcm2835_wr_fifo_count(bs, tx_remaining); in bcm2835_spi_transfer_prologue()
551 bcm2835_wait_tx_fifo_empty(bs); in bcm2835_spi_transfer_prologue()
552 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX in bcm2835_spi_transfer_prologue()
556 if (likely(!bs->tx_spillover)) { in bcm2835_spi_transfer_prologue()
557 sg_dma_address(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; in bcm2835_spi_transfer_prologue()
558 sg_dma_len(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; in bcm2835_spi_transfer_prologue()
574 static void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) in bcm2835_spi_undo_prologue() argument
576 struct spi_transfer *tfr = bs->tfr; in bcm2835_spi_undo_prologue()
578 if (!bs->tx_prologue) in bcm2835_spi_undo_prologue()
581 if (bs->rx_prologue) { in bcm2835_spi_undo_prologue()
582 sg_dma_address(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; in bcm2835_spi_undo_prologue()
583 sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; in bcm2835_spi_undo_prologue()
586 if (!bs->tx_buf) in bcm2835_spi_undo_prologue()
589 if (likely(!bs->tx_spillover)) { in bcm2835_spi_undo_prologue()
590 sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; in bcm2835_spi_undo_prologue()
591 sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; in bcm2835_spi_undo_prologue()
593 sg_dma_len(&tfr->tx_sg.sgl[0]) = bs->tx_prologue - 4; in bcm2835_spi_undo_prologue()
598 bs->tx_prologue = 0; in bcm2835_spi_undo_prologue()
610 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_dma_rx_done() local
618 bs->tx_dma_active = false; in bcm2835_spi_dma_rx_done()
619 bs->rx_dma_active = false; in bcm2835_spi_dma_rx_done()
620 bcm2835_spi_undo_prologue(bs); in bcm2835_spi_dma_rx_done()
623 bcm2835_spi_reset_hw(bs); in bcm2835_spi_dma_rx_done()
638 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_dma_tx_done() local
641 while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) in bcm2835_spi_dma_tx_done()
642 bcm2835_wr(bs, BCM2835_SPI_CS, bs->target->clear_rx_cs); in bcm2835_spi_dma_tx_done()
644 bs->tx_dma_active = false; in bcm2835_spi_dma_tx_done()
652 if (cmpxchg(&bs->rx_dma_active, true, false)) in bcm2835_spi_dma_tx_done()
655 bcm2835_spi_undo_prologue(bs); in bcm2835_spi_dma_tx_done()
656 bcm2835_spi_reset_hw(bs); in bcm2835_spi_dma_tx_done()
673 struct bcm2835_spi *bs, in bcm2835_spi_prepare_sg() argument
714 bs->target = target; in bcm2835_spi_prepare_sg()
775 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_transfer_one_dma() local
780 bs->count_transfer_dma++; in bcm2835_spi_transfer_one_dma()
786 bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs); in bcm2835_spi_transfer_one_dma()
789 if (bs->tx_buf) { in bcm2835_spi_transfer_one_dma()
790 ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, target, true); in bcm2835_spi_transfer_one_dma()
792 cookie = dmaengine_submit(bs->fill_tx_desc); in bcm2835_spi_transfer_one_dma()
799 bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len); in bcm2835_spi_transfer_one_dma()
802 bcm2835_wr(bs, BCM2835_SPI_CS, in bcm2835_spi_transfer_one_dma()
805 bs->tx_dma_active = true; in bcm2835_spi_transfer_one_dma()
815 if (bs->rx_buf) { in bcm2835_spi_transfer_one_dma()
816 ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, target, false); in bcm2835_spi_transfer_one_dma()
824 bs->tx_dma_active = false; in bcm2835_spi_transfer_one_dma()
830 bs->rx_dma_active = true; in bcm2835_spi_transfer_one_dma()
837 if (!bs->rx_buf && !bs->tx_dma_active && in bcm2835_spi_transfer_one_dma()
838 cmpxchg(&bs->rx_dma_active, true, false)) { in bcm2835_spi_transfer_one_dma()
840 bcm2835_spi_reset_hw(bs); in bcm2835_spi_transfer_one_dma()
847 bcm2835_spi_reset_hw(bs); in bcm2835_spi_transfer_one_dma()
848 bcm2835_spi_undo_prologue(bs); in bcm2835_spi_transfer_one_dma()
865 struct bcm2835_spi *bs) in bcm2835_dma_release() argument
870 if (bs->fill_tx_desc) in bcm2835_dma_release()
871 dmaengine_desc_free(bs->fill_tx_desc); in bcm2835_dma_release()
873 if (bs->fill_tx_addr) in bcm2835_dma_release()
875 bs->fill_tx_addr, sizeof(u32), in bcm2835_dma_release()
891 struct bcm2835_spi *bs) in bcm2835_dma_init() argument
935 bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev, in bcm2835_dma_init()
939 if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) { in bcm2835_dma_init()
941 bs->fill_tx_addr = 0; in bcm2835_dma_init()
946 bs->fill_tx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_tx, in bcm2835_dma_init()
947 bs->fill_tx_addr, in bcm2835_dma_init()
950 if (!bs->fill_tx_desc) { in bcm2835_dma_init()
956 ret = dmaengine_desc_set_reuse(bs->fill_tx_desc); in bcm2835_dma_init()
985 bcm2835_dma_release(ctlr, bs); in bcm2835_dma_init()
1002 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_transfer_one_poll() local
1006 bs->count_transfer_polling++; in bcm2835_spi_transfer_one_poll()
1009 bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); in bcm2835_spi_transfer_one_poll()
1015 bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); in bcm2835_spi_transfer_one_poll()
1021 while (bs->rx_len) { in bcm2835_spi_transfer_one_poll()
1023 bcm2835_wr_fifo(bs); in bcm2835_spi_transfer_one_poll()
1026 bcm2835_rd_fifo(bs); in bcm2835_spi_transfer_one_poll()
1031 if (bs->rx_len && time_after(jiffies, timeout)) { in bcm2835_spi_transfer_one_poll()
1035 bs->tx_len, bs->rx_len); in bcm2835_spi_transfer_one_poll()
1039 bs->count_transfer_irq_after_polling++; in bcm2835_spi_transfer_one_poll()
1047 bcm2835_spi_reset_hw(bs); in bcm2835_spi_transfer_one_poll()
1056 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_transfer_one() local
1065 if (spi_hz >= bs->clk_hz / 2) { in bcm2835_spi_transfer_one()
1069 cdiv = DIV_ROUND_UP(bs->clk_hz, spi_hz); in bcm2835_spi_transfer_one()
1077 tfr->effective_speed_hz = cdiv ? (bs->clk_hz / cdiv) : (bs->clk_hz / 65536); in bcm2835_spi_transfer_one()
1078 bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); in bcm2835_spi_transfer_one()
1085 bs->tx_buf = tfr->tx_buf; in bcm2835_spi_transfer_one()
1086 bs->rx_buf = tfr->rx_buf; in bcm2835_spi_transfer_one()
1087 bs->tx_len = tfr->len; in bcm2835_spi_transfer_one()
1088 bs->rx_len = tfr->len; in bcm2835_spi_transfer_one()
1118 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_prepare_message() local
1125 bcm2835_wr(bs, BCM2835_SPI_CS, target->prepare_cs); in bcm2835_spi_prepare_message()
1133 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_handle_err() local
1138 bs->tx_dma_active = false; in bcm2835_spi_handle_err()
1142 bs->rx_dma_active = false; in bcm2835_spi_handle_err()
1144 bcm2835_spi_undo_prologue(bs); in bcm2835_spi_handle_err()
1147 bcm2835_spi_reset_hw(bs); in bcm2835_spi_handle_err()
1154 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_cleanup() local
1165 gpiod_put(bs->cs_gpio); in bcm2835_spi_cleanup()
1173 struct bcm2835_spi *bs, in bcm2835_spi_setup_dma() argument
1225 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_setup() local
1239 ret = bcm2835_spi_setup_dma(ctlr, spi, bs, target); in bcm2835_spi_setup()
1315 bs->cs_gpio = gpiod_get(&spi->dev, "cs", GPIOD_OUT_LOW); in bcm2835_spi_setup()
1317 if (IS_ERR(bs->cs_gpio)) { in bcm2835_spi_setup()
1318 ret = PTR_ERR(bs->cs_gpio); in bcm2835_spi_setup()
1322 spi_set_csgpiod(spi, 0, bs->cs_gpio); in bcm2835_spi_setup()
1338 struct bcm2835_spi *bs; in bcm2835_spi_probe() local
1341 ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*bs)); in bcm2835_spi_probe()
1359 bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_probe()
1360 bs->ctlr = ctlr; in bcm2835_spi_probe()
1362 bs->regs = devm_platform_ioremap_resource(pdev, 0); in bcm2835_spi_probe()
1363 if (IS_ERR(bs->regs)) in bcm2835_spi_probe()
1364 return PTR_ERR(bs->regs); in bcm2835_spi_probe()
1366 bs->clk = devm_clk_get_enabled(&pdev->dev, NULL); in bcm2835_spi_probe()
1367 if (IS_ERR(bs->clk)) in bcm2835_spi_probe()
1368 return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk), in bcm2835_spi_probe()
1371 ctlr->max_speed_hz = clk_get_rate(bs->clk) / 2; in bcm2835_spi_probe()
1373 bs->irq = platform_get_irq(pdev, 0); in bcm2835_spi_probe()
1374 if (bs->irq < 0) in bcm2835_spi_probe()
1375 return bs->irq; in bcm2835_spi_probe()
1377 bs->clk_hz = clk_get_rate(bs->clk); in bcm2835_spi_probe()
1379 err = bcm2835_dma_init(ctlr, &pdev->dev, bs); in bcm2835_spi_probe()
1384 bcm2835_wr(bs, BCM2835_SPI_CS, in bcm2835_spi_probe()
1387 err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, in bcm2835_spi_probe()
1388 IRQF_SHARED, dev_name(&pdev->dev), bs); in bcm2835_spi_probe()
1401 bcm2835_debugfs_create(bs, dev_name(&pdev->dev)); in bcm2835_spi_probe()
1406 bcm2835_dma_release(ctlr, bs); in bcm2835_spi_probe()
1413 struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); in bcm2835_spi_remove() local
1415 bcm2835_debugfs_remove(bs); in bcm2835_spi_remove()
1419 bcm2835_dma_release(ctlr, bs); in bcm2835_spi_remove()
1422 bcm2835_wr(bs, BCM2835_SPI_CS, in bcm2835_spi_remove()