Lines Matching full:spicc
2 * Driver for Amlogic Meson SPI communication controller (SPICC)
34 * reading threshold, SPICC starts a reading DMA burst, which reads the preset
37 * writing threshold, SPICC starts a writing request burst, which reads the
206 static void meson_spicc_oen_enable(struct meson_spicc_device *spicc) in meson_spicc_oen_enable() argument
210 if (!spicc->data->has_oen) { in meson_spicc_oen_enable()
212 spicc->pins_idle_high = pinctrl_lookup_state(spicc->pinctrl, in meson_spicc_oen_enable()
214 if (IS_ERR(spicc->pins_idle_high)) { in meson_spicc_oen_enable()
215 dev_warn(&spicc->pdev->dev, "can't get idle-high pinctrl\n"); in meson_spicc_oen_enable()
216 spicc->pins_idle_high = NULL; in meson_spicc_oen_enable()
218 spicc->pins_idle_low = pinctrl_lookup_state(spicc->pinctrl, in meson_spicc_oen_enable()
220 if (IS_ERR(spicc->pins_idle_low)) { in meson_spicc_oen_enable()
221 dev_warn(&spicc->pdev->dev, "can't get idle-low pinctrl\n"); in meson_spicc_oen_enable()
222 spicc->pins_idle_low = NULL; in meson_spicc_oen_enable()
227 conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) | in meson_spicc_oen_enable()
230 writel_relaxed(conf, spicc->base + SPICC_ENH_CTL0); in meson_spicc_oen_enable()
233 static int meson_spicc_dma_map(struct meson_spicc_device *spicc, in meson_spicc_dma_map() argument
236 struct device *dev = spicc->host->dev.parent; in meson_spicc_dma_map()
249 spicc->tx_dma = t->tx_dma; in meson_spicc_dma_map()
250 spicc->rx_dma = t->rx_dma; in meson_spicc_dma_map()
255 static void meson_spicc_dma_unmap(struct meson_spicc_device *spicc, in meson_spicc_dma_unmap() argument
258 struct device *dev = spicc->host->dev.parent; in meson_spicc_dma_unmap()
270 static u32 meson_spicc_calc_dma_len(struct meson_spicc_device *spicc, in meson_spicc_calc_dma_len() argument
275 if (len <= spicc->data->fifo_size) { in meson_spicc_calc_dma_len()
303 static void meson_spicc_setup_dma(struct meson_spicc_device *spicc) in meson_spicc_setup_dma() argument
314 writel_relaxed(spicc->tx_dma, spicc->base + SPICC_DRADDR); in meson_spicc_setup_dma()
315 writel_relaxed(spicc->rx_dma, spicc->base + SPICC_DWADDR); in meson_spicc_setup_dma()
322 spicc->base + SPICC_CONREG); in meson_spicc_setup_dma()
324 len = meson_spicc_calc_dma_len(spicc, spicc->xfer_remain, in meson_spicc_setup_dma()
326 spicc->xfer_remain -= len; in meson_spicc_setup_dma()
330 if (spicc->tx_dma) { in meson_spicc_setup_dma()
331 spicc->tx_dma += len; in meson_spicc_setup_dma()
333 txfifo_thres = spicc->data->fifo_size - dma_burst_len; in meson_spicc_setup_dma()
338 if (spicc->rx_dma) { in meson_spicc_setup_dma()
339 spicc->rx_dma += len; in meson_spicc_setup_dma()
346 writel_relaxed(count_en, spicc->base + SPICC_LD_CNTL0); in meson_spicc_setup_dma()
347 writel_relaxed(ld_ctr1, spicc->base + SPICC_LD_CNTL1); in meson_spicc_setup_dma()
354 spicc->base + SPICC_DMAREG); in meson_spicc_setup_dma()
357 static irqreturn_t meson_spicc_dma_irq(struct meson_spicc_device *spicc) in meson_spicc_dma_irq() argument
359 if (readl_relaxed(spicc->base + SPICC_DMAREG) & SPICC_DMA_ENABLE) in meson_spicc_dma_irq()
362 if (spicc->xfer_remain) { in meson_spicc_dma_irq()
363 meson_spicc_setup_dma(spicc); in meson_spicc_dma_irq()
365 writel_bits_relaxed(SPICC_SMC, 0, spicc->base + SPICC_CONREG); in meson_spicc_dma_irq()
366 writel_relaxed(0, spicc->base + SPICC_INTREG); in meson_spicc_dma_irq()
367 writel_relaxed(0, spicc->base + SPICC_DMAREG); in meson_spicc_dma_irq()
368 meson_spicc_dma_unmap(spicc, spicc->xfer); in meson_spicc_dma_irq()
369 complete(&spicc->done); in meson_spicc_dma_irq()
375 static inline bool meson_spicc_txfull(struct meson_spicc_device *spicc) in meson_spicc_txfull() argument
378 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_txfull()
381 static inline bool meson_spicc_rxready(struct meson_spicc_device *spicc) in meson_spicc_rxready() argument
384 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_rxready()
387 static inline u32 meson_spicc_pull_data(struct meson_spicc_device *spicc) in meson_spicc_pull_data() argument
389 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_pull_data()
395 byte = *spicc->tx_buf++; in meson_spicc_pull_data()
400 spicc->tx_remain--; in meson_spicc_pull_data()
404 static inline void meson_spicc_push_data(struct meson_spicc_device *spicc, in meson_spicc_push_data() argument
407 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_push_data()
413 *spicc->rx_buf++ = byte; in meson_spicc_push_data()
417 spicc->rx_remain--; in meson_spicc_push_data()
420 static inline void meson_spicc_rx(struct meson_spicc_device *spicc) in meson_spicc_rx() argument
423 while (spicc->rx_remain && in meson_spicc_rx()
424 meson_spicc_rxready(spicc)) in meson_spicc_rx()
425 meson_spicc_push_data(spicc, in meson_spicc_rx()
426 readl_relaxed(spicc->base + SPICC_RXDATA)); in meson_spicc_rx()
429 static inline void meson_spicc_tx(struct meson_spicc_device *spicc) in meson_spicc_tx() argument
432 while (spicc->tx_remain && in meson_spicc_tx()
433 !meson_spicc_txfull(spicc)) in meson_spicc_tx()
434 writel_relaxed(meson_spicc_pull_data(spicc), in meson_spicc_tx()
435 spicc->base + SPICC_TXDATA); in meson_spicc_tx()
438 static inline void meson_spicc_setup_burst(struct meson_spicc_device *spicc) in meson_spicc_setup_burst() argument
442 spicc->xfer_remain / in meson_spicc_setup_burst()
443 spicc->bytes_per_word, in meson_spicc_setup_burst()
444 spicc->data->fifo_size); in meson_spicc_setup_burst()
446 spicc->tx_remain = burst_len; in meson_spicc_setup_burst()
447 spicc->rx_remain = burst_len; in meson_spicc_setup_burst()
448 spicc->xfer_remain -= burst_len * spicc->bytes_per_word; in meson_spicc_setup_burst()
454 spicc->base + SPICC_CONREG); in meson_spicc_setup_burst()
457 meson_spicc_tx(spicc); in meson_spicc_setup_burst()
462 struct meson_spicc_device *spicc = (void *) data; in meson_spicc_irq() local
464 writel_bits_relaxed(SPICC_TC, SPICC_TC, spicc->base + SPICC_STATREG); in meson_spicc_irq()
466 if (spicc->using_dma) in meson_spicc_irq()
467 return meson_spicc_dma_irq(spicc); in meson_spicc_irq()
470 meson_spicc_rx(spicc); in meson_spicc_irq()
472 if (!spicc->xfer_remain) { in meson_spicc_irq()
474 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_irq()
476 complete(&spicc->done); in meson_spicc_irq()
482 meson_spicc_setup_burst(spicc); in meson_spicc_irq()
485 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_irq()
490 static void meson_spicc_auto_io_delay(struct meson_spicc_device *spicc) in meson_spicc_auto_io_delay() argument
496 if (spicc->data->has_enhance_clk_div) { in meson_spicc_auto_io_delay()
498 readl_relaxed(spicc->base + SPICC_ENH_CTL0)); in meson_spicc_auto_io_delay()
503 readl_relaxed(spicc->base + SPICC_CONREG)); in meson_spicc_auto_io_delay()
510 hz = clk_get_rate(spicc->clk); in meson_spicc_auto_io_delay()
525 conf = readl_relaxed(spicc->base + SPICC_TESTREG); in meson_spicc_auto_io_delay()
530 writel_relaxed(conf, spicc->base + SPICC_TESTREG); in meson_spicc_auto_io_delay()
533 static void meson_spicc_setup_xfer(struct meson_spicc_device *spicc, in meson_spicc_setup_xfer() argument
539 conf = conf_orig = readl_relaxed(spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
544 (spicc->bytes_per_word << 3) - 1); in meson_spicc_setup_xfer()
548 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
550 clk_set_rate(spicc->clk, xfer->speed_hz); in meson_spicc_setup_xfer()
552 meson_spicc_auto_io_delay(spicc); in meson_spicc_setup_xfer()
554 writel_relaxed(0, spicc->base + SPICC_DMAREG); in meson_spicc_setup_xfer()
557 static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc) in meson_spicc_reset_fifo() argument
559 if (spicc->data->has_oen) in meson_spicc_reset_fifo()
562 spicc->base + SPICC_ENH_CTL0); in meson_spicc_reset_fifo()
565 spicc->base + SPICC_TESTREG); in meson_spicc_reset_fifo()
567 while (meson_spicc_rxready(spicc)) in meson_spicc_reset_fifo()
568 readl_relaxed(spicc->base + SPICC_RXDATA); in meson_spicc_reset_fifo()
570 if (spicc->data->has_oen) in meson_spicc_reset_fifo()
572 spicc->base + SPICC_ENH_CTL0); in meson_spicc_reset_fifo()
579 struct meson_spicc_device *spicc = spi_controller_get_devdata(host); in meson_spicc_transfer_one() local
583 spicc->xfer = xfer; in meson_spicc_transfer_one()
586 spicc->tx_buf = (u8 *)xfer->tx_buf; in meson_spicc_transfer_one()
587 spicc->rx_buf = (u8 *)xfer->rx_buf; in meson_spicc_transfer_one()
588 spicc->xfer_remain = xfer->len; in meson_spicc_transfer_one()
591 spicc->bytes_per_word = in meson_spicc_transfer_one()
592 DIV_ROUND_UP(spicc->xfer->bits_per_word, 8); in meson_spicc_transfer_one()
594 if (xfer->len % spicc->bytes_per_word) in meson_spicc_transfer_one()
598 meson_spicc_setup_xfer(spicc, xfer); in meson_spicc_transfer_one()
600 meson_spicc_reset_fifo(spicc); in meson_spicc_transfer_one()
603 reinit_completion(&spicc->done); in meson_spicc_transfer_one()
622 ret = meson_spicc_dma_map(spicc, xfer); in meson_spicc_transfer_one()
624 meson_spicc_dma_unmap(spicc, xfer); in meson_spicc_transfer_one()
629 spicc->using_dma = true; in meson_spicc_transfer_one()
630 spicc->xfer_remain = DIV_ROUND_UP(xfer->len, spicc->bytes_per_word); in meson_spicc_transfer_one()
631 meson_spicc_setup_dma(spicc); in meson_spicc_transfer_one()
632 writel_relaxed(SPICC_TE_EN, spicc->base + SPICC_INTREG); in meson_spicc_transfer_one()
633 writel_bits_relaxed(SPICC_SMC, SPICC_SMC, spicc->base + SPICC_CONREG); in meson_spicc_transfer_one()
635 spicc->using_dma = false; in meson_spicc_transfer_one()
637 meson_spicc_setup_burst(spicc); in meson_spicc_transfer_one()
640 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_transfer_one()
643 writel_relaxed(SPICC_TC_EN, spicc->base + SPICC_INTREG); in meson_spicc_transfer_one()
646 if (!wait_for_completion_timeout(&spicc->done, msecs_to_jiffies(timeout))) in meson_spicc_transfer_one()
655 struct meson_spicc_device *spicc = spi_controller_get_devdata(host); in meson_spicc_prepare_message() local
657 u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK; in meson_spicc_prepare_message()
660 spicc->message = message; in meson_spicc_prepare_message()
674 if (!spicc->data->has_oen) { in meson_spicc_prepare_message()
676 if (spicc->pins_idle_high) in meson_spicc_prepare_message()
677 pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_high); in meson_spicc_prepare_message()
679 if (spicc->pins_idle_low) in meson_spicc_prepare_message()
680 pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_low); in meson_spicc_prepare_message()
707 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_prepare_message()
710 writel_relaxed(0, spicc->base + SPICC_PERIODREG); in meson_spicc_prepare_message()
714 spicc->base + SPICC_TESTREG); in meson_spicc_prepare_message()
721 struct meson_spicc_device *spicc = spi_controller_get_devdata(host); in meson_spicc_unprepare_transfer() local
722 u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK; in meson_spicc_unprepare_transfer()
725 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_unprepare_transfer()
727 device_reset_optional(&spicc->pdev->dev); in meson_spicc_unprepare_transfer()
730 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_unprepare_transfer()
732 if (!spicc->data->has_oen) in meson_spicc_unprepare_transfer()
733 pinctrl_select_default_state(&spicc->pdev->dev); in meson_spicc_unprepare_transfer()
791 struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); in meson_spicc_pow2_recalc_rate() local
793 if (!spicc->host->cur_msg) in meson_spicc_pow2_recalc_rate()
803 struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); in meson_spicc_pow2_determine_rate() local
805 if (!spicc->host->cur_msg) in meson_spicc_pow2_determine_rate()
815 struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); in meson_spicc_pow2_set_rate() local
817 if (!spicc->host->cur_msg) in meson_spicc_pow2_set_rate()
829 static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc) in meson_spicc_pow2_clk_init() argument
831 struct device *dev = &spicc->pdev->dev; in meson_spicc_pow2_clk_init()
852 if (spicc->data->has_pclk) { in meson_spicc_pow2_clk_init()
854 parent_data[0].hw = __clk_get_hw(spicc->pclk); in meson_spicc_pow2_clk_init()
857 parent_data[0].hw = __clk_get_hw(spicc->core); in meson_spicc_pow2_clk_init()
880 spicc->pow2_div.shift = 16; in meson_spicc_pow2_clk_init()
881 spicc->pow2_div.width = 3; in meson_spicc_pow2_clk_init()
882 spicc->pow2_div.flags = CLK_DIVIDER_POWER_OF_TWO; in meson_spicc_pow2_clk_init()
883 spicc->pow2_div.reg = spicc->base + SPICC_CONREG; in meson_spicc_pow2_clk_init()
884 spicc->pow2_div.hw.init = &init; in meson_spicc_pow2_clk_init()
886 spicc->clk = devm_clk_register(dev, &spicc->pow2_div.hw); in meson_spicc_pow2_clk_init()
887 if (WARN_ON(IS_ERR(spicc->clk))) in meson_spicc_pow2_clk_init()
888 return PTR_ERR(spicc->clk); in meson_spicc_pow2_clk_init()
893 static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc) in meson_spicc_enh_clk_init() argument
895 struct device *dev = &spicc->pdev->dev; in meson_spicc_enh_clk_init()
918 if (spicc->data->has_pclk) { in meson_spicc_enh_clk_init()
920 parent_data[0].hw = __clk_get_hw(spicc->pclk); in meson_spicc_enh_clk_init()
923 parent_data[0].hw = __clk_get_hw(spicc->core); in meson_spicc_enh_clk_init()
948 enh_div->reg = spicc->base + SPICC_ENH_CTL0; in meson_spicc_enh_clk_init()
962 parent_data[0].hw = &spicc->pow2_div.hw; in meson_spicc_enh_clk_init()
969 mux->reg = spicc->base + SPICC_ENH_CTL0; in meson_spicc_enh_clk_init()
972 spicc->clk = devm_clk_register(dev, &mux->hw); in meson_spicc_enh_clk_init()
973 if (WARN_ON(IS_ERR(spicc->clk))) in meson_spicc_enh_clk_init()
974 return PTR_ERR(spicc->clk); in meson_spicc_enh_clk_init()
982 struct meson_spicc_device *spicc; in meson_spicc_probe() local
985 host = spi_alloc_host(&pdev->dev, sizeof(*spicc)); in meson_spicc_probe()
990 spicc = spi_controller_get_devdata(host); in meson_spicc_probe()
991 spicc->host = host; in meson_spicc_probe()
993 spicc->data = of_device_get_match_data(&pdev->dev); in meson_spicc_probe()
994 if (!spicc->data) { in meson_spicc_probe()
1000 spicc->pdev = pdev; in meson_spicc_probe()
1001 platform_set_drvdata(pdev, spicc); in meson_spicc_probe()
1003 init_completion(&spicc->done); in meson_spicc_probe()
1005 spicc->base = devm_platform_ioremap_resource(pdev, 0); in meson_spicc_probe()
1006 if (IS_ERR(spicc->base)) { in meson_spicc_probe()
1008 ret = PTR_ERR(spicc->base); in meson_spicc_probe()
1014 spicc->base + SPICC_CONREG); in meson_spicc_probe()
1017 writel_relaxed(0, spicc->base + SPICC_INTREG); in meson_spicc_probe()
1026 0, NULL, spicc); in meson_spicc_probe()
1032 spicc->core = devm_clk_get_enabled(&pdev->dev, "core"); in meson_spicc_probe()
1033 if (IS_ERR(spicc->core)) { in meson_spicc_probe()
1035 ret = PTR_ERR(spicc->core); in meson_spicc_probe()
1039 if (spicc->data->has_pclk) { in meson_spicc_probe()
1040 spicc->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); in meson_spicc_probe()
1041 if (IS_ERR(spicc->pclk)) { in meson_spicc_probe()
1043 ret = PTR_ERR(spicc->pclk); in meson_spicc_probe()
1048 spicc->pinctrl = devm_pinctrl_get(&pdev->dev); in meson_spicc_probe()
1049 if (IS_ERR(spicc->pinctrl)) { in meson_spicc_probe()
1050 ret = PTR_ERR(spicc->pinctrl); in meson_spicc_probe()
1060 host->min_speed_hz = spicc->data->min_speed_hz; in meson_spicc_probe()
1061 host->max_speed_hz = spicc->data->max_speed_hz; in meson_spicc_probe()
1069 meson_spicc_oen_enable(spicc); in meson_spicc_probe()
1071 ret = meson_spicc_pow2_clk_init(spicc); in meson_spicc_probe()
1077 if (spicc->data->has_enhance_clk_div) { in meson_spicc_probe()
1078 ret = meson_spicc_enh_clk_init(spicc); in meson_spicc_probe()
1101 struct meson_spicc_device *spicc = platform_get_drvdata(pdev); in meson_spicc_remove() local
1104 writel(0, spicc->base + SPICC_CONREG); in meson_spicc_remove()
1106 spi_controller_put(spicc->host); in meson_spicc_remove()
1134 .compatible = "amlogic,meson-gx-spicc",
1138 .compatible = "amlogic,meson-axg-spicc",
1142 .compatible = "amlogic,meson-g12a-spicc",
1153 .name = "meson-spicc",