linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] firmware: xilinx: Clear IOCTL_SET_SD_TAPDELAY using PM_MMIO_WRITE
@ 2022-10-20 20:02 Marek Vasut
  2022-12-15 11:43 ` Michal Simek
  0 siblings, 1 reply; 2+ messages in thread
From: Marek Vasut @ 2022-10-20 20:02 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Marek Vasut, Abhyuday Godhasara, Harsha, Michal Simek,
	Rajan Vaja, Ronak Jain, Tanmay Shah

In case the tap delay required by Arasan SDHCI is set to 0, the current
embeddedsw firmware unconditionally writes IOU_SLCR SD_ITAPDLY to 0x100
(SD0_ITAPDLYENA=1, SD0_ITAPDLYSEL=0). Previous behavior was to keep the
IOU_SLCR SD_ITAPDLY set to 0x0. There is some sort of difference in the
behavior between SD0_ITAPDLYENA=1/0 with the same SD0_ITAPDLYSEL=0, even
though the behavior should be identical -- zero delay added to rxclk_in
line. The former breaks HS200 training in low temperature conditions.

Write IOU_SLCR SD_ITAPDLY register to 0 using PM_MMIO_WRITE which seem
to allow unrestricted WRITE access (and PM_MMIO_READ which allows read
access) to the entire address space. This way, it is possible to work
around the defect in IOCTL_SET_SD_TAPDELAY design which does not permit
clearing SDx_ITAPDLYENA bit.

Note that the embeddedsw firmware does not permit clearing the SD_ITAPDLY
SD0_ITAPDLYENA bit, this bit can only ever be set by the firmware and it
is often impossible to update the possibly broken firmware.

Signed-off-by: Marek Vasut <marex@denx.de>
---
Cc: Abhyuday Godhasara <abhyuday.godhasara@xilinx.com>
Cc: Harsha <harsha.harsha@xilinx.com>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Rajan Vaja <rajan.vaja@xilinx.com>
Cc: Ronak Jain <ronak.jain@xilinx.com>
Cc: Tanmay Shah <tanmay.shah@xilinx.com>
To: linux-arm-kernel@lists.infradead.org
---
V2: - Use PM_MMIO_WRITE to clear SD_xTAPDLYx bitfields and work around
      the IOCTL_SET_SD_TAPDELAY design defect.
    - Update commit message accordingly.
---
 drivers/firmware/xilinx/zynqmp.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 6bc6b6c84241c..c0ff3efd321fc 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -738,8 +738,33 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
  */
 int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
 {
-	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
-				   type, value, NULL);
+#define SD_ITAPDLY	0xFF180314
+#define SD_OTAPDLYSEL	0xFF180318
+	u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL;
+	u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16);
+
+	if (value) {
+		return zynqmp_pm_invoke_fn(PM_IOCTL, node_id,
+					   IOCTL_SET_SD_TAPDELAY,
+					   type, value, NULL);
+	}
+
+	/*
+	 * Work around completely misdesigned firmware API on Xilinx ZynqMP.
+	 * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only
+	 * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA
+	 * bits, but there is no matching call to clear those bits. If those
+	 * bits are not cleared, SDMMC tuning may fail.
+	 *
+	 * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to
+	 * allow complete unrestricted access to all address space, including
+	 * IOU_SLCR SD_ITAPDLY Register and all the other registers, access
+	 * to which was supposed to be protected by the current firmware API.
+	 *
+	 * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter
+	 * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits.
+	 */
+	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, reg, mask, 0, 0, NULL);
 }
 EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
 
-- 
2.35.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] firmware: xilinx: Clear IOCTL_SET_SD_TAPDELAY using PM_MMIO_WRITE
  2022-10-20 20:02 [PATCH v2] firmware: xilinx: Clear IOCTL_SET_SD_TAPDELAY using PM_MMIO_WRITE Marek Vasut
@ 2022-12-15 11:43 ` Michal Simek
  0 siblings, 0 replies; 2+ messages in thread
From: Michal Simek @ 2022-12-15 11:43 UTC (permalink / raw)
  To: Marek Vasut, linux-arm-kernel, Sai Krishna Potthuri
  Cc: Abhyuday Godhasara, Harsha, Rajan Vaja, Ronak Jain, Tanmay Shah



