From: Greg Kroah-Hartman Date: Sat, 30 Dec 2023 11:13:44 +0000 (+0000) Subject: drop spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch X-Git-Tag: v6.1.70~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18ec544a0f3661e0f0f1e1cdf22586dc0a540de5;p=thirdparty%2Fkernel%2Fstable-queue.git drop spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch from 6.1 and 5.15 --- diff --git a/queue-5.15/series b/queue-5.15/series index 4b2e7c25deb..f69a618bbb5 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -55,7 +55,6 @@ net-9p-avoid-freeing-uninit-memory-in-p9pdu_vreadf.patch net-rfkill-gpio-set-gpio-direction.patch net-ks8851-fix-tx-stall-caused-by-tx-buffer-overrun.patch dt-bindings-nvmem-mxs-ocotp-document-fsl-ocotp.patch -spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch scsi-core-always-send-batch-on-reset-or-error-handling-command.patch tracing-synthetic-disable-events-after-testing-in-synth_event_gen_test_init.patch bus-ti-sysc-flush-posted-write-only-after-srst_udelay.patch diff --git a/queue-5.15/spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch b/queue-5.15/spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch deleted file mode 100644 index 2904f98def0..00000000000 --- a/queue-5.15/spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch +++ /dev/null @@ -1,241 +0,0 @@ -From fc70d643a2f6678cbe0f5c86433c1aeb4d613fcc Mon Sep 17 00:00:00 2001 -From: Louis Chauvet -Date: Mon, 4 Dec 2023 16:49:03 +0100 -Subject: spi: atmel: Fix clock issue when using devices with different polarities - -From: Louis Chauvet - -commit fc70d643a2f6678cbe0f5c86433c1aeb4d613fcc upstream. - -The current Atmel SPI controller driver (v2) behaves incorrectly when -using two SPI devices with different clock polarities and GPIO CS. - -When switching from one device to another, the controller driver first -enables the CS and then applies whatever configuration suits the targeted -device (typically, the polarities). The side effect of such order is the -apparition of a spurious clock edge after enabling the CS when the clock -polarity needs to be inverted wrt. the previous configuration of the -controller. - -This parasitic clock edge is problematic when the SPI device uses that edge -for internal processing, which is perfectly legitimate given that its CS -was asserted. Indeed, devices such as HVS8080 driven by driver gpio-sr in -the kernel are shift registers and will process this first clock edge to -perform a first register shift. In this case, the first bit gets lost and -the whole data block that will later be read by the kernel is all shifted -by one. - - Current behavior: - The actual switching of the clock polarity only occurs after the CS - when the controller sends the first message: - - CLK ------------\ /-\ /-\ - | | | | | . . . - \---/ \-/ \ - CS -----\ - | - \------------------ - - ^ ^ ^ - | | | - | | Actual clock of the message sent - | | - | Change of clock polarity, which occurs with the first - | write to the bus. This edge occurs when the CS is - | already asserted, and can be interpreted as - | the first clock edge by the receiver. - | - GPIO CS toggle - -This issue is specific to this controller because while the SPI core -performs the operations in the right order, the controller however does -not. In practice, the controller only applies the clock configuration right -before the first transmission. - -So this is not a problem when using the controller's dedicated CS, as the -controller does things correctly, but it becomes a problem when you need to -change the clock polarity and use an external GPIO for the CS. - -One possible approach to solve this problem is to send a dummy message -before actually activating the CS, so that the controller applies the clock -polarity beforehand. - -New behavior: - -CLK ------\ /-\ /-\ /-\ /-\ - | | | ... | | | | ... | | - \------/ \- -/ \------/ \- -/ \------ - -CS -\/-----------------------\ - || | - \/ \--------------------- - ^ ^ ^ ^ ^ - | | | | | - | | | | Expected clock cycles when - | | | | sending the message - | | | | - | | | Actual GPIO CS activation, occurs inside - | | | the driver - | | | - | | Dummy message, to trigger clock polarity - | | reconfiguration. This message is not received and - | | processed by the device because CS is low. - | | - | Change of clock polarity, forced by the dummy message. This - | time, the edge is not detected by the receiver. - | - This small spike in CS activation is due to the fact that the - spi-core activates the CS gpio before calling the driver's - set_cs callback, which deactivates this gpio again until the - clock polarity is correct. - -To avoid having to systematically send a dummy packet, the driver keeps -track of the clock's current polarity. In this way, it only sends the dummy -packet when necessary, ensuring that the clock will have the correct -polarity when the CS is toggled. - -There could be two hardware problems with this patch: -1- Maybe the small CS activation peak can confuse SPI devices -2- If on a design, a single wire is used to select two devices depending -on its state, the dummy message may disturb them. - -Fixes: 5ee36c989831 ("spi: atmel_spi update chipselect handling") -Cc: -Signed-off-by: Louis Chauvet -Link: https://msgid.link/r/20231204154903.11607-1-louis.chauvet@bootlin.com -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman ---- - drivers/spi/spi-atmel.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 81 insertions(+), 1 deletion(-) - ---- a/drivers/spi/spi-atmel.c -+++ b/drivers/spi/spi-atmel.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - - /* SPI register offsets */ -@@ -278,6 +279,7 @@ struct atmel_spi { - bool keep_cs; - - u32 fifo_size; -+ bool last_polarity; - u8 native_cs_free; - u8 native_cs_for_gpio; - }; -@@ -291,6 +293,22 @@ struct atmel_spi_device { - #define INVALID_DMA_ADDRESS 0xffffffff - - /* -+ * This frequency can be anything supported by the controller, but to avoid -+ * unnecessary delay, the highest possible frequency is chosen. -+ * -+ * This frequency is the highest possible which is not interfering with other -+ * chip select registers (see Note for Serial Clock Bit Rate configuration in -+ * Atmel-11121F-ATARM-SAMA5D3-Series-Datasheet_02-Feb-16, page 1283) -+ */ -+#define DUMMY_MSG_FREQUENCY 0x02 -+/* -+ * 8 bits is the minimum data the controller is capable of sending. -+ * -+ * This message can be anything as it should not be treated by any SPI device. -+ */ -+#define DUMMY_MSG 0xAA -+ -+/* - * Version 2 of the SPI controller has - * - CR.LASTXFER - * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) -@@ -304,6 +322,43 @@ static bool atmel_spi_is_v2(struct atmel - } - - /* -+ * Send a dummy message. -+ * -+ * This is sometimes needed when using a CS GPIO to force clock transition when -+ * switching between devices with different polarities. -+ */ -+static void atmel_spi_send_dummy(struct atmel_spi *as, struct spi_device *spi, int chip_select) -+{ -+ u32 status; -+ u32 csr; -+ -+ /* -+ * Set a clock frequency to allow sending message on SPI bus. -+ * The frequency here can be anything, but is needed for -+ * the controller to send the data. -+ */ -+ csr = spi_readl(as, CSR0 + 4 * chip_select); -+ csr = SPI_BFINS(SCBR, DUMMY_MSG_FREQUENCY, csr); -+ spi_writel(as, CSR0 + 4 * chip_select, csr); -+ -+ /* -+ * Read all data coming from SPI bus, needed to be able to send -+ * the message. -+ */ -+ spi_readl(as, RDR); -+ while (spi_readl(as, SR) & SPI_BIT(RDRF)) { -+ spi_readl(as, RDR); -+ cpu_relax(); -+ } -+ -+ spi_writel(as, TDR, DUMMY_MSG); -+ -+ readl_poll_timeout_atomic(as->regs + SPI_SR, status, -+ (status & SPI_BIT(TXEMPTY)), 1, 1000); -+} -+ -+ -+/* - * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby - * they assume that spi slave device state will not change on deselect, so - * that automagic deselection is OK. ("NPCSx rises if no data is to be -@@ -319,11 +374,17 @@ static bool atmel_spi_is_v2(struct atmel - * Master on Chip Select 0.") No workaround exists for that ... so for - * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH, - * and (c) will trigger that first erratum in some cases. -+ * -+ * When changing the clock polarity, the SPI controller waits for the next -+ * transmission to enforce the default clock state. This may be an issue when -+ * using a GPIO as Chip Select: the clock level is applied only when the first -+ * packet is sent, once the CS has already been asserted. The workaround is to -+ * avoid this by sending a first (dummy) message before toggling the CS state. - */ -- - static void cs_activate(struct atmel_spi *as, struct spi_device *spi) - { - struct atmel_spi_device *asd = spi->controller_state; -+ bool new_polarity; - int chip_select; - u32 mr; - -@@ -352,6 +413,25 @@ static void cs_activate(struct atmel_spi - } - - mr = spi_readl(as, MR); -+ -+ /* -+ * Ensures the clock polarity is valid before we actually -+ * assert the CS to avoid spurious clock edges to be -+ * processed by the spi devices. -+ */ -+ if (spi_get_csgpiod(spi, 0)) { -+ new_polarity = (asd->csr & SPI_BIT(CPOL)) != 0; -+ if (new_polarity != as->last_polarity) { -+ /* -+ * Need to disable the GPIO before sending the dummy -+ * message because it is already set by the spi core. -+ */ -+ gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), 0); -+ atmel_spi_send_dummy(as, spi, chip_select); -+ as->last_polarity = new_polarity; -+ gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), 1); -+ } -+ } - } else { - u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; - int i; diff --git a/queue-6.1/series b/queue-6.1/series index 45bf78282f1..bb0fe3fdcd8 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -93,7 +93,6 @@ btrfs-zoned-no-longer-count-fresh-bg-region-as-zone-.patch ubifs-fix-possible-dereference-after-free.patch ublk-move-ublk_cancel_dev-out-of-ub-mutex.patch selftests-mptcp-join-fix-subflow_send_ack-lookup.patch -spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch revert-scsi-aacraid-reply-queue-mapping-to-cpus-based-on-irq-affinity.patch scsi-core-always-send-batch-on-reset-or-error-handling-command.patch tracing-synthetic-disable-events-after-testing-in-synth_event_gen_test_init.patch diff --git a/queue-6.1/spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch b/queue-6.1/spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch deleted file mode 100644 index 2904f98def0..00000000000 --- a/queue-6.1/spi-atmel-fix-clock-issue-when-using-devices-with-different-polarities.patch +++ /dev/null @@ -1,241 +0,0 @@ -From fc70d643a2f6678cbe0f5c86433c1aeb4d613fcc Mon Sep 17 00:00:00 2001 -From: Louis Chauvet -Date: Mon, 4 Dec 2023 16:49:03 +0100 -Subject: spi: atmel: Fix clock issue when using devices with different polarities - -From: Louis Chauvet - -commit fc70d643a2f6678cbe0f5c86433c1aeb4d613fcc upstream. - -The current Atmel SPI controller driver (v2) behaves incorrectly when -using two SPI devices with different clock polarities and GPIO CS. - -When switching from one device to another, the controller driver first -enables the CS and then applies whatever configuration suits the targeted -device (typically, the polarities). The side effect of such order is the -apparition of a spurious clock edge after enabling the CS when the clock -polarity needs to be inverted wrt. the previous configuration of the -controller. - -This parasitic clock edge is problematic when the SPI device uses that edge -for internal processing, which is perfectly legitimate given that its CS -was asserted. Indeed, devices such as HVS8080 driven by driver gpio-sr in -the kernel are shift registers and will process this first clock edge to -perform a first register shift. In this case, the first bit gets lost and -the whole data block that will later be read by the kernel is all shifted -by one. - - Current behavior: - The actual switching of the clock polarity only occurs after the CS - when the controller sends the first message: - - CLK ------------\ /-\ /-\ - | | | | | . . . - \---/ \-/ \ - CS -----\ - | - \------------------ - - ^ ^ ^ - | | | - | | Actual clock of the message sent - | | - | Change of clock polarity, which occurs with the first - | write to the bus. This edge occurs when the CS is - | already asserted, and can be interpreted as - | the first clock edge by the receiver. - | - GPIO CS toggle - -This issue is specific to this controller because while the SPI core -performs the operations in the right order, the controller however does -not. In practice, the controller only applies the clock configuration right -before the first transmission. - -So this is not a problem when using the controller's dedicated CS, as the -controller does things correctly, but it becomes a problem when you need to -change the clock polarity and use an external GPIO for the CS. - -One possible approach to solve this problem is to send a dummy message -before actually activating the CS, so that the controller applies the clock -polarity beforehand. - -New behavior: - -CLK ------\ /-\ /-\ /-\ /-\ - | | | ... | | | | ... | | - \------/ \- -/ \------/ \- -/ \------ - -CS -\/-----------------------\ - || | - \/ \--------------------- - ^ ^ ^ ^ ^ - | | | | | - | | | | Expected clock cycles when - | | | | sending the message - | | | | - | | | Actual GPIO CS activation, occurs inside - | | | the driver - | | | - | | Dummy message, to trigger clock polarity - | | reconfiguration. This message is not received and - | | processed by the device because CS is low. - | | - | Change of clock polarity, forced by the dummy message. This - | time, the edge is not detected by the receiver. - | - This small spike in CS activation is due to the fact that the - spi-core activates the CS gpio before calling the driver's - set_cs callback, which deactivates this gpio again until the - clock polarity is correct. - -To avoid having to systematically send a dummy packet, the driver keeps -track of the clock's current polarity. In this way, it only sends the dummy -packet when necessary, ensuring that the clock will have the correct -polarity when the CS is toggled. - -There could be two hardware problems with this patch: -1- Maybe the small CS activation peak can confuse SPI devices -2- If on a design, a single wire is used to select two devices depending -on its state, the dummy message may disturb them. - -Fixes: 5ee36c989831 ("spi: atmel_spi update chipselect handling") -Cc: -Signed-off-by: Louis Chauvet -Link: https://msgid.link/r/20231204154903.11607-1-louis.chauvet@bootlin.com -Signed-off-by: Mark Brown -Signed-off-by: Greg Kroah-Hartman ---- - drivers/spi/spi-atmel.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 81 insertions(+), 1 deletion(-) - ---- a/drivers/spi/spi-atmel.c -+++ b/drivers/spi/spi-atmel.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - - /* SPI register offsets */ -@@ -278,6 +279,7 @@ struct atmel_spi { - bool keep_cs; - - u32 fifo_size; -+ bool last_polarity; - u8 native_cs_free; - u8 native_cs_for_gpio; - }; -@@ -291,6 +293,22 @@ struct atmel_spi_device { - #define INVALID_DMA_ADDRESS 0xffffffff - - /* -+ * This frequency can be anything supported by the controller, but to avoid -+ * unnecessary delay, the highest possible frequency is chosen. -+ * -+ * This frequency is the highest possible which is not interfering with other -+ * chip select registers (see Note for Serial Clock Bit Rate configuration in -+ * Atmel-11121F-ATARM-SAMA5D3-Series-Datasheet_02-Feb-16, page 1283) -+ */ -+#define DUMMY_MSG_FREQUENCY 0x02 -+/* -+ * 8 bits is the minimum data the controller is capable of sending. -+ * -+ * This message can be anything as it should not be treated by any SPI device. -+ */ -+#define DUMMY_MSG 0xAA -+ -+/* - * Version 2 of the SPI controller has - * - CR.LASTXFER - * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) -@@ -304,6 +322,43 @@ static bool atmel_spi_is_v2(struct atmel - } - - /* -+ * Send a dummy message. -+ * -+ * This is sometimes needed when using a CS GPIO to force clock transition when -+ * switching between devices with different polarities. -+ */ -+static void atmel_spi_send_dummy(struct atmel_spi *as, struct spi_device *spi, int chip_select) -+{ -+ u32 status; -+ u32 csr; -+ -+ /* -+ * Set a clock frequency to allow sending message on SPI bus. -+ * The frequency here can be anything, but is needed for -+ * the controller to send the data. -+ */ -+ csr = spi_readl(as, CSR0 + 4 * chip_select); -+ csr = SPI_BFINS(SCBR, DUMMY_MSG_FREQUENCY, csr); -+ spi_writel(as, CSR0 + 4 * chip_select, csr); -+ -+ /* -+ * Read all data coming from SPI bus, needed to be able to send -+ * the message. -+ */ -+ spi_readl(as, RDR); -+ while (spi_readl(as, SR) & SPI_BIT(RDRF)) { -+ spi_readl(as, RDR); -+ cpu_relax(); -+ } -+ -+ spi_writel(as, TDR, DUMMY_MSG); -+ -+ readl_poll_timeout_atomic(as->regs + SPI_SR, status, -+ (status & SPI_BIT(TXEMPTY)), 1, 1000); -+} -+ -+ -+/* - * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby - * they assume that spi slave device state will not change on deselect, so - * that automagic deselection is OK. ("NPCSx rises if no data is to be -@@ -319,11 +374,17 @@ static bool atmel_spi_is_v2(struct atmel - * Master on Chip Select 0.") No workaround exists for that ... so for - * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH, - * and (c) will trigger that first erratum in some cases. -+ * -+ * When changing the clock polarity, the SPI controller waits for the next -+ * transmission to enforce the default clock state. This may be an issue when -+ * using a GPIO as Chip Select: the clock level is applied only when the first -+ * packet is sent, once the CS has already been asserted. The workaround is to -+ * avoid this by sending a first (dummy) message before toggling the CS state. - */ -- - static void cs_activate(struct atmel_spi *as, struct spi_device *spi) - { - struct atmel_spi_device *asd = spi->controller_state; -+ bool new_polarity; - int chip_select; - u32 mr; - -@@ -352,6 +413,25 @@ static void cs_activate(struct atmel_spi - } - - mr = spi_readl(as, MR); -+ -+ /* -+ * Ensures the clock polarity is valid before we actually -+ * assert the CS to avoid spurious clock edges to be -+ * processed by the spi devices. -+ */ -+ if (spi_get_csgpiod(spi, 0)) { -+ new_polarity = (asd->csr & SPI_BIT(CPOL)) != 0; -+ if (new_polarity != as->last_polarity) { -+ /* -+ * Need to disable the GPIO before sending the dummy -+ * message because it is already set by the spi core. -+ */ -+ gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), 0); -+ atmel_spi_send_dummy(as, spi, chip_select); -+ as->last_polarity = new_polarity; -+ gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), 1); -+ } -+ } - } else { - u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0; - int i;