From: Alex Elder <elder@riscstar.com>
To: Yixun Lan <dlan@gentoo.org>
Cc: broonie@kernel.org, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, ziyao@disroot.org,
linux-spi@vger.kernel.org, devicetree@vger.kernel.org,
paul.walmsley@sifive.com, palmer@dabbelt.com,
aou@eecs.berkeley.edu, alex@ghiti.fr, p.zabel@pengutronix.de,
spacemit@lists.linux.dev, linux-riscv@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 2/3] spi: spacemit: introduce SpacemiT K1 SPI controller driver
Date: Tue, 23 Sep 2025 07:49:22 -0500 [thread overview]
Message-ID: <786f4a5e-f62e-4cd0-a017-7b61408f34aa@riscstar.com> (raw)
In-Reply-To: <20250922230639-GYA1303776@gentoo.org>
On 9/22/25 6:06 PM, Yixun Lan wrote:
> Hi Alex,
>
> On 11:17 Mon 22 Sep , Alex Elder wrote:
>> This patch introduces the driver for the SPI controller found in the
>> SpacemiT K1 SoC. Currently the driver supports master mode only.
>> The SPI hardware implements RX and TX FIFOs, 32 entries each, and
>> supports both PIO and DMA mode transfers.
>>
>> Signed-off-by: Alex Elder <elder@riscstar.com>
>> ---
>> v3: - Added imply_PDMA to the SPI_SPACEMIT_K1 Kconfig option
>> - Fixed a bug pointed out by Vivian (and Troy) in word-sized reads
>> - Added a comment stating we use 1, 2, or 4 bytes per word
>> - Cleaned up DMA channels properly in case of failure setting up
>> - No longer use devm_*() for allocating DMA channels or buffer
>>
>> drivers/spi/Kconfig | 9 +
>> drivers/spi/Makefile | 1 +
>> drivers/spi/spi-spacemit-k1.c | 965 ++++++++++++++++++++++++++++++++++
>> 3 files changed, 975 insertions(+)
>> create mode 100644 drivers/spi/spi-spacemit-k1.c
. . .
>> diff --git a/drivers/spi/spi-spacemit-k1.c b/drivers/spi/spi-spacemit-k1.c
>> new file mode 100644
>> index 0000000000000..2b932d80cc510
>> --- /dev/null
>> +++ b/drivers/spi/spi-spacemit-k1.c
>> @@ -0,0 +1,965 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Support for SpacemiT K1 SPI controller
>> + *
>> + * Copyright (C) 2025 by RISCstar Solutions Corporation. All rights reserved.
>> + * Copyright (c) 2023, spacemit Corporation.
>> + */
. . .
>> +static irqreturn_t k1_spi_ssp_isr(int irq, void *dev_id)
>> +{
>> + struct k1_spi_driver_data *drv_data = dev_id;
>> + bool rx_done;
>> + bool tx_done;
>> + u32 val;
>> +
>> + /* Get status and clear pending interrupts */
>> + val = readl(drv_data->base + SSP_STATUS);
>> + writel(val, drv_data->base + SSP_STATUS);
>> +
>> + if (!drv_data->message)
>> + return IRQ_NONE;
>> +
>> + /* Check for a TX underrun or RX underrun first */
> s/RX underrun/RX overrun/
OK.
>> + if (val & (SSP_STATUS_TUR | SSP_STATUS_ROR)) {
>> + /* Disable all interrupts on error */
>> + writel(0, drv_data->base + SSP_INT_EN);
> should clear status of SSP_STATUS instead of disabling ISR, see commet below
The status is cleared immediately after reading, above. We hold
the status value so we can act on the current state of the FIFOs.
>> +
>> + drv_data->message->status = -EIO;
>> + complete(&drv_data->completion);
>> +
>> + return IRQ_HANDLED;
>> + }
>> +
>> + /* Drain the RX FIFO first, then transmit what we can */
>> + rx_done = k1_spi_read(drv_data);
>> + tx_done = k1_spi_write(drv_data);
>> +
>> + /* Disable interrupts if we're done transferring either direction */
>> + if (rx_done || tx_done) {
>> + /* If both are done, disable all interrupts */
>> + if (rx_done && tx_done) {
>> + val = 0;
>> + } else {
>> + val = readl(drv_data->base + SSP_INT_EN);
>> + if (rx_done)
>> + val &= ~(SSP_INT_EN_TINTE | SSP_INT_EN_RIE);
>> + if (tx_done)
>> + val &= ~SSP_INT_EN_TIE;
>> + }
>> + writel(val, drv_data->base + SSP_INT_EN);
>> + }
> It occur to me, enabling/disabling interrupt in trasfer_start()/ISR is
> unnecessary, which bring extra overhead, why not enable them once
> and only handle status clear bit? I mean bits has "R/W1C" in SSP_STATUS
Disabling the TX interrupt when we are done sending means we
won't get a pointless "more room in the FIFO" interrupt.
Disabling the RX interrupt when we have received what we want
means we won't get interrupted again, even if (for some reason)
there is more in the FIFO to consume.
I think this is OK.
-Alex
>> +
>> + if (rx_done && tx_done)
>> + complete(&drv_data->completion);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static int k1_spi_probe(struct platform_device *pdev)
>> +{
>> + struct k1_spi_driver_data *drv_data;
>> + struct device *dev = &pdev->dev;
>> + struct reset_control *reset;
>> + struct spi_controller *host;
>> + struct resource *iores;
>> + struct clk *clk_bus;
>> + int ret;
>> +
>> + host = devm_spi_alloc_host(dev, sizeof(*drv_data));
>> + if (!host)
>> + return -ENOMEM;
>> + drv_data = spi_controller_get_devdata(host);
>> + drv_data->controller = host;
>> + platform_set_drvdata(pdev, drv_data);
>> + drv_data->dev = dev;
>> + init_completion(&drv_data->completion);
>> +
>> + drv_data->base = devm_platform_get_and_ioremap_resource(pdev, 0,
>> + &iores);
>> + if (IS_ERR(drv_data->base))
>> + return dev_err_probe(dev, PTR_ERR(drv_data->base),
>> + "error mapping memory\n");
>> + drv_data->base_addr = iores->start;
>> +
>> + ret = devm_k1_spi_dma_setup(drv_data);
>> + if (ret)
>> + return dev_err_probe(dev, ret, "error setting up DMA\n");
>> +
>> + k1_spi_host_init(drv_data);
>> +
>> + clk_bus = devm_clk_get_enabled(dev, "bus");
>> + if (IS_ERR(clk_bus))
>> + return dev_err_probe(dev, PTR_ERR(clk_bus),
>> + "error getting/enabling bus clock\n");
>> + drv_data->bus_rate = clk_get_rate(clk_bus);
>> +
>> + drv_data->clk = devm_clk_get_enabled(dev, "core");
>> + if (IS_ERR(drv_data->clk))
>> + return dev_err_probe(dev, PTR_ERR(drv_data->clk),
>> + "error getting/enabling core clock\n");
>> +
>> + reset = devm_reset_control_get_exclusive_deasserted(dev, NULL);
>> + if (IS_ERR(reset))
>> + return dev_err_probe(dev, PTR_ERR(reset),
>> + "error getting/deasserting reset\n");
>> +
>> + k1_spi_register_reset(drv_data, true);
>> +
>> + drv_data->irq = platform_get_irq(pdev, 0);
>> + if (drv_data->irq < 0)
>> + return dev_err_probe(dev, drv_data->irq, "error getting IRQ\n");
>> +
>> + ret = devm_request_irq(dev, drv_data->irq, k1_spi_ssp_isr,
>> + IRQF_SHARED, dev_name(dev), drv_data);
>> + if (ret < 0)
>> + return dev_err_probe(dev, ret, "error requesting IRQ\n");
>> +
>> + ret = devm_spi_register_controller(dev, host);
>> + if (ret)
>> + dev_err(dev, "error registering controller\n");
>> +
>> + return ret;
>> +}
>> +
>> +static void k1_spi_remove(struct platform_device *pdev)
>> +{
>> + struct k1_spi_driver_data *drv_data = platform_get_drvdata(pdev);
>> +
>> + k1_spi_register_reset(drv_data, false);
>> +}
>> +
>> +static struct platform_driver k1_spi_driver = {
>> + .driver = {
>> + .name = "k1-spi",
>> + .of_match_table = k1_spi_dt_ids,
>> + },
>> + .probe = k1_spi_probe,
>> + .remove = k1_spi_remove,
>> +};
>> +
>> +module_platform_driver(k1_spi_driver);
>> +
>> +MODULE_DESCRIPTION("SpacemiT K1 SPI controller driver");
>> +MODULE_LICENSE("GPL");
>> --
>> 2.48.1
>>
>
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
next prev parent reply other threads:[~2025-09-23 12:49 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-22 16:17 [PATCH v3 0/3] spi: support the SpacemiT K1 SPI controller Alex Elder
2025-09-22 16:17 ` [PATCH v3 1/3] dt-bindings: spi: add SpacemiT K1 SPI support Alex Elder
2025-09-22 16:17 ` [PATCH v3 2/3] spi: spacemit: introduce SpacemiT K1 SPI controller driver Alex Elder
2025-09-22 23:06 ` Yixun Lan
2025-09-23 8:27 ` Mark Brown
2025-09-23 12:49 ` Alex Elder [this message]
2025-09-28 12:36 ` Yixun Lan
2025-09-28 18:30 ` Alex Elder
2025-09-22 16:17 ` [PATCH v3 3/3] riscv: dts: spacemit: define a SPI controller node Alex Elder
2025-09-23 0:19 ` Yixun Lan
2025-09-23 2:59 ` Troy Mitchell
2025-09-23 6:31 ` Junhui Liu
2025-09-24 3:11 ` Troy Mitchell
2025-09-23 12:49 ` Alex Elder
2025-09-24 3:10 ` Troy Mitchell
2025-09-23 12:49 ` Alex Elder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=786f4a5e-f62e-4cd0-a017-7b61408f34aa@riscstar.com \
--to=elder@riscstar.com \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=broonie@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dlan@gentoo.org \
--cc=krzk+dt@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux-spi@vger.kernel.org \
--cc=p.zabel@pengutronix.de \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=robh@kernel.org \
--cc=spacemit@lists.linux.dev \
--cc=ziyao@disroot.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox