Lines Matching +full:spi +full:- +full:clk

1 // SPDX-License-Identifier: (GPL-2.0)
3 * Microchip CoreSPI SPI controller driver
5 * Copyright (c) 2018-2022 Microchip Technology Inc. and its subsidiaries
12 #include <linux/clk.h>
21 #include <linux/spi/spi.h>
105 struct clk *clk; member
108 u32 clk_gen; /* divider for spi output clock generated by the controller */
117 static inline u32 mchp_corespi_read(struct mchp_corespi *spi, unsigned int reg) in mchp_corespi_read() argument
119 return readl(spi->regs + reg); in mchp_corespi_read()
122 static inline void mchp_corespi_write(struct mchp_corespi *spi, unsigned int reg, u32 val) in mchp_corespi_write() argument
124 writel(val, spi->regs + reg); in mchp_corespi_write()
127 static inline void mchp_corespi_disable(struct mchp_corespi *spi) in mchp_corespi_disable() argument
129 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable()
133 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable()
136 static inline void mchp_corespi_read_fifo(struct mchp_corespi *spi) in mchp_corespi_read_fifo() argument
141 fifo_max = min(spi->rx_len, FIFO_DEPTH); in mchp_corespi_read_fifo()
143 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_RXFIFO_EMPTY)) { in mchp_corespi_read_fifo()
144 data = mchp_corespi_read(spi, REG_RX_DATA); in mchp_corespi_read_fifo()
146 if (spi->rx_buf) in mchp_corespi_read_fifo()
147 *spi->rx_buf++ = data; in mchp_corespi_read_fifo()
150 spi->rx_len -= i; in mchp_corespi_read_fifo()
151 spi->pending -= i; in mchp_corespi_read_fifo()
154 static void mchp_corespi_enable_ints(struct mchp_corespi *spi) in mchp_corespi_enable_ints() argument
156 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_enable_ints()
159 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_enable_ints()
162 static void mchp_corespi_disable_ints(struct mchp_corespi *spi) in mchp_corespi_disable_ints() argument
164 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_disable_ints()
167 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_disable_ints()
170 static inline void mchp_corespi_set_xfer_size(struct mchp_corespi *spi, int len) in mchp_corespi_set_xfer_size() argument
174 u32 frames = mchp_corespi_read(spi, REG_FRAMESUP); in mchp_corespi_set_xfer_size()
181 mchp_corespi_write(spi, REG_COMMAND, COMMAND_CLRFRAMECNT); in mchp_corespi_set_xfer_size()
197 * would actually write zeros into the lower 16 bits on an mpfs250t-es, in mchp_corespi_set_xfer_size()
198 * despite documentation stating these bits were read-only. in mchp_corespi_set_xfer_size()
200 * on an mpfs250t-es and will be a NOP for the lower 16 bits on hardware in mchp_corespi_set_xfer_size()
204 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_xfer_size()
207 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_xfer_size()
208 mchp_corespi_write(spi, REG_FRAMESUP, len); in mchp_corespi_set_xfer_size()
211 static inline void mchp_corespi_write_fifo(struct mchp_corespi *spi) in mchp_corespi_write_fifo() argument
216 fifo_max = min(spi->tx_len, FIFO_DEPTH); in mchp_corespi_write_fifo()
217 mchp_corespi_set_xfer_size(spi, fifo_max); in mchp_corespi_write_fifo()
219 while ((i < fifo_max) && !(mchp_corespi_read(spi, REG_STATUS) & STATUS_TXFIFO_FULL)) { in mchp_corespi_write_fifo()
220 byte = spi->tx_buf ? *spi->tx_buf++ : 0xaa; in mchp_corespi_write_fifo()
221 mchp_corespi_write(spi, REG_TX_DATA, byte); in mchp_corespi_write_fifo()
225 spi->tx_len -= i; in mchp_corespi_write_fifo()
226 spi->pending += i; in mchp_corespi_write_fifo()
229 static inline void mchp_corespi_set_framesize(struct mchp_corespi *spi, int bt) in mchp_corespi_set_framesize() argument
231 u32 frame_size = mchp_corespi_read(spi, REG_FRAME_SIZE); in mchp_corespi_set_framesize()
238 * Disable the SPI controller. Writes to the frame size have in mchp_corespi_set_framesize()
241 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_framesize()
243 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_framesize()
245 mchp_corespi_write(spi, REG_FRAME_SIZE, bt); in mchp_corespi_set_framesize()
248 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_framesize()
251 static void mchp_corespi_set_cs(struct spi_device *spi, bool disable) in mchp_corespi_set_cs() argument
254 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); in mchp_corespi_set_cs()
257 reg &= ~BIT(spi_get_chipselect(spi, 0)); in mchp_corespi_set_cs()
258 reg |= !disable << spi_get_chipselect(spi, 0); in mchp_corespi_set_cs()
259 corespi->pending_slave_select = reg; in mchp_corespi_set_cs()
269 if (((spi->mode & SPI_CS_HIGH) == 0) == disable) in mchp_corespi_set_cs()
273 static int mchp_corespi_setup(struct spi_device *spi) in mchp_corespi_setup() argument
275 struct mchp_corespi *corespi = spi_controller_get_devdata(spi->controller); in mchp_corespi_setup()
283 if (spi->mode & SPI_CS_HIGH) { in mchp_corespi_setup()
285 reg |= BIT(spi_get_chipselect(spi, 0)); in mchp_corespi_setup()
286 corespi->pending_slave_select = reg; in mchp_corespi_setup()
292 static void mchp_corespi_init(struct spi_controller *host, struct mchp_corespi *spi) in mchp_corespi_init() argument
295 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
298 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
314 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
316 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_init()
318 /* max. possible spi clock rate is the apb clock rate */ in mchp_corespi_init()
319 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_init()
320 host->max_speed_hz = clk_hz; in mchp_corespi_init()
322 mchp_corespi_enable_ints(spi); in mchp_corespi_init()
329 spi->pending_slave_select = SSELOUT | SSEL_DIRECT; in mchp_corespi_init()
330 mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); in mchp_corespi_init()
332 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_init()
337 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_init()
340 static inline void mchp_corespi_set_clk_gen(struct mchp_corespi *spi) in mchp_corespi_set_clk_gen() argument
344 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_clk_gen()
345 if (spi->clk_mode) in mchp_corespi_set_clk_gen()
350 mchp_corespi_write(spi, REG_CLK_GEN, spi->clk_gen); in mchp_corespi_set_clk_gen()
351 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_clk_gen()
354 static inline void mchp_corespi_set_mode(struct mchp_corespi *spi, unsigned int mode) in mchp_corespi_set_mode() argument
357 u32 control = mchp_corespi_read(spi, REG_CONTROL); in mchp_corespi_set_mode()
375 * Disable the SPI controller. Writes to the frame protocol have in mchp_corespi_set_mode()
380 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
385 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
388 mchp_corespi_write(spi, REG_CONTROL, control); in mchp_corespi_set_mode()
394 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_interrupt() local
395 u32 intfield = mchp_corespi_read(spi, REG_MIS) & 0xf; in mchp_corespi_interrupt()
403 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TXDONE); in mchp_corespi_interrupt()
406 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RXRDY); in mchp_corespi_interrupt()
408 if (spi->rx_len) in mchp_corespi_interrupt()
409 mchp_corespi_read_fifo(spi); in mchp_corespi_interrupt()
412 if (!spi->rx_len && !spi->tx_len) in mchp_corespi_interrupt()
416 mchp_corespi_write(spi, REG_INT_CLEAR, INT_RX_CHANNEL_OVERFLOW); in mchp_corespi_interrupt()
418 dev_err(&host->dev, in mchp_corespi_interrupt()
420 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
424 mchp_corespi_write(spi, REG_INT_CLEAR, INT_TX_CHANNEL_UNDERRUN); in mchp_corespi_interrupt()
426 dev_err(&host->dev, in mchp_corespi_interrupt()
428 spi->rx_len, spi->tx_len); in mchp_corespi_interrupt()
437 static int mchp_corespi_calculate_clkgen(struct mchp_corespi *spi, in mchp_corespi_calculate_clkgen() argument
442 clk_hz = clk_get_rate(spi->clk); in mchp_corespi_calculate_clkgen()
444 return -EINVAL; in mchp_corespi_calculate_clkgen()
457 clk_gen = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1; in mchp_corespi_calculate_clkgen()
460 clk_gen = fls(clk_gen) - 1; in mchp_corespi_calculate_clkgen()
463 return -EINVAL; in mchp_corespi_calculate_clkgen()
465 spi->clk_mode = 0; in mchp_corespi_calculate_clkgen()
467 spi->clk_mode = 1; in mchp_corespi_calculate_clkgen()
470 spi->clk_gen = clk_gen; in mchp_corespi_calculate_clkgen()
478 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_transfer_one() local
481 ret = mchp_corespi_calculate_clkgen(spi, (unsigned long)xfer->speed_hz); in mchp_corespi_transfer_one()
483 dev_err(&host->dev, "failed to set clk_gen for target %u Hz\n", xfer->speed_hz); in mchp_corespi_transfer_one()
487 mchp_corespi_set_clk_gen(spi); in mchp_corespi_transfer_one()
489 spi->tx_buf = xfer->tx_buf; in mchp_corespi_transfer_one()
490 spi->rx_buf = xfer->rx_buf; in mchp_corespi_transfer_one()
491 spi->tx_len = xfer->len; in mchp_corespi_transfer_one()
492 spi->rx_len = xfer->len; in mchp_corespi_transfer_one()
493 spi->pending = 0; in mchp_corespi_transfer_one()
495 mchp_corespi_set_xfer_size(spi, (spi->tx_len > FIFO_DEPTH) in mchp_corespi_transfer_one()
496 ? FIFO_DEPTH : spi->tx_len); in mchp_corespi_transfer_one()
498 mchp_corespi_write(spi, REG_COMMAND, COMMAND_RXFIFORST | COMMAND_TXFIFORST); in mchp_corespi_transfer_one()
500 mchp_corespi_write(spi, REG_SLAVE_SELECT, spi->pending_slave_select); in mchp_corespi_transfer_one()
502 while (spi->tx_len) in mchp_corespi_transfer_one()
503 mchp_corespi_write_fifo(spi); in mchp_corespi_transfer_one()
511 struct spi_device *spi_dev = msg->spi; in mchp_corespi_prepare_message()
512 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_prepare_message() local
514 mchp_corespi_set_framesize(spi, DEFAULT_FRAMESIZE); in mchp_corespi_prepare_message()
515 mchp_corespi_set_mode(spi, spi_dev->mode); in mchp_corespi_prepare_message()
523 struct mchp_corespi *spi; in mchp_corespi_probe() local
528 host = devm_spi_alloc_host(&pdev->dev, sizeof(*spi)); in mchp_corespi_probe()
530 return dev_err_probe(&pdev->dev, -ENOMEM, in mchp_corespi_probe()
531 "unable to allocate host for SPI controller\n"); in mchp_corespi_probe()
535 if (of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs)) in mchp_corespi_probe()
538 host->num_chipselect = num_cs; in mchp_corespi_probe()
539 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; in mchp_corespi_probe()
540 host->setup = mchp_corespi_setup; in mchp_corespi_probe()
541 host->bits_per_word_mask = SPI_BPW_MASK(8); in mchp_corespi_probe()
542 host->transfer_one = mchp_corespi_transfer_one; in mchp_corespi_probe()
543 host->prepare_message = mchp_corespi_prepare_message; in mchp_corespi_probe()
544 host->set_cs = mchp_corespi_set_cs; in mchp_corespi_probe()
545 host->dev.of_node = pdev->dev.of_node; in mchp_corespi_probe()
547 spi = spi_controller_get_devdata(host); in mchp_corespi_probe()
549 spi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in mchp_corespi_probe()
550 if (IS_ERR(spi->regs)) in mchp_corespi_probe()
551 return PTR_ERR(spi->regs); in mchp_corespi_probe()
553 spi->irq = platform_get_irq(pdev, 0); in mchp_corespi_probe()
554 if (spi->irq < 0) in mchp_corespi_probe()
555 return spi->irq; in mchp_corespi_probe()
557 ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt, in mchp_corespi_probe()
558 IRQF_SHARED, dev_name(&pdev->dev), host); in mchp_corespi_probe()
560 return dev_err_probe(&pdev->dev, ret, in mchp_corespi_probe()
563 spi->clk = devm_clk_get(&pdev->dev, NULL); in mchp_corespi_probe()
564 if (IS_ERR(spi->clk)) in mchp_corespi_probe()
565 return dev_err_probe(&pdev->dev, PTR_ERR(spi->clk), in mchp_corespi_probe()
566 "could not get clk\n"); in mchp_corespi_probe()
568 ret = clk_prepare_enable(spi->clk); in mchp_corespi_probe()
570 return dev_err_probe(&pdev->dev, ret, in mchp_corespi_probe()
573 mchp_corespi_init(host, spi); in mchp_corespi_probe()
575 ret = devm_spi_register_controller(&pdev->dev, host); in mchp_corespi_probe()
577 mchp_corespi_disable(spi); in mchp_corespi_probe()
578 clk_disable_unprepare(spi->clk); in mchp_corespi_probe()
579 return dev_err_probe(&pdev->dev, ret, in mchp_corespi_probe()
580 "unable to register host for SPI controller\n"); in mchp_corespi_probe()
583 dev_info(&pdev->dev, "Registered SPI controller %d\n", host->bus_num); in mchp_corespi_probe()
591 struct mchp_corespi *spi = spi_controller_get_devdata(host); in mchp_corespi_remove() local
593 mchp_corespi_disable_ints(spi); in mchp_corespi_remove()
594 clk_disable_unprepare(spi->clk); in mchp_corespi_remove()
595 mchp_corespi_disable(spi); in mchp_corespi_remove()
606 { .compatible = "microchip,mpfs-spi" },
615 .name = "microchip-corespi",
622 MODULE_DESCRIPTION("Microchip coreSPI SPI controller driver");