Lines Matching +full:lgm +full:- +full:clk

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2011-2015 Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
4 * Copyright (C) 2016 Hauke Mehrtens <hauke@hauke-m.de>
10 #include <linux/clk.h>
141 #define LTQ_SPI_RXCNT_TODO_M 0xFFFF /* Recevie to-do value */
168 struct clk *spi_clk;
169 struct clk *fpi_clk;
190 return __raw_readl(spi->regbase + reg); in lantiq_ssc_readl()
196 __raw_writel(val, spi->regbase + reg); in lantiq_ssc_writel()
202 u32 val = __raw_readl(spi->regbase + reg); in lantiq_ssc_maskl()
206 __raw_writel(val, spi->regbase + reg); in lantiq_ssc_maskl()
211 const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg; in tx_fifo_level()
214 return (fstat >> LTQ_SPI_FSTAT_TXFFL_S) & hwcfg->fifo_size_mask; in tx_fifo_level()
219 const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg; in rx_fifo_level()
222 return (fstat >> LTQ_SPI_FSTAT_RXFFL_S) & hwcfg->fifo_size_mask; in rx_fifo_level()
227 return spi->tx_fifo_size - tx_fifo_level(spi); in tx_fifo_free()
232 u32 val = spi->rx_fifo_size << LTQ_SPI_RXFCON_RXFITL_S; in rx_fifo_reset()
276 * baudrate = -------------- in hw_setup_speed_hz()
279 spi_clk = clk_get_rate(spi->fpi_clk) / 2; in hw_setup_speed_hz()
284 brt = spi_clk / max_speed_hz - 1; in hw_setup_speed_hz()
289 dev_dbg(spi->dev, "spi_clk %u, max_speed_hz %u, brt %u\n", in hw_setup_speed_hz()
300 /* CON.BM value = bits_per_word - 1 */ in hw_setup_bits_per_word()
301 bm = (bits_per_word - 1) << LTQ_SPI_CON_BM_S; in hw_setup_bits_per_word()
346 const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg; in lantiq_ssc_hw_init()
366 hw_setup_bits_per_word(spi, spi->bits_per_word); in lantiq_ssc_hw_init()
383 lantiq_ssc_writel(spi, hwcfg->irnen_t | hwcfg->irnen_r | in lantiq_ssc_hw_init()
389 struct spi_master *master = spidev->master; in lantiq_ssc_setup()
391 unsigned int cs = spidev->chip_select; in lantiq_ssc_setup()
395 if (spidev->cs_gpiod) in lantiq_ssc_setup()
398 dev_dbg(spi->dev, "using internal chipselect %u\n", cs); in lantiq_ssc_setup()
400 if (cs < spi->base_cs) { in lantiq_ssc_setup()
401 dev_err(spi->dev, in lantiq_ssc_setup()
402 "chipselect %i too small (min %i)\n", cs, spi->base_cs); in lantiq_ssc_setup()
403 return -EINVAL; in lantiq_ssc_setup()
407 gpocon = 1 << ((cs - spi->base_cs) + LTQ_SPI_GPOCON_ISCSBN_S); in lantiq_ssc_setup()
410 if (spidev->mode & SPI_CS_HIGH) in lantiq_ssc_setup()
411 gpocon |= 1 << (cs - spi->base_cs); in lantiq_ssc_setup()
424 hw_setup_clock_mode(spi, message->spi->mode); in lantiq_ssc_prepare_message()
433 unsigned int speed_hz = t->speed_hz; in hw_setup_transfer()
434 unsigned int bits_per_word = t->bits_per_word; in hw_setup_transfer()
437 if (bits_per_word != spi->bits_per_word || in hw_setup_transfer()
438 speed_hz != spi->speed_hz) { in hw_setup_transfer()
444 spi->speed_hz = speed_hz; in hw_setup_transfer()
445 spi->bits_per_word = bits_per_word; in hw_setup_transfer()
450 if (t->tx_buf) in hw_setup_transfer()
455 if (t->rx_buf) in hw_setup_transfer()
468 flush_workqueue(spi->wq); in lantiq_ssc_unprepare_message()
485 spi->fdx_tx_level = 0; in tx_fifo_write()
486 while (spi->tx_todo && tx_free) { in tx_fifo_write()
487 switch (spi->bits_per_word) { in tx_fifo_write()
489 tx8 = spi->tx; in tx_fifo_write()
491 spi->tx_todo--; in tx_fifo_write()
492 spi->tx++; in tx_fifo_write()
495 tx16 = (u16 *) spi->tx; in tx_fifo_write()
497 spi->tx_todo -= 2; in tx_fifo_write()
498 spi->tx += 2; in tx_fifo_write()
501 tx32 = (u32 *) spi->tx; in tx_fifo_write()
503 spi->tx_todo -= 4; in tx_fifo_write()
504 spi->tx += 4; in tx_fifo_write()
513 tx_free--; in tx_fifo_write()
514 spi->fdx_tx_level++; in tx_fifo_write()
530 while (rx_fill != spi->fdx_tx_level) in rx_fifo_read_full_duplex()
536 switch (spi->bits_per_word) { in rx_fifo_read_full_duplex()
538 rx8 = spi->rx; in rx_fifo_read_full_duplex()
540 spi->rx_todo--; in rx_fifo_read_full_duplex()
541 spi->rx++; in rx_fifo_read_full_duplex()
544 rx16 = (u16 *) spi->rx; in rx_fifo_read_full_duplex()
546 spi->rx_todo -= 2; in rx_fifo_read_full_duplex()
547 spi->rx += 2; in rx_fifo_read_full_duplex()
550 rx32 = (u32 *) spi->rx; in rx_fifo_read_full_duplex()
552 spi->rx_todo -= 4; in rx_fifo_read_full_duplex()
553 spi->rx += 4; in rx_fifo_read_full_duplex()
560 rx_fill--; in rx_fifo_read_full_duplex()
572 * In RX-only mode the bits per word value is ignored by HW. A value in rx_fifo_read_half_duplex()
579 if (spi->rx_todo < 4) { in rx_fifo_read_half_duplex()
584 shift = (rxbv - 1) * 8; in rx_fifo_read_half_duplex()
585 rx8 = spi->rx; in rx_fifo_read_half_duplex()
589 rxbv--; in rx_fifo_read_half_duplex()
590 shift -= 8; in rx_fifo_read_half_duplex()
591 spi->rx_todo--; in rx_fifo_read_half_duplex()
592 spi->rx++; in rx_fifo_read_half_duplex()
596 rx32 = (u32 *) spi->rx; in rx_fifo_read_half_duplex()
599 spi->rx_todo -= 4; in rx_fifo_read_half_duplex()
600 spi->rx += 4; in rx_fifo_read_half_duplex()
602 rx_fill--; in rx_fifo_read_half_duplex()
615 rxreq = spi->rx_todo; in rx_request()
616 rxreq_max = spi->rx_fifo_size * 4; in rx_request()
626 const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg; in lantiq_ssc_xmit_interrupt()
627 u32 val = lantiq_ssc_readl(spi, hwcfg->irncr); in lantiq_ssc_xmit_interrupt()
629 spin_lock(&spi->lock); in lantiq_ssc_xmit_interrupt()
630 if (hwcfg->irq_ack) in lantiq_ssc_xmit_interrupt()
631 lantiq_ssc_writel(spi, val, hwcfg->irncr); in lantiq_ssc_xmit_interrupt()
633 if (spi->tx) { in lantiq_ssc_xmit_interrupt()
634 if (spi->rx && spi->rx_todo) in lantiq_ssc_xmit_interrupt()
637 if (spi->tx_todo) in lantiq_ssc_xmit_interrupt()
641 } else if (spi->rx) { in lantiq_ssc_xmit_interrupt()
642 if (spi->rx_todo) { in lantiq_ssc_xmit_interrupt()
645 if (spi->rx_todo) in lantiq_ssc_xmit_interrupt()
654 spin_unlock(&spi->lock); in lantiq_ssc_xmit_interrupt()
658 queue_work(spi->wq, &spi->work); in lantiq_ssc_xmit_interrupt()
659 spin_unlock(&spi->lock); in lantiq_ssc_xmit_interrupt()
667 const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg; in lantiq_ssc_err_interrupt()
669 u32 val = lantiq_ssc_readl(spi, hwcfg->irncr); in lantiq_ssc_err_interrupt()
674 spin_lock(&spi->lock); in lantiq_ssc_err_interrupt()
675 if (hwcfg->irq_ack) in lantiq_ssc_err_interrupt()
676 lantiq_ssc_writel(spi, val, hwcfg->irncr); in lantiq_ssc_err_interrupt()
679 dev_err(spi->dev, "receive underflow error\n"); in lantiq_ssc_err_interrupt()
681 dev_err(spi->dev, "transmit underflow error\n"); in lantiq_ssc_err_interrupt()
683 dev_err(spi->dev, "abort error\n"); in lantiq_ssc_err_interrupt()
685 dev_err(spi->dev, "receive overflow error\n"); in lantiq_ssc_err_interrupt()
687 dev_err(spi->dev, "transmit overflow error\n"); in lantiq_ssc_err_interrupt()
689 dev_err(spi->dev, "mode error\n"); in lantiq_ssc_err_interrupt()
695 if (spi->master->cur_msg) in lantiq_ssc_err_interrupt()
696 spi->master->cur_msg->status = -EIO; in lantiq_ssc_err_interrupt()
697 queue_work(spi->wq, &spi->work); in lantiq_ssc_err_interrupt()
698 spin_unlock(&spi->lock); in lantiq_ssc_err_interrupt()
706 const struct lantiq_ssc_hwcfg *hwcfg = spi->hwcfg; in intel_lgm_ssc_isr()
707 u32 val = lantiq_ssc_readl(spi, hwcfg->irncr); in intel_lgm_ssc_isr()
715 if ((val & hwcfg->irnen_t) || (val & hwcfg->irnen_r)) in intel_lgm_ssc_isr()
726 spin_lock_irqsave(&spi->lock, flags); in transfer_start()
728 spi->tx = t->tx_buf; in transfer_start()
729 spi->rx = t->rx_buf; in transfer_start()
731 if (t->tx_buf) { in transfer_start()
732 spi->tx_todo = t->len; in transfer_start()
738 if (spi->rx) { in transfer_start()
739 spi->rx_todo = t->len; in transfer_start()
741 /* start shift clock in RX-only mode */ in transfer_start()
742 if (!spi->tx) in transfer_start()
746 spin_unlock_irqrestore(&spi->lock, flags); in transfer_start()
748 return t->len; in transfer_start()
766 do_div(timeout, spi->speed_hz); in lantiq_ssc_bussy_work()
774 spi_finalize_current_transfer(spi->master); in lantiq_ssc_bussy_work()
781 if (spi->master->cur_msg) in lantiq_ssc_bussy_work()
782 spi->master->cur_msg->status = -EIO; in lantiq_ssc_bussy_work()
783 spi_finalize_current_transfer(spi->master); in lantiq_ssc_bussy_work()
798 struct lantiq_ssc_spi *spi = spi_master_get_devdata(spidev->master); in lantiq_ssc_set_cs()
799 unsigned int cs = spidev->chip_select; in lantiq_ssc_set_cs()
802 if (!!(spidev->mode & SPI_CS_HIGH) == enable) in lantiq_ssc_set_cs()
803 fgpo = (1 << (cs - spi->base_cs)); in lantiq_ssc_set_cs()
805 fgpo = (1 << (cs - spi->base_cs + LTQ_SPI_FGPO_SETOUTN_S)); in lantiq_ssc_set_cs()
829 return devm_request_irq(&pdev->dev, irq, intel_lgm_ssc_isr, 0, "spi", spi); in intel_lgm_cfg_irq()
840 err = devm_request_irq(&pdev->dev, irq, lantiq_ssc_xmit_interrupt, in lantiq_cfg_irq()
849 err = devm_request_irq(&pdev->dev, irq, lantiq_ssc_xmit_interrupt, in lantiq_cfg_irq()
859 err = devm_request_irq(&pdev->dev, irq, lantiq_ssc_err_interrupt, in lantiq_cfg_irq()
895 { .compatible = "lantiq,ase-spi", .data = &lantiq_ssc_xway, },
896 { .compatible = "lantiq,falcon-spi", .data = &lantiq_ssc_xrx, },
897 { .compatible = "lantiq,xrx100-spi", .data = &lantiq_ssc_xrx, },
898 { .compatible = "intel,lgm-spi", .data = &intel_ssc_lgm, },
905 struct device *dev = &pdev->dev; in lantiq_ssc_probe()
917 return -ENOMEM; in lantiq_ssc_probe()
920 spi->master = master; in lantiq_ssc_probe()
921 spi->dev = dev; in lantiq_ssc_probe()
922 spi->hwcfg = hwcfg; in lantiq_ssc_probe()
924 spi->regbase = devm_platform_ioremap_resource(pdev, 0); in lantiq_ssc_probe()
925 if (IS_ERR(spi->regbase)) { in lantiq_ssc_probe()
926 err = PTR_ERR(spi->regbase); in lantiq_ssc_probe()
930 err = hwcfg->cfg_irq(pdev, spi); in lantiq_ssc_probe()
934 spi->spi_clk = devm_clk_get(dev, "gate"); in lantiq_ssc_probe()
935 if (IS_ERR(spi->spi_clk)) { in lantiq_ssc_probe()
936 err = PTR_ERR(spi->spi_clk); in lantiq_ssc_probe()
939 err = clk_prepare_enable(spi->spi_clk); in lantiq_ssc_probe()
945 * supports common clk. in lantiq_ssc_probe()
948 spi->fpi_clk = clk_get_fpi(); in lantiq_ssc_probe()
950 spi->fpi_clk = clk_get(dev, "freq"); in lantiq_ssc_probe()
952 if (IS_ERR(spi->fpi_clk)) { in lantiq_ssc_probe()
953 err = PTR_ERR(spi->fpi_clk); in lantiq_ssc_probe()
958 of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); in lantiq_ssc_probe()
960 spi->base_cs = 1; in lantiq_ssc_probe()
961 of_property_read_u32(pdev->dev.of_node, "base-cs", &spi->base_cs); in lantiq_ssc_probe()
963 spin_lock_init(&spi->lock); in lantiq_ssc_probe()
964 spi->bits_per_word = 8; in lantiq_ssc_probe()
965 spi->speed_hz = 0; in lantiq_ssc_probe()
967 master->dev.of_node = pdev->dev.of_node; in lantiq_ssc_probe()
968 master->num_chipselect = num_cs; in lantiq_ssc_probe()
969 master->use_gpio_descriptors = true; in lantiq_ssc_probe()
970 master->setup = lantiq_ssc_setup; in lantiq_ssc_probe()
971 master->set_cs = lantiq_ssc_set_cs; in lantiq_ssc_probe()
972 master->handle_err = lantiq_ssc_handle_err; in lantiq_ssc_probe()
973 master->prepare_message = lantiq_ssc_prepare_message; in lantiq_ssc_probe()
974 master->unprepare_message = lantiq_ssc_unprepare_message; in lantiq_ssc_probe()
975 master->transfer_one = lantiq_ssc_transfer_one; in lantiq_ssc_probe()
976 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH | in lantiq_ssc_probe()
978 master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) | in lantiq_ssc_probe()
981 spi->wq = alloc_ordered_workqueue(dev_name(dev), WQ_MEM_RECLAIM); in lantiq_ssc_probe()
982 if (!spi->wq) { in lantiq_ssc_probe()
983 err = -ENOMEM; in lantiq_ssc_probe()
986 INIT_WORK(&spi->work, lantiq_ssc_bussy_work); in lantiq_ssc_probe()
989 spi->tx_fifo_size = (id >> LTQ_SPI_ID_TXFS_S) & hwcfg->fifo_size_mask; in lantiq_ssc_probe()
990 spi->rx_fifo_size = (id >> LTQ_SPI_ID_RXFS_S) & hwcfg->fifo_size_mask; in lantiq_ssc_probe()
998 revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma); in lantiq_ssc_probe()
1009 destroy_workqueue(spi->wq); in lantiq_ssc_probe()
1011 clk_put(spi->fpi_clk); in lantiq_ssc_probe()
1013 clk_disable_unprepare(spi->spi_clk); in lantiq_ssc_probe()
1030 destroy_workqueue(spi->wq); in lantiq_ssc_remove()
1031 clk_disable_unprepare(spi->spi_clk); in lantiq_ssc_remove()
1032 clk_put(spi->fpi_clk); in lantiq_ssc_remove()
1041 .name = "spi-lantiq-ssc",
1049 MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
1051 MODULE_ALIAS("platform:spi-lantiq-ssc");