On 10/20/22 22:02, Marek Vasut wrote:
> In case the tap delay required by Arasan SDHCI is set to 0, the current
> embeddedsw firmware unconditionally writes IOU_SLCR SD_ITAPDLY to 0x100
> (SD0_ITAPDLYENA=1, SD0_ITAPDLYSEL=0). Previous behavior was to keep the
> IOU_SLCR SD_ITAPDLY set to 0x0. There is some sort of difference in the
> behavior between SD0_ITAPDLYENA=1/0 with the same SD0_ITAPDLYSEL=0, even
> though the behavior should be identical -- zero delay added to rxclk_in
> line. The former breaks HS200 training in low temperature conditions.
> 
> Write IOU_SLCR SD_ITAPDLY register to 0 using PM_MMIO_WRITE which seem
> to allow unrestricted WRITE access (and PM_MMIO_READ which allows read
> access) to the entire address space. This way, it is possible to work
> around the defect in IOCTL_SET_SD_TAPDELAY design which does not permit
> clearing SDx_ITAPDLYENA bit.
> 
> Note that the embeddedsw firmware does not permit clearing the SD_ITAPDLY
> SD0_ITAPDLYENA bit, this bit can only ever be set by the firmware and it
> is often impossible to update the possibly broken firmware.
> 
> Signed-off-by: Marek Vasut <marex@denx.de>
> ---
> Cc: Abhyuday Godhasara <abhyuday.godhasara@xilinx.com>
> Cc: Harsha <harsha.harsha@xilinx.com>
> Cc: Michal Simek <michal.simek@amd.com>
> Cc: Rajan Vaja <rajan.vaja@xilinx.com>
> Cc: Ronak Jain <ronak.jain@xilinx.com>
> Cc: Tanmay Shah <tanmay.shah@xilinx.com>
> To: linux-arm-kernel@lists.infradead.org
> ---
> V2: - Use PM_MMIO_WRITE to clear SD_xTAPDLYx bitfields and work around
>        the IOCTL_SET_SD_TAPDELAY design defect.
>      - Update commit message accordingly.
> ---
>   drivers/firmware/xilinx/zynqmp.c | 29 +++++++++++++++++++++++++++--
>   1 file changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
> index 6bc6b6c84241c..c0ff3efd321fc 100644
> --- a/drivers/firmware/xilinx/zynqmp.c
> +++ b/drivers/firmware/xilinx/zynqmp.c
> @@ -738,8 +738,33 @@ EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
>    */
>   int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
>   {
> -	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
> -				   type, value, NULL);
> +#define SD_ITAPDLY	0xFF180314
> +#define SD_OTAPDLYSEL	0xFF180318

These two macros should go to include/linux/firmware/xlnx-zynqmp.h


> +	u32 reg = (type == PM_TAPDELAY_INPUT) ? SD_ITAPDLY : SD_OTAPDLYSEL;
> +	u32 mask = (node_id == NODE_SD_0) ? GENMASK(15, 0) : GENMASK(31, 16);
> +
> +	if (value) {
> +		return zynqmp_pm_invoke_fn(PM_IOCTL, node_id,
> +					   IOCTL_SET_SD_TAPDELAY,
> +					   type, value, NULL);
> +	}
> +
> +	/*
> +	 * Work around completely misdesigned firmware API on Xilinx ZynqMP.
> +	 * The IOCTL_SET_SD_TAPDELAY firmware call allows the caller to only
> +	 * ever set IOU_SLCR SD_ITAPDLY Register SD0_ITAPDLYENA/SD1_ITAPDLYENA
> +	 * bits, but there is no matching call to clear those bits. If those
> +	 * bits are not cleared, SDMMC tuning may fail.
> +	 *
> +	 * Luckily, there are PM_MMIO_READ/PM_MMIO_WRITE calls which seem to
> +	 * allow complete unrestricted access to all address space, including
> +	 * IOU_SLCR SD_ITAPDLY Register and all the other registers, access
> +	 * to which was supposed to be protected by the current firmware API.
> +	 *
> +	 * Use PM_MMIO_READ/PM_MMIO_WRITE to re-implement the missing counter
> +	 * part of IOCTL_SET_SD_TAPDELAY which clears SDx_ITAPDLYENA bits.
> +	 */
> +	return zynqmp_pm_invoke_fn(PM_MMIO_WRITE, reg, mask, 0, 0, NULL);
>   }
>   EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
>   

I am fine with this workaround. Just for the record the way forward is IMHO to 
deprecate the whole IOCTL_SET_SD_TAPDELAY and create new one 
IOCTL_SET_SD_TAPDELAY2 and use feature check interface to find it if new 
firmware provides it. If provides use it and don't get to PM_MMIO_WRITE 
interface. It is our plan of record that MMIO_READ/WRITE interface should be 
deprecated.

Once macro position is fixed I will queue it.

Thanks,
Michal

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-12-15 11:45 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-20 20:02 [PATCH v2] firmware: xilinx: Clear IOCTL_SET_SD_TAPDELAY using PM_MMIO_WRITE Marek Vasut
2022-12-15 11:43 ` Michal Simek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).