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_enable(struct mchp_corespi *spi) in mchp_corespi_enable() argument
124 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_enable()
128 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable()
131 static inline void mchp_corespi_disable(struct mchp_corespi *spi) in mchp_corespi_disable() argument
133 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable()
137 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable()
140 static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi) in mchp_corespi_read_fifo() argument
145 fifo_max = min(spi->rx_len, FIFO_DEPTH); in mchp_corespi_read_fifo()
147 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) { in mchp_corespi_read_fifo()
148 data = mchp_corespi_read(spi, REG_RX_DATA); in mchp_corespi_read_fifo()
150 if (spi->rx_buf) in mchp_corespi_read_fifo()
151 *spi->rx_buf++ = data; in mchp_corespi_read_fifo()
154 spi->rx_len -= i; in mchp_corespi_read_fifo()
155 spi->pending -= i; in mchp_corespi_read_fifo()
158 static void mchp_corespi_enable_ints(struct mchp_corespi *spi) in mchp_corespi_enable_ints() argument
162 mchp_corespi_disable(spi); in mchp_corespi_enable_ints()
164 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_enable_ints()
167 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable_ints()
170 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable_ints()
173 static void mchp_corespi_disable_ints(struct mchp_corespi *spi) in mchp_corespi_disable_ints() argument
177 mchp_corespi_disable(spi); in mchp_corespi_disable_ints()
179 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable_ints()
181 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable_ints()
184 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable_ints()
187 static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len) in mchp_corespi_set_xfer_size() argument
193 * Disable the SPI controller. Writes to transfer length have in mchp_corespi_set_xfer_size()
196 mchp_corespi_disable(spi); in mchp_corespi_set_xfer_size()
206 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_xfer_size()
209 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_xfer_size()
212 mchp_corespi_write(spi, REG_FRAMESUP, lenpart); in mchp_corespi_set_xfer_size()
215 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_xfer_size()
218 static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi) in mchp_corespi_write_fifo() argument
223 fifo_max = min(spi->tx_len, FIFO_DEPTH); in mchp_corespi_write_fifo()
224 mchp_corespi_set_xfer_size(spi, fifo_max); in mchp_corespi_write_fifo()
226 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) { in mchp_corespi_write_fifo()
227 byte = spi->tx_buf ? *spi->tx_buf++ : 0xaa; in mchp_corespi_write_fifo()
228 mchp_corespi_write(spi, REG_TX_DATA, byte); in mchp_corespi_write_fifo()
232 spi->tx_len -= i; in mchp_corespi_write_fifo()
233 spi->pending += i; in mchp_corespi_write_fifo()
236 static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt) in mchp_corespi_set_framesize() argument
241 * Disable the SPI controller. Writes to the frame size have in mchp_corespi_set_framesize()
244 mchp_corespi_disable(spi); in mchp_corespi_set_framesize()
246 mchp_corespi_write(spi, REG_FRAME_SIZE, bt); in mchp_corespi_set_framesize()
248 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_framesize()
250 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_framesize()
253 static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) in mchp_corespi_set_cs() argument
256 struct mchp_corespi *corespi = spi_master_get_devdata(spi->master); in mchp_corespi_set_cs()
259 reg &= ~BIT(spi->chip_select); in mchp_corespi_set_cs()
260 reg |= !disable << spi->chip_select; in mchp_corespi_set_cs()
265 static int mchp_corespi_setup(struct spi_device *spi) in mchp_corespi_setup() argument
267 struct mchp_corespi *corespi = spi_master_get_devdata(spi->master); in mchp_corespi_setup()
275 if (spi->mode & SPI_CS_HIGH) { in mchp_corespi_setup()
277 reg |= BIT(spi->chip_select); in mchp_corespi_setup()
283 static void mchp_corespi_init(struct spi_master *master, struct mchp_corespi *spi) in mchp_corespi_init() argument
286 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
293 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_init()
295 /* max. possible spi clock rate is the apb clock rate */ in mchp_corespi_init()
296 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_init()
307 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
310 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
312 mchp_corespi_enable_ints(spi); in mchp_corespi_init()
319 mchp_corespi_write(spi, REG_SLAVE_SELECT, SSELOUT | SSEL_DIRECT); in mchp_corespi_init()
321 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
326 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
329 static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi) in mchp_corespi_set_clk_gen() argument
333 mchp_corespi_disable(spi); in mchp_corespi_set_clk_gen()
335 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_clk_gen()
336 if (spi->clk_mode) in mchp_corespi_set_clk_gen()
341 mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen); in mchp_corespi_set_clk_gen()
342 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_clk_gen()
343 mchp_corespi_write(spi, REG_CONTROL, control | CONTROL_ENABLE); in mchp_corespi_set_clk_gen()
346 static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode) in mchp_corespi_set_mode() argument
366 * Disable the SPI controller. Writes to the frame size have in mchp_corespi_set_mode()
369 mchp_corespi_disable(spi); in mchp_corespi_set_mode()
371 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_mode()
375 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
378 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
384 struct mchp_corespi *spi = spi_master_get_devdata(master); in mchp_corespi_interrupt() local
385 u32 intfield = mchp_corespi_read(spi, REG_MIS) & 0xf; in mchp_corespi_interrupt()
393 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE); in mchp_corespi_interrupt()
395 if (spi->rx_len) in mchp_corespi_interrupt()
396 mchp_corespi_read_fifo(spi); in mchp_corespi_interrupt()
398 if (spi->tx_len) in mchp_corespi_interrupt()
399 mchp_corespi_write_fifo(spi); in mchp_corespi_interrupt()
401 if (!spi->rx_len) in mchp_corespi_interrupt()
406 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY); in mchp_corespi_interrupt()
409 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); in mchp_corespi_interrupt()
413 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
417 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN); in mchp_corespi_interrupt()
421 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
430 static int mchp_corespi_calculate_clkgen(struct mchp_corespi *spi, in mchp_corespi_calculate_clkgen() argument
435 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_calculate_clkgen()
458 spi->clk_mode = 0; in mchp_corespi_calculate_clkgen()
460 spi->clk_mode = 1; in mchp_corespi_calculate_clkgen()
463 spi->clk_gen = clk_gen; in mchp_corespi_calculate_clkgen()
471 struct mchp_corespi *spi = spi_master_get_devdata(master); in mchp_corespi_transfer_one() local
474 ret = mchp_corespi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz); in mchp_corespi_transfer_one()
480 mchp_corespi_set_clk_gen(spi); in mchp_corespi_transfer_one()
482 spi->tx_buf = xfer->tx_buf; in mchp_corespi_transfer_one()
483 spi->rx_buf = xfer->rx_buf; in mchp_corespi_transfer_one()
484 spi->tx_len = xfer->len; in mchp_corespi_transfer_one()
485 spi->rx_len = xfer->len; in mchp_corespi_transfer_one()
486 spi->pending = 0; in mchp_corespi_transfer_one()
488 mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH) in mchp_corespi_transfer_one()
489 ? FIFO_DEPTH : spi->tx_len); in mchp_corespi_transfer_one()
491 if (spi->tx_len) in mchp_corespi_transfer_one()
492 mchp_corespi_write_fifo(spi); in mchp_corespi_transfer_one()
499 struct spi_device *spi_dev = msg->spi; in mchp_corespi_prepare_message()
500 struct mchp_corespi *spi = spi_master_get_devdata(master); in mchp_corespi_prepare_message() local
502 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_prepare_message()
503 mchp_corespi_set_mode(spi, spi_dev->mode); in mchp_corespi_prepare_message()
511 struct mchp_corespi *spi; in mchp_corespi_probe() local
516 master = devm_spi_alloc_master(&pdev->dev, sizeof(*spi)); in mchp_corespi_probe()
519 "unable to allocate master for SPI controller\n"); in mchp_corespi_probe()
535 spi = spi_master_get_devdata(master); in mchp_corespi_probe()
537 spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in mchp_corespi_probe()
538 if (IS_ERR(spi->regs)) in mchp_corespi_probe()
539 return PTR_ERR(spi->regs); in mchp_corespi_probe()
541 spi->irq = platform_get_irq(pdev, 0); in mchp_corespi_probe()
542 if (spi->irq <= 0) in mchp_corespi_probe()
544 "invalid IRQ %d for SPI controller\n", in mchp_corespi_probe()
545 spi->irq); in mchp_corespi_probe()
547 ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt, in mchp_corespi_probe()
553 spi->clk = devm_clk_get(&pdev->dev, NULL); in mchp_corespi_probe()
554 if (IS_ERR(spi->clk)) in mchp_corespi_probe()
555 return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), in mchp_corespi_probe()
558 ret = clk_prepare_enable(spi->clk); in mchp_corespi_probe()
563 mchp_corespi_init(master, spi); in mchp_corespi_probe()
567 mchp_corespi_disable(spi); in mchp_corespi_probe()
568 clk_disable_unprepare(spi->clk); in mchp_corespi_probe()
570 "unable to register master for SPI controller\n"); in mchp_corespi_probe()
573 dev_info(&pdev->dev, "Registered SPI controller %d\n", master->bus_num); in mchp_corespi_probe()
581 struct mchp_corespi *spi = spi_master_get_devdata(master); in mchp_corespi_remove() local
583 mchp_corespi_disable_ints(spi); in mchp_corespi_remove()
584 clk_disable_unprepare(spi->clk); in mchp_corespi_remove()
585 mchp_corespi_disable(spi); in mchp_corespi_remove()
598 { .compatible = "microchip,mpfs-spi" },
614 MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver");