Lines Matching +full:spim +full:- +full:ctrl
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright 2000-2010 Broadcom Corporation
6 * Copyright 2012-2013 Jonas Gorski <jonas.gorski@gmail.com>
7 * Copyright 2019-2022 Broadcom Ltd
17 #include <linux/dma-mapping.h>
23 #include <linux/spi/spi-mem.h>
129 struct spi_controller *ctrl = dev_get_drvdata(dev); in wait_mode_show() local
130 struct bcmbca_hsspi *bs = spi_controller_get_devdata(ctrl); in wait_mode_show()
132 return sprintf(buf, "%d\n", bs->wait_mode); in wait_mode_show()
138 struct spi_controller *ctrl = dev_get_drvdata(dev); in wait_mode_store() local
139 struct bcmbca_hsspi *bs = spi_controller_get_devdata(ctrl); in wait_mode_store()
143 return -EINVAL; in wait_mode_store()
147 return -EINVAL; in wait_mode_store()
150 mutex_lock(&bs->msg_mutex); in wait_mode_store()
151 bs->wait_mode = val; in wait_mode_store()
154 __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); in wait_mode_store()
155 mutex_unlock(&bs->msg_mutex); in wait_mode_store()
180 mutex_lock(&bs->bus_mutex); in bcmbca_hsspi_set_cs()
182 reg = __raw_readl(bs->spim_ctrl); in bcmbca_hsspi_set_cs()
188 __raw_writel(reg, bs->spim_ctrl); in bcmbca_hsspi_set_cs()
190 mutex_unlock(&bs->bus_mutex); in bcmbca_hsspi_set_cs()
199 reg = DIV_ROUND_UP(2048, DIV_ROUND_UP(bs->speed_hz, hz)); in bcmbca_hsspi_set_clk()
201 bs->regs + HSSPI_PROFILE_CLK_CTRL_REG(profile)); in bcmbca_hsspi_set_clk()
203 reg = __raw_readl(bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile)); in bcmbca_hsspi_set_clk()
208 __raw_writel(reg, bs->regs + HSSPI_PROFILE_SIGNAL_CTRL_REG(profile)); in bcmbca_hsspi_set_clk()
210 mutex_lock(&bs->bus_mutex); in bcmbca_hsspi_set_clk()
212 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcmbca_hsspi_set_clk()
214 if (spi->mode & SPI_CPOL) in bcmbca_hsspi_set_clk()
216 __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcmbca_hsspi_set_clk()
218 mutex_unlock(&bs->bus_mutex); in bcmbca_hsspi_set_clk()
227 if (bs->wait_mode == HSSPI_WAIT_MODE_INTR) { in bcmbca_hsspi_wait_cmd()
228 if (wait_for_completion_timeout(&bs->done, HZ) == 0) in bcmbca_hsspi_wait_cmd()
234 reg = __raw_readl(bs->regs + HSSPI_PINGPONG_STATUS_REG(0)); in bcmbca_hsspi_wait_cmd()
245 dev_err(&bs->pdev->dev, "transfer timed out!\n"); in bcmbca_hsspi_wait_cmd()
253 struct bcmbca_hsspi *bs = spi_controller_get_devdata(spi->controller); in bcmbca_hsspi_do_txrx()
256 int pending = t->len; in bcmbca_hsspi_do_txrx()
258 const u8 *tx = t->tx_buf; in bcmbca_hsspi_do_txrx()
259 u8 *rx = t->rx_buf; in bcmbca_hsspi_do_txrx()
262 bcmbca_hsspi_set_clk(bs, spi, t->speed_hz); in bcmbca_hsspi_do_txrx()
272 step_size -= HSSPI_OPCODE_LEN; in bcmbca_hsspi_do_txrx()
274 if ((opcode == HSSPI_OP_READ && t->rx_nbits == SPI_NBITS_DUAL) || in bcmbca_hsspi_do_txrx()
275 (opcode == HSSPI_OP_WRITE && t->tx_nbits == SPI_NBITS_DUAL)) { in bcmbca_hsspi_do_txrx()
278 if (t->rx_nbits == SPI_NBITS_DUAL) in bcmbca_hsspi_do_txrx()
280 if (t->tx_nbits == SPI_NBITS_DUAL) in bcmbca_hsspi_do_txrx()
285 bs->regs + HSSPI_PROFILE_MODE_CTRL_REG(chip_select)); in bcmbca_hsspi_do_txrx()
290 reinit_completion(&bs->done); in bcmbca_hsspi_do_txrx()
292 memcpy_toio(bs->fifo + HSSPI_OPCODE_LEN, tx, curr_step); in bcmbca_hsspi_do_txrx()
297 __raw_writew(val, bs->fifo); in bcmbca_hsspi_do_txrx()
300 if (bs->wait_mode == HSSPI_WAIT_MODE_INTR) in bcmbca_hsspi_do_txrx()
302 bs->regs + HSSPI_INT_MASK_REG); in bcmbca_hsspi_do_txrx()
313 __raw_writel(reg, bs->regs + HSSPI_PINGPONG_COMMAND_REG(0)); in bcmbca_hsspi_do_txrx()
316 return -ETIMEDOUT; in bcmbca_hsspi_do_txrx()
318 pending -= curr_step; in bcmbca_hsspi_do_txrx()
321 memcpy_fromio(rx, bs->fifo, curr_step); in bcmbca_hsspi_do_txrx()
331 struct bcmbca_hsspi *bs = spi_controller_get_devdata(spi->controller); in bcmbca_hsspi_setup()
334 reg = __raw_readl(bs->regs + in bcmbca_hsspi_setup()
337 if (spi->mode & SPI_CPHA) in bcmbca_hsspi_setup()
341 __raw_writel(reg, bs->regs + in bcmbca_hsspi_setup()
344 mutex_lock(&bs->bus_mutex); in bcmbca_hsspi_setup()
345 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcmbca_hsspi_setup()
347 if (spi->mode & SPI_CS_HIGH) in bcmbca_hsspi_setup()
351 __raw_writel(reg, bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcmbca_hsspi_setup()
353 if (spi->mode & SPI_CS_HIGH) in bcmbca_hsspi_setup()
354 bs->cs_polarity |= BIT(spi_get_chipselect(spi, 0)); in bcmbca_hsspi_setup()
356 bs->cs_polarity &= ~BIT(spi_get_chipselect(spi, 0)); in bcmbca_hsspi_setup()
358 reg = __raw_readl(bs->spim_ctrl); in bcmbca_hsspi_setup()
360 if (spi->mode & SPI_CS_HIGH) in bcmbca_hsspi_setup()
362 __raw_writel(reg, bs->spim_ctrl); in bcmbca_hsspi_setup()
364 mutex_unlock(&bs->bus_mutex); in bcmbca_hsspi_setup()
374 struct spi_device *spi = msg->spi; in bcmbca_hsspi_transfer_one()
375 int status = -EINVAL; in bcmbca_hsspi_transfer_one()
378 mutex_lock(&bs->msg_mutex); in bcmbca_hsspi_transfer_one()
379 list_for_each_entry(t, &msg->transfers, transfer_list) { in bcmbca_hsspi_transfer_one()
386 if (t->cs_change) { in bcmbca_hsspi_transfer_one()
387 if (list_is_last(&t->transfer_list, &msg->transfers)) { in bcmbca_hsspi_transfer_one()
390 if (!t->cs_off) in bcmbca_hsspi_transfer_one()
395 if (!list_next_entry(t, transfer_list)->cs_off) in bcmbca_hsspi_transfer_one()
398 } else if (!list_is_last(&t->transfer_list, &msg->transfers) && in bcmbca_hsspi_transfer_one()
399 t->cs_off != list_next_entry(t, transfer_list)->cs_off) { in bcmbca_hsspi_transfer_one()
400 bcmbca_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), t->cs_off); in bcmbca_hsspi_transfer_one()
403 msg->actual_length += t->len; in bcmbca_hsspi_transfer_one()
406 mutex_unlock(&bs->msg_mutex); in bcmbca_hsspi_transfer_one()
411 msg->status = status; in bcmbca_hsspi_transfer_one()
421 if (__raw_readl(bs->regs + HSSPI_INT_STATUS_MASKED_REG) == 0) in bcmbca_hsspi_interrupt()
424 __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); in bcmbca_hsspi_interrupt()
425 __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); in bcmbca_hsspi_interrupt()
427 complete(&bs->done); in bcmbca_hsspi_interrupt()
438 struct device *dev = &pdev->dev; in bcmbca_hsspi_probe()
451 spim_ctrl = devm_platform_ioremap_resource_byname(pdev, "spim-ctrl"); in bcmbca_hsspi_probe()
478 ret = -EINVAL; in bcmbca_hsspi_probe()
483 host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs)); in bcmbca_hsspi_probe()
485 ret = -ENOMEM; in bcmbca_hsspi_probe()
490 bs->pdev = pdev; in bcmbca_hsspi_probe()
491 bs->clk = clk; in bcmbca_hsspi_probe()
492 bs->pll_clk = pll_clk; in bcmbca_hsspi_probe()
493 bs->regs = regs; in bcmbca_hsspi_probe()
494 bs->spim_ctrl = spim_ctrl; in bcmbca_hsspi_probe()
495 bs->speed_hz = rate; in bcmbca_hsspi_probe()
496 bs->fifo = (u8 __iomem *) (bs->regs + HSSPI_FIFO_REG(0)); in bcmbca_hsspi_probe()
497 bs->wait_mode = HSSPI_WAIT_MODE_POLLING; in bcmbca_hsspi_probe()
499 mutex_init(&bs->bus_mutex); in bcmbca_hsspi_probe()
500 mutex_init(&bs->msg_mutex); in bcmbca_hsspi_probe()
501 init_completion(&bs->done); in bcmbca_hsspi_probe()
503 host->dev.of_node = dev->of_node; in bcmbca_hsspi_probe()
504 if (!dev->of_node) in bcmbca_hsspi_probe()
505 host->bus_num = HSSPI_BUS_NUM; in bcmbca_hsspi_probe()
507 of_property_read_u32(dev->of_node, "num-cs", &num_cs); in bcmbca_hsspi_probe()
513 host->num_chipselect = num_cs; in bcmbca_hsspi_probe()
514 host->setup = bcmbca_hsspi_setup; in bcmbca_hsspi_probe()
515 host->transfer_one_message = bcmbca_hsspi_transfer_one; in bcmbca_hsspi_probe()
516 host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | in bcmbca_hsspi_probe()
518 host->bits_per_word_mask = SPI_BPW_MASK(8); in bcmbca_hsspi_probe()
519 host->auto_runtime_pm = true; in bcmbca_hsspi_probe()
524 __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); in bcmbca_hsspi_probe()
527 __raw_writel(HSSPI_INT_CLEAR_ALL, bs->regs + HSSPI_INT_STATUS_REG); in bcmbca_hsspi_probe()
530 reg = __raw_readl(bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcmbca_hsspi_probe()
531 bs->cs_polarity = reg & GLOBAL_CTRL_CS_POLARITY_MASK; in bcmbca_hsspi_probe()
533 bs->regs + HSSPI_GLOBAL_CTRL_REG); in bcmbca_hsspi_probe()
537 pdev->name, bs); in bcmbca_hsspi_probe()
542 ret = devm_pm_runtime_enable(&pdev->dev); in bcmbca_hsspi_probe()
546 ret = sysfs_create_group(&pdev->dev.kobj, &bcmbca_hsspi_group); in bcmbca_hsspi_probe()
548 dev_err(&pdev->dev, "couldn't register sysfs group\n"); in bcmbca_hsspi_probe()
562 sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); in bcmbca_hsspi_probe()
576 __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); in bcmbca_hsspi_remove()
577 clk_disable_unprepare(bs->pll_clk); in bcmbca_hsspi_remove()
578 clk_disable_unprepare(bs->clk); in bcmbca_hsspi_remove()
579 sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); in bcmbca_hsspi_remove()
589 clk_disable_unprepare(bs->pll_clk); in bcmbca_hsspi_suspend()
590 clk_disable_unprepare(bs->clk); in bcmbca_hsspi_suspend()
601 ret = clk_prepare_enable(bs->clk); in bcmbca_hsspi_resume()
605 if (bs->pll_clk) { in bcmbca_hsspi_resume()
606 ret = clk_prepare_enable(bs->pll_clk); in bcmbca_hsspi_resume()
608 clk_disable_unprepare(bs->clk); in bcmbca_hsspi_resume()
623 { .compatible = "brcm,bcmbca-hsspi-v1.1", },
631 .name = "bcmbca-hsspi",