Lines Matching +full:mpfs +full:- +full:spi

1 // SPDX-License-Identifier: (GPL-2.0)
3 * Microchip CoreSPI SPI controller driver
5 * Copyright (c) 2018-2022 Microchip Technology Inc. and its subsidiaries
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()
297 master->max_speed_hz = clk_hz; 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()
411 dev_err(&master->dev, 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()
419 dev_err(&master->dev, 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()
437 return -EINVAL; in mchp_corespi_calculate_clkgen()
448 * clk_gen is the register name for the clock divider on MPFS. in mchp_corespi_calculate_clkgen()
450 clk_gen = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1; in mchp_corespi_calculate_clkgen()
453 clk_gen = fls(clk_gen) - 1; in mchp_corespi_calculate_clkgen()
456 return -EINVAL; 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()
476 dev_err(&master->dev, "failed to set clk_gen for target %u Hz\n", 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()
518 return dev_err_probe(&pdev->dev, -ENOMEM, in mchp_corespi_probe()
519 "unable to allocate master for SPI controller\n"); in mchp_corespi_probe()
523 if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs)) in mchp_corespi_probe()
526 master->num_chipselect = num_cs; in mchp_corespi_probe()
527 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; in mchp_corespi_probe()
528 master->setup = mchp_corespi_setup; in mchp_corespi_probe()
529 master->bits_per_word_mask = SPI_BPW_MASK(8); in mchp_corespi_probe()
530 master->transfer_one = mchp_corespi_transfer_one; in mchp_corespi_probe()
531 master->prepare_message = mchp_corespi_prepare_message; in mchp_corespi_probe()
532 master->set_cs = mchp_corespi_set_cs; in mchp_corespi_probe()
533 master->dev.of_node = pdev->dev.of_node; 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()
543 return dev_err_probe(&pdev->dev, -ENXIO, 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()
548 IRQF_SHARED, dev_name(&pdev->dev), master); in mchp_corespi_probe()
550 return dev_err_probe(&pdev->dev, ret, 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()
560 return dev_err_probe(&pdev->dev, ret, in mchp_corespi_probe()
563 mchp_corespi_init(master, spi); in mchp_corespi_probe()
565 ret = devm_spi_register_master(&pdev->dev, master); in mchp_corespi_probe()
567 mchp_corespi_disable(spi); in mchp_corespi_probe()
568 clk_disable_unprepare(spi->clk); in mchp_corespi_probe()
569 return dev_err_probe(&pdev->dev, ret, 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" },
607 .name = "microchip-corespi",
614 MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver");