diff mbox series

[2/6] spi: rockchip: Preset cs-high and clk polarity in setup progress

Message ID 20220211034344.4130-2-jon.lin@rock-chips.com (mailing list archive)
State New, archived
Headers show
Series [1/6] spi: rockchip: Stop spi slave dma receiver when cs inactive | expand

Commit Message

Jon Lin Feb. 11, 2022, 3:43 a.m. UTC
After power up, the cs and clock is in default status, and the cs-high
and clock polarity dts property configuration will take no effect until
the calling of rockchip_spi_config in the first transmission.
So preset them to make sure a correct voltage before the first
transmission coming.

Signed-off-by: Jon Lin <jon.lin@rock-chips.com>
---

 drivers/spi/spi-rockchip.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Comments

Mark Brown Feb. 11, 2022, 11:24 a.m. UTC | #1
On Fri, Feb 11, 2022 at 11:43:38AM +0800, Jon Lin wrote:

> +static int rockchip_spi_setup(struct spi_device *spi)
> +{
> +	struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller);
> +	u32 cr0;
> +
> +	pm_runtime_get_sync(rs->dev);
> +
> +	cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0);
> +
> +	cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET);
> +	if (spi->mode & SPI_CS_HIGH)
> +		cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;

What ensures that this read/modify/write doesn't race with a transfer
running on another client device in the case where the controller has
more than one device connected?  Similarly with the mode, though it's
not great to have devices with different modes connected to a single
controller.
Mark Brown Feb. 14, 2022, 12:49 p.m. UTC | #2
On Mon, Feb 14, 2022 at 04:40:19PM +0800, Jon Lin wrote:
> 在 2022/2/11 19:24, Mark Brown 写道:

> > > +   cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET);
> > > +   if (spi->mode & SPI_CS_HIGH)
> > > +           cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;

> > What ensures that this read/modify/write doesn't race with a transfer
> > running on another client device in the case where the controller has
> > more than one device connected?  Similarly with the mode, though it's
> > not great to have devices with different modes connected to a single
> > controller.

> I have no idea how to deal with the conflict configuration between
> different cs, and also I find nothing strategy in others spi drivers.
> As we all know, some configurations should be consistent for different
> CS devices, such as SPI_CPOL, so I suggest the framework to make
> corresponding early warning prompts.

As covered in the documentation setup() for one device may run while
another is active, therefore if multiple devices are configured in the
same register you should use a lock to ensure there can't be multiple
writes.  Note that the above appears to not just be setting the mode but
also the chip select so if you've got two SPI_CS_HIGH devices then
they'll both be going in and separately setting cr0.
Mark Brown Feb. 15, 2022, 12:36 p.m. UTC | #3
On Tue, Feb 15, 2022 at 11:00:54AM +0800, Jon Lin wrote:
> 在 2022/2/14 20:49, Mark Brown 写道:

> > As covered in the documentation setup() for one device may run while
> > another is active, therefore if multiple devices are configured in the
> > same register you should use a lock to ensure there can't be multiple
> > writes.  Note that the above appears to not just be setting the mode but
> > also the chip select so if you've got two SPI_CS_HIGH devices then
> > they'll both be going in and separately setting cr0.

> Is the io_mutex in function spi_setup is good enough?

It's not supposed to be for that but looking at the code quickly I
*think* setup() is never called with io_mutex held so it might well be
fine - you should double check though.  If not you'd need to add another
lock in your driver data.
Jon Lin Feb. 16, 2022, 1:23 a.m. UTC | #4
在 2022/2/15 20:36, Mark Brown 写道:
> On Tue, Feb 15, 2022 at 11:00:54AM +0800, Jon Lin wrote:
>> 在 2022/2/14 20:49, Mark Brown 写道:
> 
>>> As covered in the documentation setup() for one device may run while
>>> another is active, therefore if multiple devices are configured in the
>>> same register you should use a lock to ensure there can't be multiple
>>> writes.  Note that the above appears to not just be setting the mode but
>>> also the chip select so if you've got two SPI_CS_HIGH devices then
>>> they'll both be going in and separately setting cr0.
> 
>> Is the io_mutex in function spi_setup is good enough?
> 
> It's not supposed to be for that but looking at the code quickly I
> *think* setup() is never called with io_mutex held so it might well be
> fine - you should double check though.  If not you'd need to add another
> lock in your driver data.

》setup() is never called with io_mutex held
I think so. and I think the io_mutex is enough for me.
diff mbox series

Patch

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 7ac07569e103..1738a2611a2b 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -711,6 +711,26 @@  static bool rockchip_spi_can_dma(struct spi_controller *ctlr,
 	return xfer->len / bytes_per_word >= rs->fifo_len;
 }
 
+static int rockchip_spi_setup(struct spi_device *spi)
+{
+	struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller);
+	u32 cr0;
+
+	pm_runtime_get_sync(rs->dev);
+
+	cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+	cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET);
+	if (spi->mode & SPI_CS_HIGH)
+		cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET;
+
+	writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
+
+	pm_runtime_put(rs->dev);
+
+	return 0;
+}
+
 static int rockchip_spi_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -837,6 +857,7 @@  static int rockchip_spi_probe(struct platform_device *pdev)
 	ctlr->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX;
 	ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT);
 
+	ctlr->setup = rockchip_spi_setup;
 	ctlr->set_cs = rockchip_spi_set_cs;
 	ctlr->transfer_one = rockchip_spi_transfer_one;
 	ctlr->max_transfer_size = rockchip_spi_max_transfer_size;