Lines Matching +full:spi +full:- +full:base

1 // SPDX-License-Identifier: GPL-2.0-only
3 * OpenCores tiny SPI master driver
19 #include <linux/spi/spi.h>
20 #include <linux/spi/spi_bitbang.h>
21 #include <linux/spi/spi_oc_tiny.h>
41 void __iomem *base; member
56 return spi_master_get_devdata(sdev->master); in tiny_spi_to_hw()
59 static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz) in tiny_spi_baud() argument
61 struct tiny_spi *hw = tiny_spi_to_hw(spi); in tiny_spi_baud()
63 return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1; in tiny_spi_baud()
66 static int tiny_spi_setup_transfer(struct spi_device *spi, in tiny_spi_setup_transfer() argument
69 struct tiny_spi *hw = tiny_spi_to_hw(spi); in tiny_spi_setup_transfer()
70 unsigned int baud = hw->baud; in tiny_spi_setup_transfer()
73 if (t->speed_hz && t->speed_hz != hw->speed_hz) in tiny_spi_setup_transfer()
74 baud = tiny_spi_baud(spi, t->speed_hz); in tiny_spi_setup_transfer()
76 writel(baud, hw->base + TINY_SPI_BAUD); in tiny_spi_setup_transfer()
77 writel(hw->mode, hw->base + TINY_SPI_CONTROL); in tiny_spi_setup_transfer()
81 static int tiny_spi_setup(struct spi_device *spi) in tiny_spi_setup() argument
83 struct tiny_spi *hw = tiny_spi_to_hw(spi); in tiny_spi_setup()
85 if (spi->max_speed_hz != hw->speed_hz) { in tiny_spi_setup()
86 hw->speed_hz = spi->max_speed_hz; in tiny_spi_setup()
87 hw->baud = tiny_spi_baud(spi, hw->speed_hz); in tiny_spi_setup()
89 hw->mode = spi->mode & SPI_MODE_X_MASK; in tiny_spi_setup()
95 while (!(readb(hw->base + TINY_SPI_STATUS) & in tiny_spi_wait_txr()
102 while (!(readb(hw->base + TINY_SPI_STATUS) & in tiny_spi_wait_txe()
107 static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) in tiny_spi_txrx_bufs() argument
109 struct tiny_spi *hw = tiny_spi_to_hw(spi); in tiny_spi_txrx_bufs()
110 const u8 *txp = t->tx_buf; in tiny_spi_txrx_bufs()
111 u8 *rxp = t->rx_buf; in tiny_spi_txrx_bufs()
114 if (hw->irq >= 0) { in tiny_spi_txrx_bufs()
116 hw->len = t->len; in tiny_spi_txrx_bufs()
117 hw->txp = t->tx_buf; in tiny_spi_txrx_bufs()
118 hw->rxp = t->rx_buf; in tiny_spi_txrx_bufs()
119 hw->txc = 0; in tiny_spi_txrx_bufs()
120 hw->rxc = 0; in tiny_spi_txrx_bufs()
123 if (t->len > 1) { in tiny_spi_txrx_bufs()
124 writeb(hw->txp ? *hw->txp++ : 0, in tiny_spi_txrx_bufs()
125 hw->base + TINY_SPI_TXDATA); in tiny_spi_txrx_bufs()
126 hw->txc++; in tiny_spi_txrx_bufs()
127 writeb(hw->txp ? *hw->txp++ : 0, in tiny_spi_txrx_bufs()
128 hw->base + TINY_SPI_TXDATA); in tiny_spi_txrx_bufs()
129 hw->txc++; in tiny_spi_txrx_bufs()
130 writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS); in tiny_spi_txrx_bufs()
132 writeb(hw->txp ? *hw->txp++ : 0, in tiny_spi_txrx_bufs()
133 hw->base + TINY_SPI_TXDATA); in tiny_spi_txrx_bufs()
134 hw->txc++; in tiny_spi_txrx_bufs()
135 writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS); in tiny_spi_txrx_bufs()
138 wait_for_completion(&hw->done); in tiny_spi_txrx_bufs()
141 writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA); in tiny_spi_txrx_bufs()
142 for (i = 1; i < t->len; i++) { in tiny_spi_txrx_bufs()
143 writeb(txp ? *txp++ : 0, hw->base + TINY_SPI_TXDATA); in tiny_spi_txrx_bufs()
145 if (rxp || (i != t->len - 1)) in tiny_spi_txrx_bufs()
148 *rxp++ = readb(hw->base + TINY_SPI_TXDATA); in tiny_spi_txrx_bufs()
152 *rxp++ = readb(hw->base + TINY_SPI_RXDATA); in tiny_spi_txrx_bufs()
155 return t->len; in tiny_spi_txrx_bufs()
162 writeb(0, hw->base + TINY_SPI_STATUS); in tiny_spi_irq()
163 if (hw->rxc + 1 == hw->len) { in tiny_spi_irq()
164 if (hw->rxp) in tiny_spi_irq()
165 *hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA); in tiny_spi_irq()
166 hw->rxc++; in tiny_spi_irq()
167 complete(&hw->done); in tiny_spi_irq()
169 if (hw->rxp) in tiny_spi_irq()
170 *hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA); in tiny_spi_irq()
171 hw->rxc++; in tiny_spi_irq()
172 if (hw->txc < hw->len) { in tiny_spi_irq()
173 writeb(hw->txp ? *hw->txp++ : 0, in tiny_spi_irq()
174 hw->base + TINY_SPI_TXDATA); in tiny_spi_irq()
175 hw->txc++; in tiny_spi_irq()
177 hw->base + TINY_SPI_STATUS); in tiny_spi_irq()
180 hw->base + TINY_SPI_STATUS); in tiny_spi_irq()
192 struct device_node *np = pdev->dev.of_node; in tiny_spi_of_probe()
197 hw->bitbang.master->dev.of_node = pdev->dev.of_node; in tiny_spi_of_probe()
198 if (!of_property_read_u32(np, "clock-frequency", &val)) in tiny_spi_of_probe()
199 hw->freq = val; in tiny_spi_of_probe()
200 if (!of_property_read_u32(np, "baud-width", &val)) in tiny_spi_of_probe()
201 hw->baudwidth = val; in tiny_spi_of_probe()
213 struct tiny_spi_platform_data *platp = dev_get_platdata(&pdev->dev); in tiny_spi_probe()
216 int err = -ENODEV; in tiny_spi_probe()
218 master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi)); in tiny_spi_probe()
223 master->bus_num = pdev->id; in tiny_spi_probe()
224 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; in tiny_spi_probe()
225 master->setup = tiny_spi_setup; in tiny_spi_probe()
226 master->use_gpio_descriptors = true; in tiny_spi_probe()
232 hw->bitbang.master = master; in tiny_spi_probe()
233 hw->bitbang.setup_transfer = tiny_spi_setup_transfer; in tiny_spi_probe()
234 hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs; in tiny_spi_probe()
237 hw->base = devm_platform_ioremap_resource(pdev, 0); in tiny_spi_probe()
238 if (IS_ERR(hw->base)) { in tiny_spi_probe()
239 err = PTR_ERR(hw->base); in tiny_spi_probe()
243 hw->irq = platform_get_irq(pdev, 0); in tiny_spi_probe()
244 if (hw->irq >= 0) { in tiny_spi_probe()
245 init_completion(&hw->done); in tiny_spi_probe()
246 err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0, in tiny_spi_probe()
247 pdev->name, hw); in tiny_spi_probe()
253 hw->freq = platp->freq; in tiny_spi_probe()
254 hw->baudwidth = platp->baudwidth; in tiny_spi_probe()
261 /* register our spi controller */ in tiny_spi_probe()
262 err = spi_bitbang_start(&hw->bitbang); in tiny_spi_probe()
265 dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq); in tiny_spi_probe()
277 struct spi_master *master = hw->bitbang.master; in tiny_spi_remove()
279 spi_bitbang_stop(&hw->bitbang); in tiny_spi_remove()
285 { .compatible = "opencores,tiny-spi-rtlsvn2", },
302 MODULE_DESCRIPTION("OpenCores tiny SPI driver");