Lines Matching full:spi
3 * Microchip CoreSPI SPI controller driver
21 #include <linux/spi/spi.h>
104 u32 clk_gen; /* divider for spi output clock generated by the controller */
112 static inline u32 mchp_corespi_read(struct mchp_corespi *spi, unsigned int reg) in mchp_corespi_read() argument
114 return readl(spi->regs + reg); in mchp_corespi_read()
117 static inline void mchp_corespi_write(struct mchp_corespi *spi, unsigned int reg, u32 val) in mchp_corespi_write() argument
119 writel(val, spi->regs + reg); in mchp_corespi_write()
122 static inline void mchp_corespi_disable(struct mchp_corespi *spi) in mchp_corespi_disable() argument
124 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable()
128 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable()
131 static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi) in mchp_corespi_read_fifo() argument
136 fifo_max = min(spi->rx_len, FIFO_DEPTH); in mchp_corespi_read_fifo()
138 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) { in mchp_corespi_read_fifo()
139 data = mchp_corespi_read(spi, REG_RX_DATA); in mchp_corespi_read_fifo()
141 if (spi->rx_buf) in mchp_corespi_read_fifo()
142 *spi->rx_buf++ = data; in mchp_corespi_read_fifo()
145 spi->rx_len -= i; in mchp_corespi_read_fifo()
146 spi->pending -= i; in mchp_corespi_read_fifo()
149 static void mchp_corespi_enable_ints(struct mchp_corespi *spi) in mchp_corespi_enable_ints() argument
153 mchp_corespi_disable(spi); in mchp_corespi_enable_ints()
155 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_enable_ints()
158 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable_ints()
161 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable_ints()
164 static void mchp_corespi_disable_ints(struct mchp_corespi *spi) in mchp_corespi_disable_ints() argument
168 mchp_corespi_disable(spi); in mchp_corespi_disable_ints()
170 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable_ints()
172 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable_ints()
175 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable_ints()
178 static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len) in mchp_corespi_set_xfer_size() argument
184 * Disable the SPI controller. Writes to transfer length have in mchp_corespi_set_xfer_size()
187 mchp_corespi_disable(spi); in mchp_corespi_set_xfer_size()
197 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_xfer_size()
200 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_xfer_size()
203 mchp_corespi_write(spi, REG_FRAMESUP, lenpart); in mchp_corespi_set_xfer_size()
206 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_xfer_size()
209 static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi) in mchp_corespi_write_fifo() argument
214 fifo_max = min(spi->tx_len, FIFO_DEPTH); in mchp_corespi_write_fifo()
215 mchp_corespi_set_xfer_size(spi, fifo_max); in mchp_corespi_write_fifo()
217 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) { in mchp_corespi_write_fifo()
218 byte = spi->tx_buf ? *spi->tx_buf++ : 0xaa; in mchp_corespi_write_fifo()
219 mchp_corespi_write(spi, REG_TX_DATA, byte); in mchp_corespi_write_fifo()
223 spi->tx_len -= i; in mchp_corespi_write_fifo()
224 spi->pending += i; in mchp_corespi_write_fifo()
227 static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt) in mchp_corespi_set_framesize() argument
232 * Disable the SPI controller. Writes to the frame size have in mchp_corespi_set_framesize()
235 mchp_corespi_disable(spi); in mchp_corespi_set_framesize()
237 mchp_corespi_write(spi, REG_FRAME_SIZE, bt); in mchp_corespi_set_framesize()
239 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_framesize()
241 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_framesize()
244 static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) in mchp_corespi_set_cs() argument
247 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); in mchp_corespi_set_cs()
250 reg &= ~BIT(spi_get_chipselect(spi, 0)); in mchp_corespi_set_cs()
251 reg |= !disable << spi_get_chipselect(spi, 0); in mchp_corespi_set_cs()
256 static int mchp_corespi_setup(struct spi_device *spi) in mchp_corespi_setup() argument
258 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); in mchp_corespi_setup()
266 if (spi->mode & SPI_CS_HIGH) { in mchp_corespi_setup()
268 reg |= BIT(spi_get_chipselect(spi, 0)); in mchp_corespi_setup()
274 static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *spi) in mchp_corespi_init() argument
277 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
284 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_init()
286 /* max. possible spi clock rate is the apb clock rate */ in mchp_corespi_init()
287 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_init()
298 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
301 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
303 mchp_corespi_enable_ints(spi); in mchp_corespi_init()
310 mchp_corespi_write(spi, REG_SLAVE_SELECT, SSELOUT | SSEL_DIRECT); in mchp_corespi_init()
312 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
317 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
320 static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi) in mchp_corespi_set_clk_gen() argument
324 mchp_corespi_disable(spi); in mchp_corespi_set_clk_gen()
326 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_clk_gen()
327 if (spi->clk_mode) in mchp_corespi_set_clk_gen()
332 mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen); in mchp_corespi_set_clk_gen()
333 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_clk_gen()
334 mchp_corespi_write(spi, REG_CONTROL, control | CONTROL_ENABLE); in mchp_corespi_set_clk_gen()
337 static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode) in mchp_corespi_set_mode() argument
357 * Disable the SPI controller. Writes to the frame size have in mchp_corespi_set_mode()
360 mchp_corespi_disable(spi); in mchp_corespi_set_mode()
362 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_mode()
366 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
369 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
375 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_interrupt() local
376 u32 intfield = mchp_corespi_read(spi, REG_MIS) & 0xf; in mchp_corespi_interrupt()
384 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE); in mchp_corespi_interrupt()
386 if (spi->rx_len) in mchp_corespi_interrupt()
387 mchp_corespi_read_fifo(spi); in mchp_corespi_interrupt()
389 if (spi->tx_len) in mchp_corespi_interrupt()
390 mchp_corespi_write_fifo(spi); in mchp_corespi_interrupt()
392 if (!spi->rx_len) in mchp_corespi_interrupt()
397 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY); in mchp_corespi_interrupt()
400 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); in mchp_corespi_interrupt()
404 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
408 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN); in mchp_corespi_interrupt()
412 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
421 static int mchp_corespi_calculate_clkgen(struct mchp_corespi *spi, in mchp_corespi_calculate_clkgen() argument
426 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_calculate_clkgen()
449 spi->clk_mode = 0; in mchp_corespi_calculate_clkgen()
451 spi->clk_mode = 1; in mchp_corespi_calculate_clkgen()
454 spi->clk_gen = clk_gen; in mchp_corespi_calculate_clkgen()
462 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_transfer_one() local
465 ret = mchp_corespi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz); in mchp_corespi_transfer_one()
471 mchp_corespi_set_clk_gen(spi); in mchp_corespi_transfer_one()
473 spi->tx_buf = xfer->tx_buf; in mchp_corespi_transfer_one()
474 spi->rx_buf = xfer->rx_buf; in mchp_corespi_transfer_one()
475 spi->tx_len = xfer->len; in mchp_corespi_transfer_one()
476 spi->rx_len = xfer->len; in mchp_corespi_transfer_one()
477 spi->pending = 0; in mchp_corespi_transfer_one()
479 mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH) in mchp_corespi_transfer_one()
480 ? FIFO_DEPTH : spi->tx_len); in mchp_corespi_transfer_one()
482 if (spi->tx_len) in mchp_corespi_transfer_one()
483 mchp_corespi_write_fifo(spi); in mchp_corespi_transfer_one()
490 struct spi_device *spi_dev = msg->spi; in mchp_corespi_prepare_message()
491 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_prepare_message() local
493 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_prepare_message()
494 mchp_corespi_set_mode(spi, spi_dev->mode); in mchp_corespi_prepare_message()
502 struct mchp_corespi *spi; in mchp_corespi_probe() local
507 host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi)); in mchp_corespi_probe()
510 "unable to allocate host for SPI controller\n"); in mchp_corespi_probe()
526 spi = spi_controller_get_devdata(host); in mchp_corespi_probe()
528 spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in mchp_corespi_probe()
529 if (IS_ERR(spi->regs)) in mchp_corespi_probe()
530 return PTR_ERR(spi->regs); in mchp_corespi_probe()
532 spi->irq = platform_get_irq(pdev, 0); in mchp_corespi_probe()
533 if (spi->irq < 0) in mchp_corespi_probe()
534 return spi->irq; in mchp_corespi_probe()
536 ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt, in mchp_corespi_probe()
542 spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); in mchp_corespi_probe()
543 if (IS_ERR(spi->clk)) in mchp_corespi_probe()
544 return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), in mchp_corespi_probe()
547 mchp_corespi_init(host, spi); in mchp_corespi_probe()
551 mchp_corespi_disable(spi); in mchp_corespi_probe()
553 "unable to register host for SPI controller\n"); in mchp_corespi_probe()
556 dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num); in mchp_corespi_probe()
564 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_remove() local
566 mchp_corespi_disable_ints(spi); in mchp_corespi_remove()
567 mchp_corespi_disable(spi); in mchp_corespi_remove()
578 { .compatible = "microchip,mpfs-spi" },
594 MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver");