Lines Matching full:spicc

2  * Driver for Amlogic Meson SPI communication controller (SPICC)
26 * The Meson SPICC controller could support DMA based transfers, but is not
171 static void meson_spicc_oen_enable(struct meson_spicc_device *spicc) in meson_spicc_oen_enable() argument
175 if (!spicc->data->has_oen) in meson_spicc_oen_enable()
178 conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) | in meson_spicc_oen_enable()
181 writel_relaxed(conf, spicc->base + SPICC_ENH_CTL0); in meson_spicc_oen_enable()
184 static inline bool meson_spicc_txfull(struct meson_spicc_device *spicc) in meson_spicc_txfull() argument
187 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_txfull()
190 static inline bool meson_spicc_rxready(struct meson_spicc_device *spicc) in meson_spicc_rxready() argument
193 readl_relaxed(spicc->base + SPICC_STATREG)); in meson_spicc_rxready()
196 static inline u32 meson_spicc_pull_data(struct meson_spicc_device *spicc) in meson_spicc_pull_data() argument
198 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_pull_data()
204 byte = *spicc->tx_buf++; in meson_spicc_pull_data()
209 spicc->tx_remain--; in meson_spicc_pull_data()
213 static inline void meson_spicc_push_data(struct meson_spicc_device *spicc, in meson_spicc_push_data() argument
216 unsigned int bytes = spicc->bytes_per_word; in meson_spicc_push_data()
222 *spicc->rx_buf++ = byte; in meson_spicc_push_data()
226 spicc->rx_remain--; in meson_spicc_push_data()
229 static inline void meson_spicc_rx(struct meson_spicc_device *spicc) in meson_spicc_rx() argument
232 while (spicc->rx_remain && in meson_spicc_rx()
233 meson_spicc_rxready(spicc)) in meson_spicc_rx()
234 meson_spicc_push_data(spicc, in meson_spicc_rx()
235 readl_relaxed(spicc->base + SPICC_RXDATA)); in meson_spicc_rx()
238 static inline void meson_spicc_tx(struct meson_spicc_device *spicc) in meson_spicc_tx() argument
241 while (spicc->tx_remain && in meson_spicc_tx()
242 !meson_spicc_txfull(spicc)) in meson_spicc_tx()
243 writel_relaxed(meson_spicc_pull_data(spicc), in meson_spicc_tx()
244 spicc->base + SPICC_TXDATA); in meson_spicc_tx()
247 static inline void meson_spicc_setup_burst(struct meson_spicc_device *spicc) in meson_spicc_setup_burst() argument
251 spicc->xfer_remain / in meson_spicc_setup_burst()
252 spicc->bytes_per_word, in meson_spicc_setup_burst()
253 spicc->data->fifo_size); in meson_spicc_setup_burst()
255 spicc->tx_remain = burst_len; in meson_spicc_setup_burst()
256 spicc->rx_remain = burst_len; in meson_spicc_setup_burst()
257 spicc->xfer_remain -= burst_len * spicc->bytes_per_word; in meson_spicc_setup_burst()
263 spicc->base + SPICC_CONREG); in meson_spicc_setup_burst()
266 meson_spicc_tx(spicc); in meson_spicc_setup_burst()
271 struct meson_spicc_device *spicc = (void *) data; in meson_spicc_irq() local
273 writel_bits_relaxed(SPICC_TC, SPICC_TC, spicc->base + SPICC_STATREG); in meson_spicc_irq()
276 meson_spicc_rx(spicc); in meson_spicc_irq()
278 if (!spicc->xfer_remain) { in meson_spicc_irq()
280 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_irq()
282 spi_finalize_current_transfer(spicc->master); in meson_spicc_irq()
288 meson_spicc_setup_burst(spicc); in meson_spicc_irq()
291 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_irq()
296 static void meson_spicc_auto_io_delay(struct meson_spicc_device *spicc) in meson_spicc_auto_io_delay() argument
302 if (spicc->data->has_enhance_clk_div) { in meson_spicc_auto_io_delay()
304 readl_relaxed(spicc->base + SPICC_ENH_CTL0)); in meson_spicc_auto_io_delay()
309 readl_relaxed(spicc->base + SPICC_CONREG)); in meson_spicc_auto_io_delay()
316 hz = clk_get_rate(spicc->clk); in meson_spicc_auto_io_delay()
331 conf = readl_relaxed(spicc->base + SPICC_TESTREG); in meson_spicc_auto_io_delay()
336 writel_relaxed(conf, spicc->base + SPICC_TESTREG); in meson_spicc_auto_io_delay()
339 static void meson_spicc_setup_xfer(struct meson_spicc_device *spicc, in meson_spicc_setup_xfer() argument
345 conf = conf_orig = readl_relaxed(spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
350 (spicc->bytes_per_word << 3) - 1); in meson_spicc_setup_xfer()
354 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_setup_xfer()
356 clk_set_rate(spicc->clk, xfer->speed_hz); in meson_spicc_setup_xfer()
358 meson_spicc_auto_io_delay(spicc); in meson_spicc_setup_xfer()
360 writel_relaxed(0, spicc->base + SPICC_DMAREG); in meson_spicc_setup_xfer()
363 static void meson_spicc_reset_fifo(struct meson_spicc_device *spicc) in meson_spicc_reset_fifo() argument
365 if (spicc->data->has_oen) in meson_spicc_reset_fifo()
368 spicc->base + SPICC_ENH_CTL0); in meson_spicc_reset_fifo()
371 spicc->base + SPICC_TESTREG); in meson_spicc_reset_fifo()
373 while (meson_spicc_rxready(spicc)) in meson_spicc_reset_fifo()
374 readl_relaxed(spicc->base + SPICC_RXDATA); in meson_spicc_reset_fifo()
376 if (spicc->data->has_oen) in meson_spicc_reset_fifo()
378 spicc->base + SPICC_ENH_CTL0); in meson_spicc_reset_fifo()
385 struct meson_spicc_device *spicc = spi_master_get_devdata(master); in meson_spicc_transfer_one() local
388 spicc->xfer = xfer; in meson_spicc_transfer_one()
391 spicc->tx_buf = (u8 *)xfer->tx_buf; in meson_spicc_transfer_one()
392 spicc->rx_buf = (u8 *)xfer->rx_buf; in meson_spicc_transfer_one()
393 spicc->xfer_remain = xfer->len; in meson_spicc_transfer_one()
396 spicc->bytes_per_word = in meson_spicc_transfer_one()
397 DIV_ROUND_UP(spicc->xfer->bits_per_word, 8); in meson_spicc_transfer_one()
399 if (xfer->len % spicc->bytes_per_word) in meson_spicc_transfer_one()
403 meson_spicc_setup_xfer(spicc, xfer); in meson_spicc_transfer_one()
405 meson_spicc_reset_fifo(spicc); in meson_spicc_transfer_one()
408 meson_spicc_setup_burst(spicc); in meson_spicc_transfer_one()
411 writel_bits_relaxed(SPICC_XCH, SPICC_XCH, spicc->base + SPICC_CONREG); in meson_spicc_transfer_one()
414 writel_relaxed(SPICC_TC_EN, spicc->base + SPICC_INTREG); in meson_spicc_transfer_one()
422 struct meson_spicc_device *spicc = spi_master_get_devdata(master); in meson_spicc_prepare_message() local
427 spicc->message = message; in meson_spicc_prepare_message()
466 writel_relaxed(conf, spicc->base + SPICC_CONREG); in meson_spicc_prepare_message()
469 writel_relaxed(0, spicc->base + SPICC_PERIODREG); in meson_spicc_prepare_message()
471 writel_bits_relaxed(SPICC_LBC_W1, 0, spicc->base + SPICC_TESTREG); in meson_spicc_prepare_message()
478 struct meson_spicc_device *spicc = spi_master_get_devdata(master); in meson_spicc_unprepare_transfer() local
481 writel(0, spicc->base + SPICC_INTREG); in meson_spicc_unprepare_transfer()
483 device_reset_optional(&spicc->pdev->dev); in meson_spicc_unprepare_transfer()
523 static int meson_spicc_clk_init(struct meson_spicc_device *spicc) in meson_spicc_clk_init() argument
525 struct device *dev = &spicc->pdev->dev; in meson_spicc_clk_init()
549 if (spicc->data->has_pclk) in meson_spicc_clk_init()
550 parent_data[0].hw = __clk_get_hw(spicc->pclk); in meson_spicc_clk_init()
552 parent_data[0].hw = __clk_get_hw(spicc->core); in meson_spicc_clk_init()
577 pow2_div->reg = spicc->base + SPICC_CONREG; in meson_spicc_clk_init()
584 if (!spicc->data->has_enhance_clk_div) { in meson_spicc_clk_init()
585 spicc->clk = clk; in meson_spicc_clk_init()
599 if (spicc->data->has_pclk) in meson_spicc_clk_init()
600 parent_data[0].hw = __clk_get_hw(spicc->pclk); in meson_spicc_clk_init()
602 parent_data[0].hw = __clk_get_hw(spicc->core); in meson_spicc_clk_init()
626 enh_div->reg = spicc->base + SPICC_ENH_CTL0; in meson_spicc_clk_init()
647 mux->reg = spicc->base + SPICC_ENH_CTL0; in meson_spicc_clk_init()
650 spicc->clk = devm_clk_register(dev, &mux->hw); in meson_spicc_clk_init()
651 if (WARN_ON(IS_ERR(spicc->clk))) in meson_spicc_clk_init()
652 return PTR_ERR(spicc->clk); in meson_spicc_clk_init()
660 struct meson_spicc_device *spicc; in meson_spicc_probe() local
663 master = spi_alloc_master(&pdev->dev, sizeof(*spicc)); in meson_spicc_probe()
668 spicc = spi_master_get_devdata(master); in meson_spicc_probe()
669 spicc->master = master; in meson_spicc_probe()
671 spicc->data = of_device_get_match_data(&pdev->dev); in meson_spicc_probe()
672 if (!spicc->data) { in meson_spicc_probe()
678 spicc->pdev = pdev; in meson_spicc_probe()
679 platform_set_drvdata(pdev, spicc); in meson_spicc_probe()
681 spicc->base = devm_platform_ioremap_resource(pdev, 0); in meson_spicc_probe()
682 if (IS_ERR(spicc->base)) { in meson_spicc_probe()
684 ret = PTR_ERR(spicc->base); in meson_spicc_probe()
690 spicc->base + SPICC_CONREG); in meson_spicc_probe()
693 writel_relaxed(0, spicc->base + SPICC_INTREG); in meson_spicc_probe()
697 0, NULL, spicc); in meson_spicc_probe()
703 spicc->core = devm_clk_get(&pdev->dev, "core"); in meson_spicc_probe()
704 if (IS_ERR(spicc->core)) { in meson_spicc_probe()
706 ret = PTR_ERR(spicc->core); in meson_spicc_probe()
710 if (spicc->data->has_pclk) { in meson_spicc_probe()
711 spicc->pclk = devm_clk_get(&pdev->dev, "pclk"); in meson_spicc_probe()
712 if (IS_ERR(spicc->pclk)) { in meson_spicc_probe()
714 ret = PTR_ERR(spicc->pclk); in meson_spicc_probe()
719 ret = clk_prepare_enable(spicc->core); in meson_spicc_probe()
725 ret = clk_prepare_enable(spicc->pclk); in meson_spicc_probe()
741 master->min_speed_hz = spicc->data->min_speed_hz; in meson_spicc_probe()
742 master->max_speed_hz = spicc->data->max_speed_hz; in meson_spicc_probe()
750 meson_spicc_oen_enable(spicc); in meson_spicc_probe()
752 ret = meson_spicc_clk_init(spicc); in meson_spicc_probe()
767 clk_disable_unprepare(spicc->pclk); in meson_spicc_probe()
770 clk_disable_unprepare(spicc->core); in meson_spicc_probe()
780 struct meson_spicc_device *spicc = platform_get_drvdata(pdev); in meson_spicc_remove() local
783 writel(0, spicc->base + SPICC_CONREG); in meson_spicc_remove()
785 clk_disable_unprepare(spicc->core); in meson_spicc_remove()
786 clk_disable_unprepare(spicc->pclk); in meson_spicc_remove()
788 spi_master_put(spicc->master); in meson_spicc_remove()
818 .compatible = "amlogic,meson-gx-spicc",
822 .compatible = "amlogic,meson-axg-spicc",
826 .compatible = "amlogic,meson-g12a-spicc",
837 .name = "meson-spicc",