Lines Matching full:spi

3  * Microchip CoreSPI SPI controller driver
21 #include <linux/spi/spi.h>
107 u32 clk_gen; /* divider for spi output clock generated by the controller */
116 static inline u32 mchp_corespi_read(struct mchp_corespi *spi, unsigned int reg) in mchp_corespi_read() argument
118 return readl(spi->regs + reg); in mchp_corespi_read()
121 static inline void mchp_corespi_write(struct mchp_corespi *spi, unsigned int reg, u32 val) in mchp_corespi_write() argument
123 writel(val, spi->regs + reg); in mchp_corespi_write()
126 static inline void mchp_corespi_disable(struct mchp_corespi *spi) in mchp_corespi_disable() argument
128 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable()
132 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable()
135 static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi, int fifo_max) in mchp_corespi_read_fifo() argument
140 while (mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY) in mchp_corespi_read_fifo()
143 data = mchp_corespi_read(spi, REG_RX_DATA); in mchp_corespi_read_fifo()
145 spi->rx_len -= spi->n_bytes; in mchp_corespi_read_fifo()
147 if (!spi->rx_buf) in mchp_corespi_read_fifo()
150 if (spi->n_bytes == 4) in mchp_corespi_read_fifo()
151 *((u32 *)spi->rx_buf) = data; in mchp_corespi_read_fifo()
152 else if (spi->n_bytes == 2) in mchp_corespi_read_fifo()
153 *((u16 *)spi->rx_buf) = data; in mchp_corespi_read_fifo()
155 *spi->rx_buf = data; in mchp_corespi_read_fifo()
157 spi->rx_buf += spi->n_bytes; in mchp_corespi_read_fifo()
161 static void mchp_corespi_enable_ints(struct mchp_corespi *spi) in mchp_corespi_enable_ints() argument
163 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_enable_ints()
166 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable_ints()
169 static void mchp_corespi_disable_ints(struct mchp_corespi *spi) in mchp_corespi_disable_ints() argument
171 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable_ints()
174 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable_ints()
177 static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len) in mchp_corespi_set_xfer_size() argument
181 u32 frames = mchp_corespi_read(spi, REG_FRAMESUP); in mchp_corespi_set_xfer_size()
188 mchp_corespi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT); in mchp_corespi_set_xfer_size()
211 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_xfer_size()
214 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_xfer_size()
215 mchp_corespi_write(spi, REG_FRAMESUP, len); in mchp_corespi_set_xfer_size()
218 static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi, int fifo_max) in mchp_corespi_write_fifo() argument
222 mchp_corespi_set_xfer_size(spi, fifo_max); in mchp_corespi_write_fifo()
224 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) { in mchp_corespi_write_fifo()
227 if (spi->n_bytes == 4) in mchp_corespi_write_fifo()
228 word = spi->tx_buf ? *((u32 *)spi->tx_buf) : 0xaa; in mchp_corespi_write_fifo()
229 else if (spi->n_bytes == 2) in mchp_corespi_write_fifo()
230 word = spi->tx_buf ? *((u16 *)spi->tx_buf) : 0xaa; in mchp_corespi_write_fifo()
232 word = spi->tx_buf ? *spi->tx_buf : 0xaa; in mchp_corespi_write_fifo()
234 mchp_corespi_write(spi, REG_TX_DATA, word); in mchp_corespi_write_fifo()
235 if (spi->tx_buf) in mchp_corespi_write_fifo()
236 spi->tx_buf += spi->n_bytes; in mchp_corespi_write_fifo()
240 spi->tx_len -= i * spi->n_bytes; in mchp_corespi_write_fifo()
243 static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt) in mchp_corespi_set_framesize() argument
245 u32 frame_size = mchp_corespi_read(spi, REG_FRAME_SIZE); in mchp_corespi_set_framesize()
252 * Disable the SPI controller. Writes to the frame size have in mchp_corespi_set_framesize()
255 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_framesize()
257 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_framesize()
259 mchp_corespi_write(spi, REG_FRAME_SIZE, bt); in mchp_corespi_set_framesize()
262 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_framesize()
265 static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) in mchp_corespi_set_cs() argument
268 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); in mchp_corespi_set_cs()
271 reg &= ~BIT(spi_get_chipselect(spi, 0)); in mchp_corespi_set_cs()
272 reg |= !disable << spi_get_chipselect(spi, 0); in mchp_corespi_set_cs()
283 if (((spi->mode & SPI_CS_HIGH) == 0) == disable) in mchp_corespi_set_cs()
287 static int mchp_corespi_setup(struct spi_device *spi) in mchp_corespi_setup() argument
289 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); in mchp_corespi_setup()
292 if (spi_is_csgpiod(spi)) in mchp_corespi_setup()
300 if (spi->mode & SPI_CS_HIGH) { in mchp_corespi_setup()
302 reg |= BIT(spi_get_chipselect(spi, 0)); in mchp_corespi_setup()
309 static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *spi) in mchp_corespi_init() argument
312 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
315 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
331 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
333 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_init()
335 /* max. possible spi clock rate is the apb clock rate */ in mchp_corespi_init()
336 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_init()
339 mchp_corespi_enable_ints(spi); in mchp_corespi_init()
346 spi->pending_slave_select = SSELOUT | SSEL_DIRECT; in mchp_corespi_init()
347 mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); in mchp_corespi_init()
349 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
354 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
357 static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi) in mchp_corespi_set_clk_gen() argument
361 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_clk_gen()
362 if (spi->clk_mode) in mchp_corespi_set_clk_gen()
367 mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen); in mchp_corespi_set_clk_gen()
368 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_clk_gen()
371 static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode) in mchp_corespi_set_mode() argument
374 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_mode()
392 * Disable the SPI controller. Writes to the frame protocol have in mchp_corespi_set_mode()
397 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
402 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
405 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
411 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_interrupt() local
412 u32 intfield = mchp_corespi_read(spi, REG_MIS) & 0xf; in mchp_corespi_interrupt()
420 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); in mchp_corespi_interrupt()
424 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
428 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN); in mchp_corespi_interrupt()
432 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
441 static int mchp_corespi_calculate_clkgen(struct mchp_corespi *spi, in mchp_corespi_calculate_clkgen() argument
446 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_calculate_clkgen()
469 spi->clk_mode = 0; in mchp_corespi_calculate_clkgen()
471 spi->clk_mode = 1; in mchp_corespi_calculate_clkgen()
474 spi->clk_gen = clk_gen; in mchp_corespi_calculate_clkgen()
482 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_transfer_one() local
485 ret = mchp_corespi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz); in mchp_corespi_transfer_one()
491 mchp_corespi_set_clk_gen(spi); in mchp_corespi_transfer_one()
493 spi->tx_buf = xfer->tx_buf; in mchp_corespi_transfer_one()
494 spi->rx_buf = xfer->rx_buf; in mchp_corespi_transfer_one()
495 spi->tx_len = xfer->len; in mchp_corespi_transfer_one()
496 spi->rx_len = xfer->len; in mchp_corespi_transfer_one()
497 spi->n_bytes = roundup_pow_of_two(DIV_ROUND_UP(xfer->bits_per_word, BITS_PER_BYTE)); in mchp_corespi_transfer_one()
499 mchp_corespi_set_framesize(spi, xfer->bits_per_word); in mchp_corespi_transfer_one()
501 mchp_corespi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST); in mchp_corespi_transfer_one()
503 mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); in mchp_corespi_transfer_one()
505 while (spi->tx_len) { in mchp_corespi_transfer_one()
506 int fifo_max = DIV_ROUND_UP(min(spi->tx_len, FIFO_DEPTH), spi->n_bytes); in mchp_corespi_transfer_one()
508 mchp_corespi_write_fifo(spi, fifo_max); in mchp_corespi_transfer_one()
509 mchp_corespi_read_fifo(spi, fifo_max); in mchp_corespi_transfer_one()
519 struct spi_device *spi_dev = msg->spi; in mchp_corespi_prepare_message()
520 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_prepare_message() local
522 mchp_corespi_set_mode(spi, spi_dev->mode); in mchp_corespi_prepare_message()
530 struct mchp_corespi *spi; in mchp_corespi_probe() local
535 host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi)); in mchp_corespi_probe()
538 "unable to allocate host for SPI controller\n"); in mchp_corespi_probe()
555 spi = spi_controller_get_devdata(host); in mchp_corespi_probe()
557 spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in mchp_corespi_probe()
558 if (IS_ERR(spi->regs)) in mchp_corespi_probe()
559 return PTR_ERR(spi->regs); in mchp_corespi_probe()
561 spi->irq = platform_get_irq(pdev, 0); in mchp_corespi_probe()
562 if (spi->irq < 0) in mchp_corespi_probe()
563 return spi->irq; in mchp_corespi_probe()
565 ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt, in mchp_corespi_probe()
571 spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); in mchp_corespi_probe()
572 if (IS_ERR(spi->clk)) in mchp_corespi_probe()
573 return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), in mchp_corespi_probe()
576 mchp_corespi_init(host, spi); in mchp_corespi_probe()
580 mchp_corespi_disable(spi); in mchp_corespi_probe()
582 "unable to register host for SPI controller\n"); in mchp_corespi_probe()
585 dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num); in mchp_corespi_probe()
593 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_remove() local
595 mchp_corespi_disable_ints(spi); in mchp_corespi_remove()
596 mchp_corespi_disable(spi); in mchp_corespi_remove()
607 { .compatible = "microchip,mpfs-spi" },
623 MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver");