Lines Matching +full:synquacer +full:- +full:spi

1 // SPDX-License-Identifier: GPL-2.0
3 // Synquacer HSSPI controller driver
5 // Copyright (c) 2015-2018 Socionext Inc.
6 // Copyright (c) 2018-2019 Linaro Ltd.
19 #include <linux/spi/spi.h>
108 (SYNQUACER_HSSPI_FIFO_DEPTH - SYNQUACER_HSSPI_FIFO_TX_THRESHOLD)
143 u32 len = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTATUS); in read_fifo()
147 len = min(len, sspi->rx_words); in read_fifo()
149 switch (sspi->bpw) { in read_fifo()
151 u8 *buf = sspi->rx_buf; in read_fifo()
153 ioread8_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO, in read_fifo()
155 sspi->rx_buf = buf + len; in read_fifo()
159 u16 *buf = sspi->rx_buf; in read_fifo()
161 ioread16_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO, in read_fifo()
163 sspi->rx_buf = buf + len; in read_fifo()
167 /* fallthrough, should use 32-bits access */ in read_fifo()
169 u32 *buf = sspi->rx_buf; in read_fifo()
171 ioread32_rep(sspi->regs + SYNQUACER_HSSPI_REG_RX_FIFO, in read_fifo()
173 sspi->rx_buf = buf + len; in read_fifo()
177 return -EINVAL; in read_fifo()
180 sspi->rx_words -= len; in read_fifo()
186 u32 len = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTATUS); in write_fifo()
190 len = min(SYNQUACER_HSSPI_FIFO_DEPTH - len, in write_fifo()
191 sspi->tx_words); in write_fifo()
193 switch (sspi->bpw) { in write_fifo()
195 const u8 *buf = sspi->tx_buf; in write_fifo()
197 iowrite8_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO, in write_fifo()
199 sspi->tx_buf = buf + len; in write_fifo()
203 const u16 *buf = sspi->tx_buf; in write_fifo()
205 iowrite16_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO, in write_fifo()
207 sspi->tx_buf = buf + len; in write_fifo()
211 /* fallthrough, should use 32-bits access */ in write_fifo()
213 const u32 *buf = sspi->tx_buf; in write_fifo()
215 iowrite32_rep(sspi->regs + SYNQUACER_HSSPI_REG_TX_FIFO, in write_fifo()
217 sspi->tx_buf = buf + len; in write_fifo()
221 return -EINVAL; in write_fifo()
224 sspi->tx_words -= len; in write_fifo()
229 struct spi_device *spi, in synquacer_spi_config() argument
236 /* Full Duplex only on 1-bit wide bus */ in synquacer_spi_config()
237 if (xfer->rx_buf && xfer->tx_buf && in synquacer_spi_config()
238 (xfer->rx_nbits != 1 || xfer->tx_nbits != 1)) { in synquacer_spi_config()
239 dev_err(sspi->dev, in synquacer_spi_config()
240 "RX and TX bus widths must be 1-bit for Full-Duplex!\n"); in synquacer_spi_config()
241 return -EINVAL; in synquacer_spi_config()
244 if (xfer->tx_buf) { in synquacer_spi_config()
245 bus_width = xfer->tx_nbits; in synquacer_spi_config()
248 bus_width = xfer->rx_nbits; in synquacer_spi_config()
252 mode = spi->mode; in synquacer_spi_config()
253 cs = spi_get_chipselect(spi, 0); in synquacer_spi_config()
254 speed = xfer->speed_hz; in synquacer_spi_config()
255 bpw = xfer->bits_per_word; in synquacer_spi_config()
258 if (speed == sspi->speed && in synquacer_spi_config()
259 bus_width == sspi->bus_width && bpw == sspi->bpw && in synquacer_spi_config()
260 mode == sspi->mode && cs == sspi->cs && in synquacer_spi_config()
261 transfer_mode == sspi->transfer_mode) { in synquacer_spi_config()
265 sspi->transfer_mode = transfer_mode; in synquacer_spi_config()
266 rate = host->max_speed_hz; in synquacer_spi_config()
270 dev_err(sspi->dev, "Requested rate too low (%u)\n", in synquacer_spi_config()
271 sspi->speed); in synquacer_spi_config()
272 return -EINVAL; in synquacer_spi_config()
275 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_PCC(cs)); in synquacer_spi_config()
304 if (sspi->aces) in synquacer_spi_config()
309 if (sspi->rtm) in synquacer_spi_config()
321 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_PCC(cs)); in synquacer_spi_config()
323 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG); in synquacer_spi_config()
326 val |= ((bpw / 8 - 1) << SYNQUACER_HSSPI_FIFOCFG_FIFO_WIDTH_SHIFT); in synquacer_spi_config()
327 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG); in synquacer_spi_config()
329 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_config()
333 if (xfer->rx_buf) in synquacer_spi_config()
342 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_config()
344 sspi->bpw = bpw; in synquacer_spi_config()
345 sspi->mode = mode; in synquacer_spi_config()
346 sspi->speed = speed; in synquacer_spi_config()
347 sspi->cs = spi_get_chipselect(spi, 0); in synquacer_spi_config()
348 sspi->bus_width = bus_width; in synquacer_spi_config()
354 struct spi_device *spi, in synquacer_spi_transfer_one() argument
364 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_transfer_one()
366 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_transfer_one()
368 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG); in synquacer_spi_transfer_one()
371 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG); in synquacer_spi_transfer_one()
374 * See if we can transfer 4-bytes as 1 word in synquacer_spi_transfer_one()
377 bpw = xfer->bits_per_word; in synquacer_spi_transfer_one()
378 if (bpw == 8 && !(xfer->len % 4) && !(spi->mode & SPI_LSB_FIRST)) in synquacer_spi_transfer_one()
379 xfer->bits_per_word = 32; in synquacer_spi_transfer_one()
381 ret = synquacer_spi_config(host, spi, xfer); in synquacer_spi_transfer_one()
384 xfer->bits_per_word = bpw; in synquacer_spi_transfer_one()
389 reinit_completion(&sspi->transfer_done); in synquacer_spi_transfer_one()
391 sspi->tx_buf = xfer->tx_buf; in synquacer_spi_transfer_one()
392 sspi->rx_buf = xfer->rx_buf; in synquacer_spi_transfer_one()
394 switch (sspi->bpw) { in synquacer_spi_transfer_one()
396 words = xfer->len; in synquacer_spi_transfer_one()
399 words = xfer->len / 2; in synquacer_spi_transfer_one()
402 /* fallthrough, should use 32-bits access */ in synquacer_spi_transfer_one()
404 words = xfer->len / 4; in synquacer_spi_transfer_one()
407 dev_err(sspi->dev, "unsupported bpw: %d\n", sspi->bpw); in synquacer_spi_transfer_one()
408 return -EINVAL; in synquacer_spi_transfer_one()
411 if (xfer->tx_buf) in synquacer_spi_transfer_one()
412 sspi->tx_words = words; in synquacer_spi_transfer_one()
414 sspi->tx_words = 0; in synquacer_spi_transfer_one()
416 if (xfer->rx_buf) in synquacer_spi_transfer_one()
417 sspi->rx_words = words; in synquacer_spi_transfer_one()
419 sspi->rx_words = 0; in synquacer_spi_transfer_one()
421 if (xfer->tx_buf) { in synquacer_spi_transfer_one()
424 dev_err(sspi->dev, "failed write_fifo. status: 0x%x\n", in synquacer_spi_transfer_one()
430 if (xfer->rx_buf) { in synquacer_spi_transfer_one()
431 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG); in synquacer_spi_transfer_one()
434 val |= ((sspi->rx_words > SYNQUACER_HSSPI_FIFO_DEPTH ? in synquacer_spi_transfer_one()
435 SYNQUACER_HSSPI_FIFO_RX_THRESHOLD : sspi->rx_words) << in synquacer_spi_transfer_one()
437 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_FIFOCFG); in synquacer_spi_transfer_one()
440 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_TXC); in synquacer_spi_transfer_one()
441 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_RXC); in synquacer_spi_transfer_one()
444 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_transfer_one()
446 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_transfer_one()
448 if (xfer->tx_buf) { in synquacer_spi_transfer_one()
450 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_TXE); in synquacer_spi_transfer_one()
451 status = wait_for_completion_timeout(&sspi->transfer_done, in synquacer_spi_transfer_one()
453 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE); in synquacer_spi_transfer_one()
456 if (xfer->rx_buf) { in synquacer_spi_transfer_one()
461 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_RXE); in synquacer_spi_transfer_one()
462 status = wait_for_completion_timeout(&sspi->transfer_done, in synquacer_spi_transfer_one()
464 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE); in synquacer_spi_transfer_one()
467 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_transfer_one()
469 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_transfer_one()
470 sspi->rx_buf = buf; in synquacer_spi_transfer_one()
471 sspi->rx_words = SYNQUACER_HSSPI_FIFO_DEPTH; in synquacer_spi_transfer_one()
476 dev_err(sspi->dev, "failed to transfer. Timeout.\n"); in synquacer_spi_transfer_one()
477 return -ETIMEDOUT; in synquacer_spi_transfer_one()
483 static void synquacer_spi_set_cs(struct spi_device *spi, bool enable) in synquacer_spi_set_cs() argument
485 struct synquacer_spi *sspi = spi_controller_get_devdata(spi->controller); in synquacer_spi_set_cs()
488 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_set_cs()
491 val |= spi_get_chipselect(spi, 0) << SYNQUACER_HSSPI_DMPSEL_CS_SHIFT; in synquacer_spi_set_cs()
496 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMSTART); in synquacer_spi_set_cs()
508 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_MCTRL) & in synquacer_spi_wait_status_update()
516 dev_err(sspi->dev, "timeout occurs in updating Module Enable Status\n"); in synquacer_spi_wait_status_update()
517 return -EBUSY; in synquacer_spi_wait_status_update()
527 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL); in synquacer_spi_enable()
532 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE); in synquacer_spi_enable()
533 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE); in synquacer_spi_enable()
534 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_TXC); in synquacer_spi_enable()
535 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_RXC); in synquacer_spi_enable()
536 writel(~0, sspi->regs + SYNQUACER_HSSPI_REG_FAULTC); in synquacer_spi_enable()
538 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_DMCFG); in synquacer_spi_enable()
541 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_DMCFG); in synquacer_spi_enable()
543 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_MCTRL); in synquacer_spi_enable()
544 if (sspi->clk_src_type == SYNQUACER_HSSPI_CLOCK_SRC_IPCLK) in synquacer_spi_enable()
554 writel(val, sspi->regs + SYNQUACER_HSSPI_REG_MCTRL); in synquacer_spi_enable()
567 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_RXF); in sq_spi_rx_handler()
572 if (sspi->rx_words == 0) { in sq_spi_rx_handler()
573 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_RXE); in sq_spi_rx_handler()
574 complete(&sspi->transfer_done); in sq_spi_rx_handler()
587 val = readl(sspi->regs + SYNQUACER_HSSPI_REG_TXF); in sq_spi_tx_handler()
589 if (sspi->tx_words == 0) { in sq_spi_tx_handler()
590 writel(0, sspi->regs + SYNQUACER_HSSPI_REG_TXE); in sq_spi_tx_handler()
591 complete(&sspi->transfer_done); in sq_spi_tx_handler()
603 struct device_node *np = pdev->dev.of_node; in synquacer_spi_probe()
609 host = spi_alloc_host(&pdev->dev, sizeof(*sspi)); in synquacer_spi_probe()
611 return -ENOMEM; in synquacer_spi_probe()
616 sspi->dev = &pdev->dev; in synquacer_spi_probe()
618 init_completion(&sspi->transfer_done); in synquacer_spi_probe()
620 sspi->regs = devm_platform_ioremap_resource(pdev, 0); in synquacer_spi_probe()
621 if (IS_ERR(sspi->regs)) { in synquacer_spi_probe()
622 ret = PTR_ERR(sspi->regs); in synquacer_spi_probe()
626 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK; /* Default */ in synquacer_spi_probe()
627 device_property_read_u32(&pdev->dev, "socionext,ihclk-rate", in synquacer_spi_probe()
628 &host->max_speed_hz); /* for ACPI */ in synquacer_spi_probe()
630 if (dev_of_node(&pdev->dev)) { in synquacer_spi_probe()
631 if (device_property_match_string(&pdev->dev, in synquacer_spi_probe()
632 "clock-names", "iHCLK") >= 0) { in synquacer_spi_probe()
633 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IHCLK; in synquacer_spi_probe()
634 sspi->clk = devm_clk_get(sspi->dev, "iHCLK"); in synquacer_spi_probe()
635 } else if (device_property_match_string(&pdev->dev, in synquacer_spi_probe()
636 "clock-names", "iPCLK") >= 0) { in synquacer_spi_probe()
637 sspi->clk_src_type = SYNQUACER_HSSPI_CLOCK_SRC_IPCLK; in synquacer_spi_probe()
638 sspi->clk = devm_clk_get(sspi->dev, "iPCLK"); in synquacer_spi_probe()
640 dev_err(&pdev->dev, "specified wrong clock source\n"); in synquacer_spi_probe()
641 ret = -EINVAL; in synquacer_spi_probe()
645 if (IS_ERR(sspi->clk)) { in synquacer_spi_probe()
646 ret = dev_err_probe(&pdev->dev, PTR_ERR(sspi->clk), in synquacer_spi_probe()
651 ret = clk_prepare_enable(sspi->clk); in synquacer_spi_probe()
653 dev_err(&pdev->dev, "failed to enable clock (%d)\n", in synquacer_spi_probe()
658 host->max_speed_hz = clk_get_rate(sspi->clk); in synquacer_spi_probe()
661 if (!host->max_speed_hz) { in synquacer_spi_probe()
662 dev_err(&pdev->dev, "missing clock source\n"); in synquacer_spi_probe()
663 ret = -EINVAL; in synquacer_spi_probe()
666 host->min_speed_hz = host->max_speed_hz / 254; in synquacer_spi_probe()
668 sspi->aces = device_property_read_bool(&pdev->dev, in synquacer_spi_probe()
669 "socionext,set-aces"); in synquacer_spi_probe()
670 sspi->rtm = device_property_read_bool(&pdev->dev, "socionext,use-rtm"); in synquacer_spi_probe()
672 host->num_chipselect = SYNQUACER_HSSPI_NUM_CHIP_SELECT; in synquacer_spi_probe()
679 snprintf(sspi->rx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-rx", in synquacer_spi_probe()
680 dev_name(&pdev->dev)); in synquacer_spi_probe()
681 ret = devm_request_irq(&pdev->dev, rx_irq, sq_spi_rx_handler, in synquacer_spi_probe()
682 0, sspi->rx_irq_name, sspi); in synquacer_spi_probe()
684 dev_err(&pdev->dev, "request rx_irq failed (%d)\n", ret); in synquacer_spi_probe()
693 snprintf(sspi->tx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-tx", in synquacer_spi_probe()
694 dev_name(&pdev->dev)); in synquacer_spi_probe()
695 ret = devm_request_irq(&pdev->dev, tx_irq, sq_spi_tx_handler, in synquacer_spi_probe()
696 0, sspi->tx_irq_name, sspi); in synquacer_spi_probe()
698 dev_err(&pdev->dev, "request tx_irq failed (%d)\n", ret); in synquacer_spi_probe()
702 host->dev.of_node = np; in synquacer_spi_probe()
703 host->dev.fwnode = pdev->dev.fwnode; in synquacer_spi_probe()
704 host->auto_runtime_pm = true; in synquacer_spi_probe()
705 host->bus_num = pdev->id; in synquacer_spi_probe()
707 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL | in synquacer_spi_probe()
709 host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(24) | in synquacer_spi_probe()
712 host->set_cs = synquacer_spi_set_cs; in synquacer_spi_probe()
713 host->transfer_one = synquacer_spi_transfer_one; in synquacer_spi_probe()
719 pm_runtime_set_active(sspi->dev); in synquacer_spi_probe()
720 pm_runtime_enable(sspi->dev); in synquacer_spi_probe()
722 ret = devm_spi_register_controller(sspi->dev, host); in synquacer_spi_probe()
729 pm_runtime_disable(sspi->dev); in synquacer_spi_probe()
731 clk_disable_unprepare(sspi->clk); in synquacer_spi_probe()
743 pm_runtime_disable(sspi->dev); in synquacer_spi_remove()
745 clk_disable_unprepare(sspi->clk); in synquacer_spi_remove()
759 clk_disable_unprepare(sspi->clk); in synquacer_spi_suspend()
772 sspi->speed = 0; in synquacer_spi_resume()
774 ret = clk_prepare_enable(sspi->clk); in synquacer_spi_resume()
783 clk_disable_unprepare(sspi->clk); in synquacer_spi_resume()
784 dev_err(dev, "failed to enable spi (%d)\n", ret); in synquacer_spi_resume()
791 clk_disable_unprepare(sspi->clk); in synquacer_spi_resume()
800 {.compatible = "socionext,synquacer-spi"},
815 .name = "synquacer-spi",
825 MODULE_DESCRIPTION("Socionext Synquacer HS-SPI controller driver");