[PATCH 2/2] ARM: meson: add support for Libre Computer aml-s905d3-cc

2024-09-20 Thread Neil Armstrong
Add support for the Libre Computer aml-s905d3-cc "Solitude" board:
https://libre.computer/products/aml-s905d3-cc/

The Solitude board has a Credit Card form factor, similar to the
the previous "Le Potato" card, but with the Amlogic A311D SoC,
MIPI DSI and CSI connectors. PoE header and a single USB2 Type-C
connector replacing the microUSB one for power and USB 2.0.

The board has an embedded SPI NOR flash, and EFI Capsule support
is added.

The GUID is dynamically generated for the board, to get it:
=> efidebug capsule esrt

ESRT: fw_resource_count=1
ESRT: fw_resource_count_max=1
ESRT: fw_resource_version=1
[entry 0]==
ESRT: fw_class=4302C3CB-2502-5EFE-87E0-894A8A322893
ESRT: fw_type=unknown
ESRT: fw_version=0
ESRT: lowest_supported_fw_version=0
ESRT: capsule_flags=0
ESRT: last_attempt_version=0
ESRT: last_attempt_status=success


On the host (with the aml_encrypt_g12a result binary):
$ eficapsule --guid 4302C3CB-2502-5EFE-87E0-894A8A322893 -i 1 u-boot.bin 
u-boot.cap

On the board (from USB disk containing u-boot.cap at root):
=> load usb 0:1 $kernel_addr_r u-boot.cap
=> efidebug capsule update $kernel_addr_r

The binary will then be flashed on the SPI.

Signed-off-by: Neil Armstrong 
---
 .../dts/meson-sm1-s905d3-libretech-cc-u-boot.dtsi  |  15 +++
 board/libre-computer/aml-s905d3-cc/MAINTAINERS |   7 ++
 board/libre-computer/aml-s905d3-cc/Makefile|   6 ++
 board/libre-computer/aml-s905d3-cc/aml-s905d3-cc.c |  44 +
 configs/aml-s905d3-cc_defconfig| 108 +
 doc/board/amlogic/aml-s905d3-cc.rst|  46 +
 doc/board/amlogic/index.rst|   1 +
 7 files changed, 227 insertions(+)

diff --git a/arch/arm/dts/meson-sm1-s905d3-libretech-cc-u-boot.dtsi 
b/arch/arm/dts/meson-sm1-s905d3-libretech-cc-u-boot.dtsi
new file mode 100644
index 000..1c4f019120f
--- /dev/null
+++ b/arch/arm/dts/meson-sm1-s905d3-libretech-cc-u-boot.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Neil Armstrong 
+ */
+
+#include "meson-g12-common-u-boot.dtsi"
+
+&sd_emmc_c {
+   pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_4b_pins>, <&emmc_ds_pins>;
+   bus-width = <4>;
+};
+
+&spifc {
+   status = "okay";
+};
diff --git a/board/libre-computer/aml-s905d3-cc/MAINTAINERS 
b/board/libre-computer/aml-s905d3-cc/MAINTAINERS
new file mode 100644
index 000..4b75c815c07
--- /dev/null
+++ b/board/libre-computer/aml-s905d3-cc/MAINTAINERS
@@ -0,0 +1,7 @@
+LIBRE-COMPUTER AML-S905D3-CC
+M: Neil Armstrong 
+S: Maintained
+L: u-boot-amlo...@groups.io
+F: board/amlogic/aml-s905d3-cc/
+F: configs/aml-s905d3-cc_defconfig
+F: doc/board/amlogic/aml-s905d3-cc.rst
diff --git a/board/libre-computer/aml-s905d3-cc/Makefile 
b/board/libre-computer/aml-s905d3-cc/Makefile
new file mode 100644
index 000..7d2c41e6436
--- /dev/null
+++ b/board/libre-computer/aml-s905d3-cc/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 BayLibre, SAS
+# Author: Neil Armstrong 
+
+obj-y  := aml-s905d3-cc.o
diff --git a/board/libre-computer/aml-s905d3-cc/aml-s905d3-cc.c 
b/board/libre-computer/aml-s905d3-cc/aml-s905d3-cc.c
new file mode 100644
index 000..f641db5a494
--- /dev/null
+++ b/board/libre-computer/aml-s905d3-cc/aml-s905d3-cc.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct efi_fw_image fw_images[] = {
+   {
+   .fw_name = u"AML_S905D3_CC_BOOT",
+   .image_index = 1,
+   },
+};
+
+struct efi_capsule_update_info update_info = {
+   .dfu_string = "sf 0:0=u-boot-bin raw 0 0x1",
+   .num_images = ARRAY_SIZE(fw_images),
+   .images = fw_images,
+};
+
+
+#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+   if (strcmp(interface, "ram") == 0)
+   env_set("dfu_alt_info", "fitimage ram 0x0808 0x400");
+   else if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
+   env_set("dfu_alt_info", update_info.dfu_string);
+}
+#endif
+
+int misc_init_r(void)
+{
+   meson_generate_serial_ethaddr();
+
+   return 0;
+}
diff --git a/configs/aml-s905d3-cc_defconfig b/configs/aml-s905d3-cc_defconfig
new file mode 100644
index 000..a6e5d584c0a
--- /dev/null
+++ b/configs/aml-s905d3-cc_defconfig
@@ -0,0 +1,108 @@
+CONFIG_ARM=y
+CONFIG_SYS_VENDOR="libre-computer"
+CONFIG_SYS_BOARD="aml-s905d3-cc"
+CONFIG_ARCH_MESON=y
+CONFIG_TEXT_BASE=0x0100
+CONFIG_NR_DRAM

[PATCH 1/2] ARM: meson: add support for Libre Computer aml-a311d-cc

2024-09-20 Thread Neil Armstrong
Add support for the Libre Computer aml-a311d-cc "Alta" board:
https://libre.computer/products/aml-a311d-cc/

The Alta board has a Credit Card form factor, similar to the
the prvevious "Le Potato" card, but with the Amlogic A311D SoC,
MIPI DSI and CSI connectors. PoE header and a single USB2 Type-C
connector replacing the microUSB one for power and USB 2.0.

The board has an embedded SPI NOR flash, and EFI Capsule support
is added.

The GUID is dynamically generated for the board, to get it:
=> efidebug capsule esrt

ESRT: fw_resource_count=1
ESRT: fw_resource_count_max=1
ESRT: fw_resource_version=1
[entry 0]==
ESRT: fw_class=17E07D9D-4D91-53F4-8780-1D91F279C1A5
ESRT: fw_type=unknown
ESRT: fw_version=0
ESRT: lowest_supported_fw_version=0
ESRT: capsule_flags=0
ESRT: last_attempt_version=0
ESRT: last_attempt_status=success


On the host (with the aml_encrypt_g12a result binary):
$ eficapsule --guid 17E07D9D-4D91-53F4-8780-1D91F279C1A5 -i 1 u-boot.bin 
u-boot.cap

On the board (from USB disk containing u-boot.cap at root):
=> load usb 0:1 $kernel_addr_r u-boot.cap
=> efidebug capsule update $kernel_addr_r

The binary will then be flashed on the SPI.

Signed-off-by: Neil Armstrong 
---
 .../dts/meson-g12b-a311d-libretech-cc-u-boot.dtsi  |  15 +++
 board/libre-computer/aml-a311d-cc/MAINTAINERS  |   7 ++
 board/libre-computer/aml-a311d-cc/Makefile |   6 ++
 board/libre-computer/aml-a311d-cc/aml-a311d-cc.c   |  44 +
 configs/aml-a311d-cc_defconfig | 108 +
 doc/board/amlogic/aml-a311d-cc.rst |  46 +
 doc/board/amlogic/index.rst|   1 +
 7 files changed, 227 insertions(+)

diff --git a/arch/arm/dts/meson-g12b-a311d-libretech-cc-u-boot.dtsi 
b/arch/arm/dts/meson-g12b-a311d-libretech-cc-u-boot.dtsi
new file mode 100644
index 000..cbada739042
--- /dev/null
+++ b/arch/arm/dts/meson-g12b-a311d-libretech-cc-u-boot.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2023 Neil Armstrong 
+ */
+
+#include "meson-g12-common-u-boot.dtsi"
+
+&sd_emmc_c {
+   pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_4b_pins>;
+   bus-width = <4>;
+};
+
+&spifc {
+   status = "okay";
+};
diff --git a/board/libre-computer/aml-a311d-cc/MAINTAINERS 
b/board/libre-computer/aml-a311d-cc/MAINTAINERS
new file mode 100644
index 000..b4b77acd23b
--- /dev/null
+++ b/board/libre-computer/aml-a311d-cc/MAINTAINERS
@@ -0,0 +1,7 @@
+LIBRE-COMPUTER AML-A311D-CC
+M: Neil Armstrong 
+S: Maintained
+L: u-boot-amlo...@groups.io
+F: board/amlogic/aml-a311d-cc/
+F: configs/aml-a311d-cc_defconfig
+F: doc/board/amlogic/aml-a311d-cc.rst
diff --git a/board/libre-computer/aml-a311d-cc/Makefile 
b/board/libre-computer/aml-a311d-cc/Makefile
new file mode 100644
index 000..461955def3a
--- /dev/null
+++ b/board/libre-computer/aml-a311d-cc/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 BayLibre, SAS
+# Author: Neil Armstrong 
+
+obj-y  := aml-a311d-cc.o
diff --git a/board/libre-computer/aml-a311d-cc/aml-a311d-cc.c 
b/board/libre-computer/aml-a311d-cc/aml-a311d-cc.c
new file mode 100644
index 000..e45cfd5d8a3
--- /dev/null
+++ b/board/libre-computer/aml-a311d-cc/aml-a311d-cc.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct efi_fw_image fw_images[] = {
+   {
+   .fw_name = u"AML_A311D_CC_BOOT",
+   .image_index = 1,
+   },
+};
+
+struct efi_capsule_update_info update_info = {
+   .dfu_string = "sf 0:0=u-boot-bin raw 0 0x1",
+   .num_images = ARRAY_SIZE(fw_images),
+   .images = fw_images,
+};
+
+
+#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+   if (strcmp(interface, "ram") == 0)
+   env_set("dfu_alt_info", "fitimage ram 0x0808 0x400");
+   else if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
+   env_set("dfu_alt_info", update_info.dfu_string);
+}
+#endif
+
+int misc_init_r(void)
+{
+   meson_generate_serial_ethaddr();
+
+   return 0;
+}
diff --git a/configs/aml-a311d-cc_defconfig b/configs/aml-a311d-cc_defconfig
new file mode 100644
index 000..c8e22200419
--- /dev/null
+++ b/configs/aml-a311d-cc_defconfig
@@ -0,0 +1,108 @@
+CONFIG_ARM=y
+CONFIG_SYS_VENDOR="libre-computer"
+CONFIG_SYS_BOARD="aml-a311d-cc"
+CONFIG_ARCH_MESON=y
+CONFIG_TEXT_BASE=0x0100
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_

[PATCH 0/2] board: libre-computer: Add support for Libre Computer aml-a311d-cc & aml-s905d3-cc boards

2024-09-20 Thread Neil Armstrong
Add support for the Libre Computer aml-a311d-cc "Alta" & aml-s905d3-cc
"Solitude" boards:
https://libre.computer/products/aml-a311d-cc/
https://libre.computer/products/aml-s905d3-cc/

The Alta & Solitude boards have a Credit Card form factor, similar to the
the previous "Le Potato" card, but with the Amlogic A311D or S903D3 SoCS,
MIPI DSI and CSI connectors. PoE header and a single USB2 Type-C
connector replacing the microUSB one for power and USB 2.0.

The boards have an embedded SPI NOR flash, and EFI Capsule support
is added.

Signed-off-by: Neil Armstrong 
---
Neil Armstrong (2):
  ARM: meson: add support for Libre Computer aml-a311d-cc
  ARM: meson: add support for Libre Computer aml-s905d3-cc

 .../dts/meson-g12b-a311d-libretech-cc-u-boot.dtsi  |  15 +++
 .../dts/meson-sm1-s905d3-libretech-cc-u-boot.dtsi  |  15 +++
 board/libre-computer/aml-a311d-cc/MAINTAINERS  |   7 ++
 board/libre-computer/aml-a311d-cc/Makefile |   6 ++
 board/libre-computer/aml-a311d-cc/aml-a311d-cc.c   |  44 +
 board/libre-computer/aml-s905d3-cc/MAINTAINERS |   7 ++
 board/libre-computer/aml-s905d3-cc/Makefile|   6 ++
 board/libre-computer/aml-s905d3-cc/aml-s905d3-cc.c |  44 +
 configs/aml-a311d-cc_defconfig | 108 +
 configs/aml-s905d3-cc_defconfig| 108 +
 doc/board/amlogic/aml-a311d-cc.rst |  46 +
 doc/board/amlogic/aml-s905d3-cc.rst|  46 +
 doc/board/amlogic/index.rst|   2 +
 13 files changed, 454 insertions(+)
---
base-commit: 13fd7a17858e5f2555a1d68e4afa75fceda0dac0
change-id: 20240920-u-boot-topic-libre-computer-solitude-alta-c3b22cbd16df

Best regards,
-- 
Neil Armstrong 



Re: [PATCH v2 09/13] ufs: Sync possible UFS Quirks with Linux UFS driver

2024-09-20 Thread Neil Armstrong

On 20/09/2024 10:00, neil.armstr...@linaro.org wrote:

From: Bhupesh Sharma 

Sync u-boot UFS driver to add all possible UFS Quirks
as supported by Linux UFS driver as well.

Synced with include/ufs/ufshcd.h from Linux v6.11 release

Signed-off-by: Bhupesh Sharma 
Tested-by: Venkatesh Yadav Abbarapu 
---
  drivers/ufs/ufs.h | 193 +-
  1 file changed, 162 insertions(+), 31 deletions(-)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index 555f8a6857d..a1006b80e88 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -712,38 +712,169 @@ struct ufs_hba {
u32 version;
u32 intr_mask;
u32 quirks;
-/*
- * If UFS host controller is having issue in processing LCC (Line
- * Control Command) coming from device then enable this quirk.
- * When this quirk is enabled, host controller driver should disable
- * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
- * attribute of device to 0).
- */
-#define UFSHCD_QUIRK_BROKEN_LCCBIT(0)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * 64-bit addressing supported capability but it doesn't work.
- */
-#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  BIT(1)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * auto-hibernate capability but it's FASTAUTO only.
- */
-#define UFSHCD_QUIRK_HIBERN_FASTAUTO   BIT(2)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * 64-bit addressing supported capability but it doesn't work.
- */
-#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
  
-/*

- * This quirk needs to be enabled if the host controller has
- * auto-hibernate capability but it's FASTAUTO only.
- */
-#define UFSHCD_QUIRK_HIBERN_FASTAUTO   0x4
+enum ufshcd_quirks {
+   /* Interrupt aggregation support is broken */
+   UFSHCD_QUIRK_BROKEN_INTR_AGGR   = 1 << 0,
+
+   /*
+* delay before each dme command is required as the unipro
+* layer has shown instabilities
+*/
+   UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS  = 1 << 1,
+
+   /*
+* If UFS host controller is having issue in processing LCC (Line
+* Control Command) coming from device then enable this quirk.
+* When this quirk is enabled, host controller driver should disable
+* the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
+* attribute of device to 0).
+*/
+   UFSHCD_QUIRK_BROKEN_LCC = 1 << 2,
+
+   /*
+* The attribute PA_RXHSUNTERMCAP specifies whether or not the
+* inbound Link supports unterminated line in HS mode. Setting this
+* attribute to 1 fixes moving to HS gear.
+*/
+   UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP= 1 << 3,
+
+   /*
+* This quirk needs to be enabled if the host controller only allows
+* accessing the peer dme attributes in AUTO mode (FAST AUTO or
+* SLOW AUTO).
+*/
+   UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE  = 1 << 4,
+
+   /*
+* This quirk needs to be enabled if the host controller doesn't
+* advertise the correct version in UFS_VER register. If this quirk
+* is enabled, standard UFS host driver will call the vendor specific
+* ops (get_ufs_hci_version) to get the correct version.
+*/
+   UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5,
+
+   /*
+* Clear handling for transfer/task request list is just opposite.
+*/
+   UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR= 1 << 6,
+
+   /*
+* This quirk needs to be enabled if host controller doesn't allow
+* that the interrupt aggregation timer and counter are reset by s/w.
+*/
+   UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR   = 1 << 7,
+
+   /*
+* This quirks needs to be enabled if host controller cannot be
+* enabled via HCE register.
+*/
+   UFSHCI_QUIRK_BROKEN_HCE = 1 << 8,
+
+   /*
+* This quirk needs to be enabled if the host controller regards
+* resolution of the values of PRDTO and PRDTL in UTRD as byte.
+*/
+   UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9,
+
+   /*
+* This quirk needs to be enabled if the host controller reports
+* OCS FATAL ERROR with device error through sense data
+*/
+   UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 10,
+
+   /*
+* This quirk needs to be enabled if the host controller has
+* auto-hibernate capability but it doesn't work.
+*/
+   UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8= 1 << 11,
+
+   /*
+* This quirk needs to disable manual flush for write booster
+*/
+   UFSHC

[PATCH v2 13/13] MAINTAINERS: Add myself to the list of UFS maintainers

2024-09-20 Thread Neil Armstrong
Adding myself to continue Bhupesh's work to enhance and fix UFS
support in U-Boot, especially for Qualcomm SoCs, and help review
patches and maintain the UFS subsystem.

Reviewed-by: Neha Malcom Francis 
Tested-by: Venkatesh Yadav Abbarapu 
Signed-off-by: Neil Armstrong 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7ab39d91a55..14809c057c9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1707,6 +1707,7 @@ T:git 
https://source.denx.de/u-boot/custodians/u-boot-ubi.git
 F: drivers/mtd/ubi/
 
 UFS
+M: Neil Armstrong 
 M: Bhupesh Sharma 
 M: Neha Malcom Francis 
 S: Maintained

-- 
2.34.1



[PATCH v2 10/13] ufs: Add missing memory barriers

2024-09-20 Thread neil . armstrong
From: Bhupesh Sharma 

Add missing wmb() and mb() barriers in the u-boot UFS core
framework driver to allow registers updates to happen before
follow-up read operations.

This makes the barrier placement similar to the Linux UFS driver,
synced from the Linux v6.9 release.

Starting from the v6.10 release, the barriers were replaced with a register
read-back in [1], this will ported to u-boot in a second time.

[1] 
https://lore.kernel.org/all/20240329-ufs-reset-ensure-effect-before-delay-v5-0-181252004...@redhat.com/

Signed-off-by: Bhupesh Sharma 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 565a6af1404..5d4e5424358 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -432,6 +432,12 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
ufshcd_writel(hba, upper_32_bits((dma_addr_t)hba->utmrdl),
  REG_UTP_TASK_REQ_LIST_BASE_H);
 
+   /*
+* Make sure base address and interrupt setup are updated before
+* enabling the run/stop registers below.
+*/
+   wmb();
+
/*
 * UCRDY, UTMRLDY and UTRLRDY bits must be 1
 */
@@ -861,6 +867,9 @@ static int ufshcd_send_command(struct ufs_hba *hba, 
unsigned int task_tag)
 
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 
+   /* Make sure doorbell reg is updated before reading interrupt status */
+   wmb();
+
start = get_timer(0);
do {
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
@@ -1994,6 +2003,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct 
ufs_hba_ops *hba_ops)
  REG_INTERRUPT_STATUS);
ufshcd_writel(hba, 0, REG_INTERRUPT_ENABLE);
 
+   mb();
+
err = ufshcd_hba_enable(hba);
if (err) {
dev_err(hba->dev, "Host controller enable failed\n");

-- 
2.34.1



[PATCH v2 12/13] ufs: core: remove link_startup_again logic

2024-09-20 Thread Neil Armstrong
The link_startup_again logic was added in Linux to handle device
that were set in LinkDown state, which should not be the case since U-boot
doesn't set LinkDown state are init, and Linux sets the device active
in ufshcd_init() for the first link startup.

ufshcd_set_ufs_dev_active(hba) is called at ufshcd_init() right before
scheduling an ufshcd_async_scan that will call ufshcd_device_init() then 
ufshcd_link_startup().

The comment in probe says:
/*
 * We are assuming that device wasn't put in sleep/power-down
 * state exclusively during the boot stage before kernel.
 * This assumption helps avoid doing link startup twice during
 * ufshcd_probe_hba().
 */
we can assume the same from U-Boot.

While it worked to far, it breaks link startup for Qualcomm Controllers v5,
let's just remove the logic.

Tested-by: Venkatesh Yadav Abbarapu 
Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index d2df5c26f76..e34e4586224 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -462,9 +462,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
 {
int ret;
int retries = DME_LINKSTARTUP_RETRIES;
-   bool link_startup_again = true;
 
-link_startup:
do {
ufshcd_ops_link_startup_notify(hba, PRE_CHANGE);
 
@@ -490,12 +488,6 @@ link_startup:
/* failed to get the link up... retire */
goto out;
 
-   if (link_startup_again) {
-   link_startup_again = false;
-   retries = DME_LINKSTARTUP_RETRIES;
-   goto link_startup;
-   }
-
/* Mark that link is up in PWM-G1, 1-lane, SLOW-AUTO mode */
ufshcd_init_pwr_info(hba);
 

-- 
2.34.1



[PATCH v2 11/13] ufs: Fix debug message in 'ufs_start'

2024-09-20 Thread neil . armstrong
From: Bhupesh Sharma 

Minor typo fix and rewording of printf message
inside 'ufs_start' which announces the availability
of the UFS device.

Signed-off-by: Bhupesh Sharma 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 5d4e5424358..d2df5c26f76 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -1925,7 +1925,7 @@ int ufs_start(struct ufs_hba *hba)
return ret;
}
 
-   printf("Device at %s up at:", hba->dev->name);
+   debug("UFS Device %s is up!\n", hba->dev->name);
ufshcd_print_pwr_info(hba);
}
 

-- 
2.34.1



[PATCH v2 09/13] ufs: Sync possible UFS Quirks with Linux UFS driver

2024-09-20 Thread neil . armstrong
From: Bhupesh Sharma 

Sync u-boot UFS driver to add all possible UFS Quirks
as supported by Linux UFS driver as well.

Synced with include/ufs/ufshcd.h from Linux v6.11 release

Signed-off-by: Bhupesh Sharma 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.h | 193 +-
 1 file changed, 162 insertions(+), 31 deletions(-)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index 555f8a6857d..a1006b80e88 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -712,38 +712,169 @@ struct ufs_hba {
u32 version;
u32 intr_mask;
u32 quirks;
-/*
- * If UFS host controller is having issue in processing LCC (Line
- * Control Command) coming from device then enable this quirk.
- * When this quirk is enabled, host controller driver should disable
- * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
- * attribute of device to 0).
- */
-#define UFSHCD_QUIRK_BROKEN_LCCBIT(0)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * 64-bit addressing supported capability but it doesn't work.
- */
-#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  BIT(1)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * auto-hibernate capability but it's FASTAUTO only.
- */
-#define UFSHCD_QUIRK_HIBERN_FASTAUTO   BIT(2)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * 64-bit addressing supported capability but it doesn't work.
- */
-#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
 
-/*
- * This quirk needs to be enabled if the host controller has
- * auto-hibernate capability but it's FASTAUTO only.
- */
-#define UFSHCD_QUIRK_HIBERN_FASTAUTO   0x4
+enum ufshcd_quirks {
+   /* Interrupt aggregation support is broken */
+   UFSHCD_QUIRK_BROKEN_INTR_AGGR   = 1 << 0,
+
+   /*
+* delay before each dme command is required as the unipro
+* layer has shown instabilities
+*/
+   UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS  = 1 << 1,
+
+   /*
+* If UFS host controller is having issue in processing LCC (Line
+* Control Command) coming from device then enable this quirk.
+* When this quirk is enabled, host controller driver should disable
+* the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
+* attribute of device to 0).
+*/
+   UFSHCD_QUIRK_BROKEN_LCC = 1 << 2,
+
+   /*
+* The attribute PA_RXHSUNTERMCAP specifies whether or not the
+* inbound Link supports unterminated line in HS mode. Setting this
+* attribute to 1 fixes moving to HS gear.
+*/
+   UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP= 1 << 3,
+
+   /*
+* This quirk needs to be enabled if the host controller only allows
+* accessing the peer dme attributes in AUTO mode (FAST AUTO or
+* SLOW AUTO).
+*/
+   UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE  = 1 << 4,
+
+   /*
+* This quirk needs to be enabled if the host controller doesn't
+* advertise the correct version in UFS_VER register. If this quirk
+* is enabled, standard UFS host driver will call the vendor specific
+* ops (get_ufs_hci_version) to get the correct version.
+*/
+   UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5,
+
+   /*
+* Clear handling for transfer/task request list is just opposite.
+*/
+   UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR= 1 << 6,
+
+   /*
+* This quirk needs to be enabled if host controller doesn't allow
+* that the interrupt aggregation timer and counter are reset by s/w.
+*/
+   UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR   = 1 << 7,
+
+   /*
+* This quirks needs to be enabled if host controller cannot be
+* enabled via HCE register.
+*/
+   UFSHCI_QUIRK_BROKEN_HCE = 1 << 8,
+
+   /*
+* This quirk needs to be enabled if the host controller regards
+* resolution of the values of PRDTO and PRDTL in UTRD as byte.
+*/
+   UFSHCD_QUIRK_PRDT_BYTE_GRAN = 1 << 9,
+
+   /*
+* This quirk needs to be enabled if the host controller reports
+* OCS FATAL ERROR with device error through sense data
+*/
+   UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR = 1 << 10,
+
+   /*
+* This quirk needs to be enabled if the host controller has
+* auto-hibernate capability but it doesn't work.
+*/
+   UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8= 1 << 11,
+
+   /*
+* This quirk needs to disable manual flush for write booster
+*/
+   UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL  = 1 << 12,
+
+   

[PATCH v2 03/13] ufs: split flush and invalidate to only invalidate when required

2024-09-20 Thread Neil Armstrong
There is no need to flush and invalidate all data updated by the
driver, mainly because on ARM platforms flush also invalidates
the cachelines.

Split the function in two and add the appropriate cacheline
invalidates after the UFS DMA operation finishes to make sure
we read from memory.

Flushing then invalidating cacheline unaligned data causes data
corruption issues on Qualcomm platforms, and is largely unnecessary
anyway, so let's cleanup the cache operations.

Reviewed-by: Neha Malcom Francis 
Tested-by: Venkatesh Yadav Abbarapu 
Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 45 ++---
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 3d9a7d7ee12..5845fd694d3 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -696,17 +696,28 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_cache_flush_and_invalidate - Flush and invalidate cache
+ * ufshcd_cache_flush - Flush cache
  *
- * Flush and invalidate cache in aligned address..address+size range.
- * The invalidation is in place to avoid stale data in cache.
+ * Flush cache in aligned address..address+size range.
  */
-static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size)
+static void ufshcd_cache_flush(void *addr, unsigned long size)
 {
uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
 
flush_dcache_range(start_addr, end_addr);
+}
+
+/**
+ * ufshcd_cache_invalidate - Invalidate cache
+ *
+ * Invalidate cache in aligned address..address+size range.
+ */
+static void ufshcd_cache_invalidate(void *addr, unsigned long size)
+{
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
+
invalidate_dcache_range(start_addr, end_addr);
 }
 
@@ -754,7 +765,7 @@ static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
 
req_desc->prd_table_length = 0;
 
-   ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc));
+   ufshcd_cache_flush(req_desc, sizeof(*req_desc));
 }
 
 static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
@@ -785,13 +796,13 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
/* Copy the Descriptor */
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
memcpy(ucd_req_ptr + 1, query->descriptor, len);
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 2 * 
sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, 2 * sizeof(*ucd_req_ptr));
} else {
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 
sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
}
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba)
@@ -809,8 +820,8 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct 
ufs_hba *hba)
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 /**
@@ -877,6 +888,8 @@ static int ufshcd_send_command(struct ufs_hba *hba, 
unsigned int task_tag)
  */
 static inline int ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
 {
+   ufshcd_cache_invalidate(ucd_rsp_ptr, sizeof(*ucd_rsp_ptr));
+
return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24;
 }
 
@@ -888,6 +901,8 @@ static inline int ufshcd_get_tr_ocs(struct ufs_hba *hba)
 {
struct utp_transfer_req_desc *req_desc = hba->utrdl;
 
+   ufshcd_cache_invalidate(req_desc, sizeof(*req_desc));
+
return le32_to_cpu(req_desc->header.dword_2) & MASK_OCS;
 }
 
@@ -1437,8 +1452,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufs_hba *hba,
memcpy(ucd_req_ptr->sc.cdb, pccb->cmd, cdb_len);
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 static inline void prepare_prdt_desc(struct ufshcd_sg_entry *entry,
@@ -1461,7 +1476,7

[PATCH v2 08/13] ufs: Clear UECPA once due to LINERESET has happened during LINK_STARTUP

2024-09-20 Thread neil . armstrong
From: Bhupesh Sharma 

Clear UECPA once in u-boot UFS driver due to LINERESET has happened
during LINK_STARTUP. This makes the u-boot ufs driver behavior related
to UECPA similar to Linux UFS driver.

Ported from Linux kernel commit:
2355b66ed20c ("scsi: ufs: Handle LINERESET indication in err handler")

Signed-off-by: Bhupesh Sharma 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index d99dcdef7d0..565a6af1404 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -504,6 +504,8 @@ link_startup:
if (ret)
goto out;
 
+   /* Clear UECPA once due to LINERESET has happened during LINK_STARTUP */
+   ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
ret = ufshcd_make_hba_operational(hba);
 out:
if (ret)

-- 
2.34.1



[PATCH v2 05/13] ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS

2024-09-20 Thread neil . armstrong
From: Marek Vasut 

Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not
support 64-bit addressing.

Ported from Linux kernel commit
6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS")
with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.

Signed-off-by: Marek Vasut 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index 43042c294bb..c92f47d82b5 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -732,6 +732,12 @@ struct ufs_hba {
  */
 #define UFSHCD_QUIRK_HIBERN_FASTAUTO   BIT(2)
 
+/*
+ * This quirk needs to be enabled if the host controller has
+ * 64-bit addressing supported capability but it doesn't work.
+ */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
+
/* Virtual memory reference */
struct utp_transfer_cmd_desc *ucdl;
struct utp_transfer_req_desc *utrdl;

-- 
2.34.1



[PATCH v2 07/13] ufs/ufs.h: Add definition of 'ufshcd_rmwl()'

2024-09-20 Thread neil . armstrong
From: Bhupesh Sharma 

Add definition of 'ufshcd_rmwl()' helper function
which would be later used by Qualcomm UFS driver
to read-modify-write registers.

Ported from Linux kernel commits:
e785060ea3a1 ("ufs: definitions for phy interface")
cff91daf52d3 ("scsi: ufs: Fix kernel-doc syntax in ufshcd.h")

Signed-off-by: Bhupesh Sharma 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index b55c4a9e996..555f8a6857d 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -3,6 +3,7 @@
 #define __UFS_H
 
 #include 
+#include 
 #include "unipro.h"
 
 struct udevice;
@@ -933,6 +934,23 @@ enum {
 #define ufshcd_readl(hba, reg) \
readl((hba)->mmio_base + (reg))
 
+/**
+ * ufshcd_rmwl - perform read/modify/write for a controller register
+ * @hba: per adapter instance
+ * @mask: mask to apply on read value
+ * @val: actual value to write
+ * @reg: register address
+ */
+static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
+{
+   u32 tmp;
+
+   tmp = ufshcd_readl(hba, reg);
+   tmp &= ~mask;
+   tmp |= (val & mask);
+   ufshcd_writel(hba, tmp, reg);
+}
+
 /* UTRLRSR - UTP Transfer Request Run-Stop Register 60h */
 #define UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT 0x1
 

-- 
2.34.1



[PATCH v2 06/13] ufs: Add UFSHCD_QUIRK_HIBERN_FASTAUTO

2024-09-20 Thread neil . armstrong
From: Marek Vasut 

Add UFSHCD_QUIRK_HIBERN_FASTAUTO quirk for host controllers which supports
auto-hibernate the capability but only FASTAUTO mode.

Ported from Linux kernel commit
2f11bbc2c7f3 ("scsi: ufs: core: Add UFSHCD_QUIRK_HIBERN_FASTAUTO")

Signed-off-by: Marek Vasut 
Tested-by: Venkatesh Yadav Abbarapu 
---
 drivers/ufs/ufs.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index c92f47d82b5..b55c4a9e996 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -738,6 +738,12 @@ struct ufs_hba {
  */
 #define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
 
+/*
+ * This quirk needs to be enabled if the host controller has
+ * auto-hibernate capability but it's FASTAUTO only.
+ */
+#define UFSHCD_QUIRK_HIBERN_FASTAUTO   0x4
+
/* Virtual memory reference */
struct utp_transfer_cmd_desc *ucdl;
struct utp_transfer_req_desc *utrdl;

-- 
2.34.1



[PATCH v2 02/13] ufs: fix dcache flush and invalidate range calculation

2024-09-20 Thread Neil Armstrong
The current calculation will omit doing a flush/invalidate on the last
cacheline if the base address is not aligned with DMA_MINALIGN.

This causes commands failures and write corruptions on Qualcomm
platforms.

Reviewed-by: Neha Malcom Francis 
Tested-by: Venkatesh Yadav Abbarapu 
Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index e005cc90608..3d9a7d7ee12 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -703,11 +703,11 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
  */
 static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size)
 {
-   uintptr_t aaddr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
-   unsigned long asize = ALIGN(size, ARCH_DMA_MINALIGN);
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
 
-   flush_dcache_range(aaddr, aaddr + asize);
-   invalidate_dcache_range(aaddr, aaddr + asize);
+   flush_dcache_range(start_addr, end_addr);
+   invalidate_dcache_range(start_addr, end_addr);
 }
 
 /**
@@ -1466,13 +1466,13 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
struct scsi_cmd *pccb)
}
 
if (pccb->dma_dir == DMA_TO_DEVICE) {   /* Write to device */
-   flush_dcache_range(aaddr, aaddr +
-  ALIGN(datalen, ARCH_DMA_MINALIGN));
+   flush_dcache_range(aaddr,
+  ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
}
 
/* In any case, invalidate cache to avoid stale data in it. */
-   invalidate_dcache_range(aaddr, aaddr +
-   ALIGN(datalen, ARCH_DMA_MINALIGN));
+   invalidate_dcache_range(aaddr,
+   ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
 
table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY);
buf = pccb->pdata;

-- 
2.34.1



[PATCH v2 04/13] ufs: use dcache helpers for scsi_cmd data and only invalidate if necessary

2024-09-20 Thread Neil Armstrong
Now we have proper flush and invalidate helpers, we can use them
directly to operate on the scsi_cmd data.

Likewise, we do not need to flush then invalidate, just flush _or_
invalidate depending on the data direction.

Reviewed-by: Neha Malcom Francis 
Tested-by: Venkatesh Yadav Abbarapu 
Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 5845fd694d3..d99dcdef7d0 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -1468,7 +1468,6 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
struct scsi_cmd *pccb)
 {
struct utp_transfer_req_desc *req_desc = hba->utrdl;
struct ufshcd_sg_entry *prd_table = hba->ucd_prdt_ptr;
-   uintptr_t aaddr = (uintptr_t)(pccb->pdata) & ~(ARCH_DMA_MINALIGN - 1);
ulong datalen = pccb->datalen;
int table_length;
u8 *buf;
@@ -1480,15 +1479,6 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
struct scsi_cmd *pccb)
return;
}
 
-   if (pccb->dma_dir == DMA_TO_DEVICE) {   /* Write to device */
-   flush_dcache_range(aaddr,
-  ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
-   }
-
-   /* In any case, invalidate cache to avoid stale data in it. */
-   invalidate_dcache_range(aaddr,
-   ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
-
table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY);
buf = pccb->pdata;
i = table_length;
@@ -1517,8 +1507,12 @@ static int ufs_scsi_exec(struct udevice *scsi_dev, 
struct scsi_cmd *pccb)
ufshcd_prepare_utp_scsi_cmd_upiu(hba, pccb, upiu_flags);
prepare_prdt_table(hba, pccb);
 
+   ufshcd_cache_flush(pccb->pdata, pccb->datalen);
+
ufshcd_send_command(hba, TASK_TAG);
 
+   ufshcd_cache_invalidate(pccb->pdata, pccb->datalen);
+
ocs = ufshcd_get_tr_ocs(hba);
switch (ocs) {
case OCS_SUCCESS:

-- 
2.34.1



[PATCH v2 01/13] ufs: allocate descriptors with size aligned with DMA_MINALIGN

2024-09-20 Thread Neil Armstrong
Align the allocation size with DMA_MINALIGN to make sure we do not
flush/invalidate data from following allocations.

Reviewed-by: Neha Malcom Francis 
Tested-by: Venkatesh Yadav Abbarapu 
Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index be64bf971f1..e005cc90608 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -633,7 +633,9 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate one Transfer Request Descriptor
 * Should be aligned to 1k boundary.
 */
-   hba->utrdl = memalign(1024, sizeof(struct utp_transfer_req_desc));
+   hba->utrdl = memalign(1024,
+ ALIGN(sizeof(struct utp_transfer_req_desc),
+   ARCH_DMA_MINALIGN));
if (!hba->utrdl) {
dev_err(hba->dev, "Transfer Descriptor memory allocation 
failed\n");
return -ENOMEM;
@@ -642,7 +644,9 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate one Command Descriptor
 * Should be aligned to 1k boundary.
 */
-   hba->ucdl = memalign(1024, sizeof(struct utp_transfer_cmd_desc));
+   hba->ucdl = memalign(1024,
+ALIGN(sizeof(struct utp_transfer_cmd_desc),
+  ARCH_DMA_MINALIGN));
if (!hba->ucdl) {
dev_err(hba->dev, "Command descriptor memory allocation 
failed\n");
return -ENOMEM;

-- 
2.34.1



[PATCH v2 00/13] ufs: enhancements to support Qualcomm UFS controllers

2024-09-20 Thread Neil Armstrong
This serie regroups all the fixes and base enhancements required to
support the Qualcomm UFS controllers in U-Boot.

This syncs headers & defines from Linux, and includes 2 set of
fixes that were sent separately:
- ufs: core: remove link_startup_again logic
- ufs: properly fix cache operations

Without those 2 sets, UFS cannot initialize on Qualcomm controlers
since v5, and a numerous of Cache issues makes any UFS controller
fail to initialize.

Since UFS core hasn't changed for a while, and since UFS is core
technology for the Qualcomm SoCs, I volunteer maintaininig the
UFS subsystem if Bhupesh & Neha Malcom Francis are ok with that.

It has been reported to show regressions on:
- TI K3 platforms (j721s2, j721e, j7200, j784s4) [1]
- AMD platform (amd_versal2_virt_defconfig) [2]

[1] https://lore.kernel.org/all/38f599a8-7094-4a04-8ff6-96fc8b9d1...@ti.com/
[2] 
https://lore.kernel.org/all/sa1pr12mb869713ca620f99077b75ef0e98...@sa1pr12mb8697.namprd12.prod.outlook.com/

Signed-off-by: Neil Armstrong 
---
Changes in v2:
- Added review and tested-by tags
- Updated patch 12 message with more explanations
- Synced patch 9 again with Linux 6.11
- Updated patches 7, 8, 9 and 10 with informations about the origins of the 
changes
- Link to v1: 
https://lore.kernel.org/r/20240910-topic-ufs-enhancements-v1-0-3ee0bffac...@linaro.org

---
Bhupesh Sharma (5):
  ufs/ufs.h: Add definition of 'ufshcd_rmwl()'
  ufs: Clear UECPA once due to LINERESET has happened during LINK_STARTUP
  ufs: Sync possible UFS Quirks with Linux UFS driver
  ufs: Add missing memory barriers
  ufs: Fix debug message in 'ufs_start'

Marek Vasut (2):
  ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS
  ufs: Add UFSHCD_QUIRK_HIBERN_FASTAUTO

Neil Armstrong (6):
  ufs: allocate descriptors with size aligned with DMA_MINALIGN
  ufs: fix dcache flush and invalidate range calculation
  ufs: split flush and invalidate to only invalidate when required
  ufs: use dcache helpers for scsi_cmd data and only invalidate if necessary
  ufs: core: remove link_startup_again logic
  MAINTAINERS: Add myself to the list of UFS maintainers

 MAINTAINERS   |   1 +
 drivers/ufs/ufs.c |  98 ---
 drivers/ufs/ufs.h | 199 --
 3 files changed, 239 insertions(+), 59 deletions(-)
---
base-commit: 24961c0e0444d3ed534ffc6a173e6ea636ca116b
change-id: 20240910-topic-ufs-enhancements-fe8ef9ce39d8

Best regards,
-- 
Neil Armstrong 



Re: [PATCH v2 1/3] ufs: add support for DesignWare Controller

2024-09-20 Thread neil . armstrong
LKDIV_DIV_125);
+   } else { /* POST_CHANGE */
+   err = ufshcd_dwc_link_is_up(hba);
+   if (err) {
+   dev_err(hba->dev, "Link is not up\n");
+   return err;
+   }
+
+   err = ufshcd_dwc_connection_setup(hba);
+   if (err)
+   dev_err(hba->dev, "Connection setup failed (%d)\n",
+   err);
+   }
+
+   return err;
+}
diff --git a/drivers/ufs/ufshcd-dwc.h b/drivers/ufs/ufshcd-dwc.h
new file mode 100644
index 00..d997045d3c
--- /dev/null
+++ b/drivers/ufs/ufshcd-dwc.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * UFS Host driver for Synopsys Designware Core
+ *
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Authors: Joao Pinto 
+ */
+
+#ifndef _UFSHCD_DWC_H
+#define _UFSHCD_DWC_H
+
+struct ufshcd_dme_attr_val {
+   u32 attr_sel;
+   u32 mib_val;
+   u8 peer;
+};
+
+int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba,
+  enum ufs_notify_change_status status);
+int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
+const struct ufshcd_dme_attr_val *v, int n);
+#endif /* End of Header */
diff --git a/drivers/ufs/ufshci-dwc.h b/drivers/ufs/ufshci-dwc.h
new file mode 100644
index 00..9e24c230c6
--- /dev/null
+++ b/drivers/ufs/ufshci-dwc.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * UFS Host driver for Synopsys Designware Core
+ *
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Authors: Joao Pinto 
+ */
+
+#ifndef _UFSHCI_DWC_H
+#define _UFSHCI_DWC_H
+
+/* DWC HC UFSHCI specific Registers */
+enum dwc_specific_registers {
+   DWC_UFS_REG_HCLKDIV = 0xFC,
+};
+
+/* Clock Divider Values: Hex equivalent of frequency in MHz */
+enum clk_div_values {
+   DWC_UFS_REG_HCLKDIV_DIV_62_5= 0x3e,
+   DWC_UFS_REG_HCLKDIV_DIV_125 = 0x7d,
+   DWC_UFS_REG_HCLKDIV_DIV_200 = 0xc8,
+};
+
+/* Selector Index */
+enum selector_index {
+   SELIND_LN0_TX   = 0x00,
+   SELIND_LN1_TX   = 0x01,
+   SELIND_LN0_RX   = 0x04,
+   SELIND_LN1_RX   = 0x05,
+};
+#endif


Reviewed-by: Neil Armstrong 


Re: [PATCH 2/3] ufs: ufs-amd-versal2: Add support for AMD UFS controller

2024-09-19 Thread neil . armstrong
 |= SRAM_CSR_BYPASS_MASK;
+   } else {
+   dev_err(hba->dev, "Invalid phy-mode %d.\n", 
priv->phy_mode);
+   return -EINVAL;
+   }
+
+   ret = versal2_pm_ufs_sram_csr_sel(priv->pd_dev_id,
+ PM_UFS_SRAM_CSR_WRITE, 
&sram_csr);
+   if (ret)
+   return ret;
+
+   /* De Assert RST_UFS Reset for UFS block in PMX_IOU */
+   ret = reset_deassert(priv->rstc);
+   if (ret)
+   dev_err(hba->dev, "ufshc reset deassert failed, err = 
%d\n", ret);
+
+   break;
+   case POST_CHANGE:
+   ret = ufs_versal2_phy_init(hba);
+   if (ret)
+   dev_err(hba->dev, "Phy init failed (%d)\n", ret);
+
+   break;
+   default:
+   ret = -EINVAL;
+   break;
+   }
+
+   return ret;
+}
+
+static int ufs_versal2_link_startup_notify(struct ufs_hba *hba,
+  enum ufs_notify_change_status status)
+{
+   struct ufs_versal2_priv *priv = dev_get_priv(hba->dev);
+   int ret = 0;
+
+   switch (status) {
+   case PRE_CHANGE:
+   if (priv->host_clk) {
+   u32 core_clk_div = priv->host_clk / TIMEOUT_MICROSEC;
+
+   ufshcd_writel(hba, core_clk_div, DWC_UFS_REG_HCLKDIV);
+   }
+   break;
+   case POST_CHANGE:
+   ret = ufshcd_dwc_link_startup_notify(hba, status);
+   break;
+   default:
+   ret = -EINVAL;
+   break;
+   }
+
+   return ret;
+}
+
+static struct ufs_hba_ops ufs_versal2_hba_ops = {
+   .init = ufs_versal2_init,
+   .link_startup_notify = ufs_versal2_link_startup_notify,
+   .hce_enable_notify = ufs_versal2_hce_enable_notify,
+};
+
+static int ufs_versal2_probe(struct udevice *dev)
+{
+   int ret;
+
+   /* Perform generic probe */
+   ret = ufshcd_probe(dev, &ufs_versal2_hba_ops);
+   if (ret)
+   dev_err(dev, "ufshcd_probe() failed %d\n", ret);
+
+   return ret;
+}
+
+static int ufs_versal2_bind(struct udevice *dev)
+{
+   struct udevice *scsi_dev;
+
+   return ufs_scsi_bind(dev, &scsi_dev);
+}
+
+static const struct udevice_id ufs_versal2_ids[] = {
+   {
+   .compatible = "amd,versal2-ufs",
+   },
+   {},
+};
+
+U_BOOT_DRIVER(ufs_versal2_pltfm) = {
+   .name   = "ufs-versal2-pltfm",
+   .id = UCLASS_UFS,
+   .of_match   = ufs_versal2_ids,
+   .probe  = ufs_versal2_probe,
+   .bind   = ufs_versal2_bind,
+};
diff --git a/drivers/ufs/ufshcd-dwc.h b/drivers/ufs/ufshcd-dwc.h
index d997045d3c..fc1bcca8cc 100644
--- a/drivers/ufs/ufshcd-dwc.h
+++ b/drivers/ufs/ufshcd-dwc.h
@@ -10,6 +10,52 @@
  #ifndef _UFSHCD_DWC_H
  #define _UFSHCD_DWC_H
  
+/* PHY modes */

+#define UFSHCD_DWC_PHY_MODE_ROM0
+
+/* RMMI Attributes */
+#define CBREFCLKCTRL2  0x8132
+#define CBCRCTRL   0x811F
+#define CBC10DIRECTCONF2   0x810E
+#define CBCREGADDRLSB  0x8116
+#define CBCREGADDRMSB  0x8117
+#define CBCREGWRLSB0x8118
+#define CBCREGWRMSB0x8119
+#define CBCREGRDLSB0x811A
+#define CBCREGRDMSB0x811B
+#define CBCREGRDWRSEL  0x811C
+
+#define CBREFREFCLK_GATE_OVR_ENBIT(7)
+
+/* M-PHY Attributes */
+#define MTX_FSM_STATE  0x41
+#define MRX_FSM_STATE  0xC1
+
+/* M-PHY registers */
+#define FAST_FLAGS(n)  (0x401C + ((n) * 0x100))
+#define RX_AFE_ATT_IDAC(n) (0x4000 + ((n) * 0x100))
+#define RX_AFE_CTLE_IDAC(n)(0x4001 + ((n) * 0x100))
+#define FW_CALIB_CCFG(n)   (0x404D + ((n) * 0x100))
+
+/* Tx/Rx FSM state */
+enum rx_fsm_state {
+   RX_STATE_DISABLED = 0,
+   RX_STATE_HIBERN8 = 1,
+   RX_STATE_SLEEP = 2,
+   RX_STATE_STALL = 3,
+   RX_STATE_LSBURST = 4,
+   RX_STATE_HSBURST = 5,
+};
+
+enum tx_fsm_state {
+   TX_STATE_DISABLED = 0,
+   TX_STATE_HIBERN8 = 1,
+   TX_STATE_SLEEP = 2,
+   TX_STATE_STALL = 3,
+   TX_STATE_LSBURST = 4,
+   TX_STATE_HSBURST = 5,
+};
+
  struct ufshcd_dme_attr_val {
u32 attr_sel;
    u32 mib_val;
diff --git a/drivers/ufs/unipro.h b/drivers/ufs/unipro.h
index b30b17fa5a..2f5726d4d3 100644
--- a/drivers/ufs/unipro.h
+++ b/drivers/ufs/unipro.h
@@ -148,6 +148,7 @@
  #define VS_MPHYCFGUPDT0xD085
  #define VS_DEBUGOMC   0xD09E
  #define VS_POWERSTATE 0xD083
+#define VS_MPHYDISABLE 0xD0C1
  
  #define PA_GRANULARITY_MIN_VAL	1

  #define PA_GRANULARITY_MAX_VAL6


Looks fine!

Reviewed-by: Neil Armstrong 

Neil


Re: [PATCH 1/3] ufs: add support for DesignWare Controller

2024-09-19 Thread neil . armstrong

Hi,

On 19/09/2024 11:17, Venkatesh Yadav Abbarapu wrote:

This patch has the goal to add support for DesignWare UFS Controller
specific operations.

This is based on linux kernel commit:
"drivers/scsi/ufs/ufshcd-dwc.c: ufs: add support for DesignWare
Controller" (sha1: 4b9ffb5a353bdee49f1f477ffe2b95ab3f9cbc0c)
It is ported from linux kernel 6.11-rc1.

Signed-off-by: Venkatesh Yadav Abbarapu 
---
  drivers/ufs/ufs.h|  11 +++
  drivers/ufs/ufshcd-dwc.c | 141 +++
  drivers/ufs/ufshcd-dwc.h |  23 +++
  drivers/ufs/ufshci-dwc.h |  32 +
  4 files changed, 207 insertions(+)
  create mode 100644 drivers/ufs/ufshcd-dwc.c
  create mode 100644 drivers/ufs/ufshcd-dwc.h
  create mode 100644 drivers/ufs/ufshci-dwc.h

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index e8a1441156..83837d5817 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -850,6 +850,7 @@ struct ufs_hba {
struct ufs_pwr_mode_info max_pwr_info;
  
  	struct ufs_dev_cmd dev_cmd;

+   enum uic_link_state uic_link_state;


Will this be really used ?


  };
  
  static inline int ufshcd_ops_init(struct ufs_hba *hba)

@@ -878,6 +879,14 @@ static inline int ufshcd_ops_link_startup_notify(struct 
ufs_hba *hba,
return 0;
  }
  
+static inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba)

+{
+   if (hba->ops && hba->ops->phy_initialization)
+   return hba->ops->phy_initialization(hba);
+
+   return 0;
+}


There's no users of hba->ops->phy_initialization,
and the patch 2 doesn't even add an user, so I think you can
also drop this


+
  /* Controller UFSHCI version */
  enum {
UFSHCI_VERSION_10 = 0x0001, /* 1.0 */
@@ -1022,6 +1031,8 @@ enum {
writel((val), (hba)->mmio_base + (reg))
  #define ufshcd_readl(hba, reg) \
readl((hba)->mmio_base + (reg))
+#define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \
+   UIC_LINK_ACTIVE_STATE)


Same here, you set as active, but there's no users of uic_link_state

I think you can drop this

  
  /**

   * ufshcd_rmwl - perform read/modify/write for a controller register
diff --git a/drivers/ufs/ufshcd-dwc.c b/drivers/ufs/ufshcd-dwc.c
new file mode 100644
index 00..db51a3b807
--- /dev/null
+++ b/drivers/ufs/ufshcd-dwc.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UFS Host driver for Synopsys Designware Core
+ *
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ufs.h"
+#include "ufshci-dwc.h"
+#include "ufshcd-dwc.h"
+
+int ufshcd_dwc_dme_set_attrs(struct ufs_hba *hba,
+const struct ufshcd_dme_attr_val *v, int n)
+{
+   int ret = 0;
+   int attr_node = 0;
+
+   for (attr_node = 0; attr_node < n; attr_node++) {
+   ret = ufshcd_dme_set_attr(hba, v[attr_node].attr_sel,
+ ATTR_SET_NOR, v[attr_node].mib_val, 
v[attr_node].peer);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+/**
+ * ufshcd_dwc_program_clk_div() - program clock divider.
+ * @hba: Private Structure pointer
+ * @divider_val: clock divider value to be programmed
+ *
+ */
+static void ufshcd_dwc_program_clk_div(struct ufs_hba *hba, u32 divider_val)
+{
+   ufshcd_writel(hba, divider_val, DWC_UFS_REG_HCLKDIV);
+}
+
+/**
+ * ufshcd_dwc_link_is_up() - check if link is up.
+ * @hba: private structure pointer
+ *
+ * Return: 0 on success, non-zero value on failure.
+ */
+static int ufshcd_dwc_link_is_up(struct ufs_hba *hba)
+{
+   int dme_result = 0;
+
+   ufshcd_dme_get(hba, UIC_ARG_MIB(VS_POWERSTATE), &dme_result);
+
+   if (dme_result == UFSHCD_LINK_IS_UP) {
+   ufshcd_set_link_active(hba);


You can drop this, we don't track and use the link state


+   return 0;
+   }
+
+   return 1;
+}
+
+/**
+ * ufshcd_dwc_connection_setup() - configure unipro attributes.
+ * @hba: pointer to drivers private data
+ *
+ * This function configures both the local side (host) and the peer side
+ * (device) unipro attributes to establish the connection to application/
+ * cport.
+ * This function is not required if the hardware is properly configured to
+ * have this connection setup on reset. But invoking this function does no
+ * harm and should be fine even working with any ufs device.
+ *
+ * Return: 0 on success non-zero value on failure.
+ */
+static int ufshcd_dwc_connection_setup(struct ufs_hba *hba)
+{
+   static const struct ufshcd_dme_attr_val setup_attrs[] = {
+   { UIC_ARG_MIB(T_CONNECTIONSTATE), 0, DME_LOCAL },
+   { UIC_ARG_MIB(N_DEVICEID), 0, DME_LOCAL },
+   { UIC_ARG_MIB(N_DEVICEID_VALID), 0, DME_LOCAL },
+   { UIC_ARG_MIB(T_PEERDEVICEID), 1, DME_LOCAL },
+   { UIC_ARG_MIB(

Re: [PATCH 00/13] ufs: enhancements to support Qualcomm UFS controllers

2024-09-19 Thread neil . armstrong

On 19/09/2024 10:56, Neha Malcom Francis wrote:

Hi Neil

On 18/09/24 13:36, Neil Armstrong wrote:

Hi Marek, Manorit, Tom, Michal,

On 10/09/2024 11:20, Neil Armstrong wrote:

This serie regroups all the fixes and base enhancements required to
support the Qualcomm UFS controllers in U-Boot.

This syncs headers & defines from Linux, and includes 2 set of
fixes that were sent separately:
- ufs: core: remove link_startup_again logic
- ufs: properly fix cache operations

Without those 2 sets, UFS cannot initialize on Qualcomm controlers
since v5, and a numerous of Cache issues makes any UFS controller
fail to initialize.

Since UFS core hasn't changed for a while, and since UFS is core
technology for the Qualcomm SoCs, I volunteer maintaininig the
UFS subsystem if Bhupesh & Neha Malcom Francis are ok with that.


Could you run this serie on the r8a779f0_spider, j721s2_evm_a72, j721e_evm_a72,
j7200_evm_a72, amd_versal2_virt and qemu-riscv and check for possible 
regressions ?



For the K3 platforms (j721s2, j721e, j7200, j784s4) I have already done a 
sanity test with this series on j784s4 with no regressions seen, so should be 
fine.


Ack, thanks for the report!

Neil




It seems the only user of UFS_PCI is qemu-riscv, is there other users ?

Thanks,
Neil



Signed-off-by: Neil Armstrong 
---
Bhupesh Sharma (5):
   ufs/ufs.h: Add definition of 'ufshcd_rmwl()'
   ufs: Clear UECPA once due to LINERESET has happened during LINK_STARTUP
   ufs: Sync possible UFS Quirks with Linux UFS driver
   ufs: Add missing memory barriers
   ufs: Fix debug message in 'ufs_start'

Marek Vasut (2):
   ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS
   ufs: Add UFSHCD_QUIRK_HIBERN_FASTAUTO

Neil Armstrong (6):
   ufs: allocate descriptors with size aligned with DMA_MINALIGN
   ufs: fix dcache flush and invalidate range calculation
   ufs: split flush and invalidate to only invalidate when required
   ufs: use dcache helpers for scsi_cmd data and only invalidate if 
necessary
   ufs: core: remove link_startup_again logic
   MAINTAINERS: Add myself to the list of UFS maintainers

  MAINTAINERS   |   1 +
  drivers/ufs/ufs.c |  98 --
  drivers/ufs/ufs.h | 157 +++---
  3 files changed, 197 insertions(+), 59 deletions(-)
---
base-commit: ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac
change-id: 20240910-topic-ufs-enhancements-fe8ef9ce39d8

Best regards,








Re: [PATCH 00/13] ufs: enhancements to support Qualcomm UFS controllers

2024-09-19 Thread neil . armstrong

On 18/09/2024 12:47, Michal Simek wrote:



On 9/18/24 12:40, neil.armstr...@linaro.org wrote:

Hi,

On 18/09/2024 11:03, Michal Simek wrote:

Hi Neil,

On 9/18/24 10:06, Neil Armstrong wrote:

Hi Marek, Manorit, Tom, Michal,

On 10/09/2024 11:20, Neil Armstrong wrote:

This serie regroups all the fixes and base enhancements required to
support the Qualcomm UFS controllers in U-Boot.

This syncs headers & defines from Linux, and includes 2 set of
fixes that were sent separately:
- ufs: core: remove link_startup_again logic
- ufs: properly fix cache operations

Without those 2 sets, UFS cannot initialize on Qualcomm controlers
since v5, and a numerous of Cache issues makes any UFS controller
fail to initialize.

Since UFS core hasn't changed for a while, and since UFS is core
technology for the Qualcomm SoCs, I volunteer maintaininig the
UFS subsystem if Bhupesh & Neha Malcom Francis are ok with that.


Could you run this serie on the r8a779f0_spider, j721s2_evm_a72, j721e_evm_a72,
j7200_evm_a72, amd_versal2_virt and qemu-riscv and check for possible 
regressions ?

It seems the only user of UFS_PCI is qemu-riscv, is there other users ?



Good timing. We are close to send some updates to UFS which we require to get 
DWC version to work inside U-Boot.

How far are that core changes from Linux? I see 9/13 is sync with Linux but 
when this is done you should also say which Linux version was used for sync.


I think we are still quite far from Linux, we just took the basic required bits 
and pieces
to at least make the Qcom UFS controller driver build work, but Linux driver is 
overly complicated
with power management code we do not really need in U-Boot, so it's quite hard 
to sync honestly.

But the plan is to align as much as possible once we get the basic Qcom UFS 
mainline.


That's understandable. But even when you say sync with Linux for some headers, 
etc it is good to say that it is sync with 6.11 for example.


Oh yes exact, I forgot to add this info, I planned to... I'll fix this in a v2.

Thanks,
Neil



Thanks,
Michal





Re: [PATCH 00/13] ufs: enhancements to support Qualcomm UFS controllers

2024-09-18 Thread neil . armstrong

Hi,

On 18/09/2024 11:03, Michal Simek wrote:

Hi Neil,

On 9/18/24 10:06, Neil Armstrong wrote:

Hi Marek, Manorit, Tom, Michal,

On 10/09/2024 11:20, Neil Armstrong wrote:

This serie regroups all the fixes and base enhancements required to
support the Qualcomm UFS controllers in U-Boot.

This syncs headers & defines from Linux, and includes 2 set of
fixes that were sent separately:
- ufs: core: remove link_startup_again logic
- ufs: properly fix cache operations

Without those 2 sets, UFS cannot initialize on Qualcomm controlers
since v5, and a numerous of Cache issues makes any UFS controller
fail to initialize.

Since UFS core hasn't changed for a while, and since UFS is core
technology for the Qualcomm SoCs, I volunteer maintaininig the
UFS subsystem if Bhupesh & Neha Malcom Francis are ok with that.


Could you run this serie on the r8a779f0_spider, j721s2_evm_a72, j721e_evm_a72,
j7200_evm_a72, amd_versal2_virt and qemu-riscv and check for possible 
regressions ?

It seems the only user of UFS_PCI is qemu-riscv, is there other users ?



Good timing. We are close to send some updates to UFS which we require to get 
DWC version to work inside U-Boot.

How far are that core changes from Linux? I see 9/13 is sync with Linux but 
when this is done you should also say which Linux version was used for sync.


I think we are still quite far from Linux, we just took the basic required bits 
and pieces
to at least make the Qcom UFS controller driver build work, but Linux driver is 
overly complicated
with power management code we do not really need in U-Boot, so it's quite hard 
to sync honestly.

But the plan is to align as much as possible once we get the basic Qcom UFS 
mainline.



I see that there are definitely some kernel-doc issues

Also s/U-boot/U-Boot/g


Ack, will check



Venkatesh: Can you please look at this patch series and validate it on our 
platform? Also make sense to send our changes to make sure that they won't 
break others.

Thanks,
Michal


Thanks,
Neil



Re: [PATCH 00/13] ufs: enhancements to support Qualcomm UFS controllers

2024-09-18 Thread Neil Armstrong

Hi Marek, Manorit, Tom, Michal,

On 10/09/2024 11:20, Neil Armstrong wrote:

This serie regroups all the fixes and base enhancements required to
support the Qualcomm UFS controllers in U-Boot.

This syncs headers & defines from Linux, and includes 2 set of
fixes that were sent separately:
- ufs: core: remove link_startup_again logic
- ufs: properly fix cache operations

Without those 2 sets, UFS cannot initialize on Qualcomm controlers
since v5, and a numerous of Cache issues makes any UFS controller
fail to initialize.

Since UFS core hasn't changed for a while, and since UFS is core
technology for the Qualcomm SoCs, I volunteer maintaininig the
UFS subsystem if Bhupesh & Neha Malcom Francis are ok with that.


Could you run this serie on the r8a779f0_spider, j721s2_evm_a72, j721e_evm_a72,
j7200_evm_a72, amd_versal2_virt and qemu-riscv and check for possible 
regressions ?

It seems the only user of UFS_PCI is qemu-riscv, is there other users ?

Thanks,
Neil



Signed-off-by: Neil Armstrong 
---
Bhupesh Sharma (5):
   ufs/ufs.h: Add definition of 'ufshcd_rmwl()'
   ufs: Clear UECPA once due to LINERESET has happened during LINK_STARTUP
   ufs: Sync possible UFS Quirks with Linux UFS driver
   ufs: Add missing memory barriers
   ufs: Fix debug message in 'ufs_start'

Marek Vasut (2):
   ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS
   ufs: Add UFSHCD_QUIRK_HIBERN_FASTAUTO

Neil Armstrong (6):
   ufs: allocate descriptors with size aligned with DMA_MINALIGN
   ufs: fix dcache flush and invalidate range calculation
   ufs: split flush and invalidate to only invalidate when required
   ufs: use dcache helpers for scsi_cmd data and only invalidate if 
necessary
   ufs: core: remove link_startup_again logic
   MAINTAINERS: Add myself to the list of UFS maintainers

  MAINTAINERS   |   1 +
  drivers/ufs/ufs.c |  98 --
  drivers/ufs/ufs.h | 157 +++---
  3 files changed, 197 insertions(+), 59 deletions(-)
---
base-commit: ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac
change-id: 20240910-topic-ufs-enhancements-fe8ef9ce39d8

Best regards,




[PATCH v2 2/2] board: libre-computer: aml-s805x-cc: Enable capsule updates

2024-09-17 Thread Neil Armstrong
Since the aml-s805-cc works well using EFI, and now the capsule updates
backend has been merged, let's enable the missing configs and add
the required structures to support it.

The GUID is dynamically generated for the board, to get it:
=> efidebug capsule esrt

ESRT: fw_resource_count=1
ESRT: fw_resource_count_max=1
ESRT: fw_resource_version=1
[entry 0]==
ESRT: fw_class=B8079027-9B2C-57D4-86AA-CC782ADA598C
ESRT: fw_type=unknown
ESRT: fw_version=0
ESRT: lowest_supported_fw_version=0
ESRT: capsule_flags=0
ESRT: last_attempt_version=0
ESRT: last_attempt_status=success


On the host (with the aml_encrypt_gxl result binary):
$ eficapsule --guid B8079027-9B2C-57D4-86AA-CC782ADA598C -i 1 u-boot.bin 
u-boot.cap

On the board (from USB disk containing u-boot.cap at root):
=> load usb 0:1 $kernel_addr_r u-boot.cap
=> efidebug capsule update $kernel_addr_r

The binary will then be flashed on the SPI.

Reviewed-by: Ilias Apalodimas 
Signed-off-by: Neil Armstrong 
---
 board/libre-computer/aml-s805x-ac/aml-s805x-ac.c | 24 
 configs/libretech-ac_defconfig   |  6 ++
 2 files changed, 30 insertions(+)

diff --git a/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c 
b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
index ae9834c0bf8..94cf5b4361f 100644
--- a/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
+++ b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -19,6 +20,29 @@
 #define EFUSE_MAC_OFFSET   52
 #define EFUSE_MAC_SIZE 6
 
+struct efi_fw_image fw_images[] = {
+   {
+   .fw_name = u"AML_S805X_AC_BOOT",
+   .image_index = 1,
+   },
+};
+
+struct efi_capsule_update_info update_info = {
+   .dfu_string = "sf 0:0=u-boot-bin raw 0 0x1",
+   .num_images = ARRAY_SIZE(fw_images),
+   .images = fw_images,
+};
+
+#if IS_ENABLED(CONFIG_SET_DFU_ALT_INFO)
+void set_dfu_alt_info(char *interface, char *devstr)
+{
+   if (strcmp(interface, "ram") == 0)
+   env_set("dfu_alt_info", "fitimage ram 0x0808 0x400");
+   else if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT))
+   env_set("dfu_alt_info", update_info.dfu_string);
+}
+#endif
+
 int misc_init_r(void)
 {
u8 mac_addr[EFUSE_MAC_SIZE + 1];
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index 11d9795e05d..7763a14f203 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -35,6 +35,7 @@ CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
 CONFIG_CMD_DFU=y
+CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -42,6 +43,7 @@ CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_EFIDEBUG=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -49,6 +51,8 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
 CONFIG_DFU_RAM=y
+CONFIG_DFU_SF=y
+CONFIG_SET_DFU_ALT_INFO=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
@@ -98,3 +102,5 @@ CONFIG_VIDEO_BMP_RLE8=y
 CONFIG_BMP_16BPP=y
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y

-- 
2.34.1



[PATCH v2 1/2] board: libretech-ac: move board support into dedicated directory

2024-09-17 Thread Neil Armstrong
The libretech-ac aka aml-s805x-ac supports mainline U-boot
from a dedicated SPI flash, move the board support into
a dedicated vendor/board subdirectory in order to support
vendor specific customization.

It also aligns with the vendor downstream changes.

Signed-off-by: Neil Armstrong 
---
 board/amlogic/p212/MAINTAINERS   |  2 -
 board/libre-computer/aml-s805x-ac/MAINTAINERS|  8 
 board/libre-computer/aml-s805x-ac/Makefile   |  6 +++
 board/libre-computer/aml-s805x-ac/aml-s805x-ac.c | 47 
 configs/libretech-ac_defconfig   |  2 +
 5 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/board/amlogic/p212/MAINTAINERS b/board/amlogic/p212/MAINTAINERS
index b2e3205fdf0..e73a4e52c1f 100644
--- a/board/amlogic/p212/MAINTAINERS
+++ b/board/amlogic/p212/MAINTAINERS
@@ -5,11 +5,9 @@ L: u-boot-amlo...@groups.io
 F: board/amlogic/p212/
 F: include/configs/p212.h
 F: configs/khadas-vim_defconfig
-F: configs/libretech-ac_defconfig
 F: configs/libretech-cc_defconfig
 F: configs/libretech-cc_v2_defconfig
 F: configs/p212_defconfig
 F: doc/board/amlogic/p212.rst
-F: doc/board/amlogic/libretech-ac.rst
 F: doc/board/amlogic/libretech-cc.rst
 F: doc/board/amlogic/khadas-vim.rst
diff --git a/board/libre-computer/aml-s805x-ac/MAINTAINERS 
b/board/libre-computer/aml-s805x-ac/MAINTAINERS
new file mode 100644
index 000..7cbc08aeb6c
--- /dev/null
+++ b/board/libre-computer/aml-s805x-ac/MAINTAINERS
@@ -0,0 +1,8 @@
+LIBRE-COMPUTER AML-S805X-AC
+M: Neil Armstrong 
+S: Maintained
+L: u-boot-amlo...@groups.io
+F: board/amlogic/aml-s805x-ac/
+F: include/configs/libretech-ac.h
+F: configs/libretech-ac_defconfig
+F: doc/board/amlogic/libretech-ac.rst
diff --git a/board/libre-computer/aml-s805x-ac/Makefile 
b/board/libre-computer/aml-s805x-ac/Makefile
new file mode 100644
index 000..b4367ea522b
--- /dev/null
+++ b/board/libre-computer/aml-s805x-ac/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 BayLibre, SAS
+# Author: Neil Armstrong 
+
+obj-y  := aml-s805x-ac.o
diff --git a/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c 
b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
new file mode 100644
index 000..ae9834c0bf8
--- /dev/null
+++ b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define EFUSE_SN_OFFSET20
+#define EFUSE_SN_SIZE  16
+#define EFUSE_MAC_OFFSET   52
+#define EFUSE_MAC_SIZE 6
+
+int misc_init_r(void)
+{
+   u8 mac_addr[EFUSE_MAC_SIZE + 1];
+   char serial[EFUSE_SN_SIZE + 1];
+   ssize_t len;
+
+   if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
+   len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
+ mac_addr, EFUSE_MAC_SIZE);
+   mac_addr[len] = '\0';
+   if (len == EFUSE_MAC_SIZE && is_valid_ethaddr(mac_addr))
+   eth_env_set_enetaddr("ethaddr", mac_addr);
+   else
+   meson_generate_serial_ethaddr();
+   }
+
+   if (!env_get("serial#")) {
+   len = meson_sm_read_efuse(EFUSE_SN_OFFSET, serial,
+   EFUSE_SN_SIZE);
+   serial[len] = '\0';
+   if (len == EFUSE_SN_SIZE)
+   env_set("serial#", serial);
+   }
+
+   return 0;
+}
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index 6ad04570022..11d9795e05d 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -1,5 +1,7 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="libretech-ac"
+CONFIG_SYS_VENDOR="libre-computer"
+CONFIG_SYS_BOARD="aml-s805x-ac"
 CONFIG_ARCH_MESON=y
 CONFIG_TEXT_BASE=0x0100
 CONFIG_NR_DRAM_BANKS=1

-- 
2.34.1



[PATCH v2 0/2] ARM: meson: libretech-ac: add support for EFI Capsules Update

2024-09-17 Thread Neil Armstrong
The necessary changes were made in U-Boot to easily support
EFI Capsules Update and be compliant with Arm SystemReady IR.

Let's add support for the libretech-ac/AML-S805X-CC since
it's an easy well-supported target having a dedicated SPI
Flash to store U-Boot.

Signed-off-by: Neil Armstrong 
---
Changes in v2:
- Add set_dfu_alt_info() + CONFIG_SET_DFU_ALT_INFO to support both RAM and SF 
DFU backend
- Fix typo in cover letter and commit message
- Link to v1: 
https://lore.kernel.org/r/20240916-u-boot-topic-dynamic-uuid-v1-0-7e4f48542...@linaro.org

---
Neil Armstrong (2):
  board: libretech-ac: move board support into dedicated directory
  board: libre-computer: aml-s805x-cc: Enable capsule updates

 board/amlogic/p212/MAINTAINERS   |  2 -
 board/libre-computer/aml-s805x-ac/MAINTAINERS|  8 +++
 board/libre-computer/aml-s805x-ac/Makefile   |  6 ++
 board/libre-computer/aml-s805x-ac/aml-s805x-ac.c | 71 
 configs/libretech-ac_defconfig   |  8 +++
 5 files changed, 93 insertions(+), 2 deletions(-)
---
base-commit: df84c019c46e6833cc79385bdb23efba4882c09d
change-id: 20240916-u-boot-topic-dynamic-uuid-a871c25236a4

Best regards,
-- 
Neil Armstrong 



[PATCH] dfu: sf: rely on DT for spi speed and mode

2024-09-17 Thread Neil Armstrong
Align with cmd_sf, and try to rely on DT for spi speed and mode,
and still fallback on spi_flash_probe() if it fails.

With the current scheme, spi_flash_probe() will be called
with CONFIG_SF_DEFAULT_SPEED and CONFIG_SF_DEFAULT_MODE
with are set to 0 by default on DT platforms using DM_SPI_FLASH.

Like cmd_sf, keep the option to specify the speed and mode
from the dfu_alt_mode string, but rely on DT properties
if not specified.

Using CONFIG_SF_DEFAULT_SPEED and CONFIG_SF_DEFAULT_MODE
makes the SPIFC controller on Amlogic Meson G12B & SM1
hardware fail and is unable to recover until a system reboot.

Signed-off-by: Neil Armstrong 
---
 drivers/dfu/dfu_sf.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c
index 7c1c0f9e2dc..b5d875be5ea 100644
--- a/drivers/dfu/dfu_sf.c
+++ b/drivers/dfu/dfu_sf.c
@@ -123,6 +123,9 @@ static struct spi_flash *parse_dev(char *devstr)
unsigned int mode = CONFIG_SF_DEFAULT_MODE;
char *s, *endp;
struct spi_flash *dev;
+#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
+   bool use_dt = true;
+#endif
 
s = strsep(&devstr, ":");
if (!s || !*s || (bus = simple_strtoul(s, &endp, 0), *endp)) {
@@ -143,6 +146,9 @@ static struct spi_flash *parse_dev(char *devstr)
printf("Invalid SPI speed %s\n", s);
return NULL;
}
+#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
+   use_dt = false;
+#endif
}
 
s = strsep(&devstr, ":");
@@ -152,9 +158,25 @@ static struct spi_flash *parse_dev(char *devstr)
printf("Invalid SPI mode %s\n", s);
return NULL;
}
+#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
+   use_dt = false;
+#endif
}
 
+#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
+   if (use_dt) {
+   struct udevice *new;
+
+   if (!spi_flash_probe_bus_cs(bus, cs, &new))
+   dev = dev_get_uclass_priv(new);
+   else
+   dev = NULL;
+   } else {
+   dev = spi_flash_probe(bus, cs, speed, mode);
+   }
+#else
dev = spi_flash_probe(bus, cs, speed, mode);
+#endif
if (!dev) {
printf("Failed to create SPI flash at %u:%u:%u:%u\n",
   bus, cs, speed, mode);

---
base-commit: 19dbc09405d3503ce3efef3c2e4b4f0f1a03372d
change-id: 20240917-uboot-topic-dfu-sf-dt-8ae62e5c7d79

Best regards,
-- 
Neil Armstrong 



Re: [PATCH 0/2] ARM: meson: libretech-ac: add suppor for EFI Capsules Update

2024-09-17 Thread Neil Armstrong

On 16/09/2024 18:29, Tom Rini wrote:

On Mon, Sep 16, 2024 at 11:41:47AM +0200, Neil Armstrong wrote:


The necessary changes were made in U-Boot to easily support
EFI Capsules Update and be compliant with Arm SystemReady SR.


To be clear, "SR" or "IR" ? I assume you meant IR here.


Indeed IR, I'll fix in v2, I need to send a v2 because I need to
add set_dfu_alt_info() to keep support for the ram backed dfu I
used when booting from USB.

Thanks,
Neil


[PATCH 1/2] board: libretech-ac: move board support into dedicated directory

2024-09-16 Thread Neil Armstrong
The libretech-ac aka aml-s805x-ac supports mainline U-boot
from a dedicated SPI flash, move the board support into
a dedicated vendor/board subdirectory in order to support
vendor specific customization.

It also aligns with the vendor downstream changes.

Signed-off-by: Neil Armstrong 
---
 board/amlogic/p212/MAINTAINERS   |  2 -
 board/libre-computer/aml-s805x-ac/MAINTAINERS|  8 
 board/libre-computer/aml-s805x-ac/Makefile   |  6 +++
 board/libre-computer/aml-s805x-ac/aml-s805x-ac.c | 47 
 configs/libretech-ac_defconfig   |  2 +
 5 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/board/amlogic/p212/MAINTAINERS b/board/amlogic/p212/MAINTAINERS
index b2e3205fdf0..e73a4e52c1f 100644
--- a/board/amlogic/p212/MAINTAINERS
+++ b/board/amlogic/p212/MAINTAINERS
@@ -5,11 +5,9 @@ L: u-boot-amlo...@groups.io
 F: board/amlogic/p212/
 F: include/configs/p212.h
 F: configs/khadas-vim_defconfig
-F: configs/libretech-ac_defconfig
 F: configs/libretech-cc_defconfig
 F: configs/libretech-cc_v2_defconfig
 F: configs/p212_defconfig
 F: doc/board/amlogic/p212.rst
-F: doc/board/amlogic/libretech-ac.rst
 F: doc/board/amlogic/libretech-cc.rst
 F: doc/board/amlogic/khadas-vim.rst
diff --git a/board/libre-computer/aml-s805x-ac/MAINTAINERS 
b/board/libre-computer/aml-s805x-ac/MAINTAINERS
new file mode 100644
index 000..7cbc08aeb6c
--- /dev/null
+++ b/board/libre-computer/aml-s805x-ac/MAINTAINERS
@@ -0,0 +1,8 @@
+LIBRE-COMPUTER AML-S805X-AC
+M: Neil Armstrong 
+S: Maintained
+L: u-boot-amlo...@groups.io
+F: board/amlogic/aml-s805x-ac/
+F: include/configs/libretech-ac.h
+F: configs/libretech-ac_defconfig
+F: doc/board/amlogic/libretech-ac.rst
diff --git a/board/libre-computer/aml-s805x-ac/Makefile 
b/board/libre-computer/aml-s805x-ac/Makefile
new file mode 100644
index 000..b4367ea522b
--- /dev/null
+++ b/board/libre-computer/aml-s805x-ac/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2016 BayLibre, SAS
+# Author: Neil Armstrong 
+
+obj-y  := aml-s805x-ac.o
diff --git a/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c 
b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
new file mode 100644
index 000..ae9834c0bf8
--- /dev/null
+++ b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define EFUSE_SN_OFFSET20
+#define EFUSE_SN_SIZE  16
+#define EFUSE_MAC_OFFSET   52
+#define EFUSE_MAC_SIZE 6
+
+int misc_init_r(void)
+{
+   u8 mac_addr[EFUSE_MAC_SIZE + 1];
+   char serial[EFUSE_SN_SIZE + 1];
+   ssize_t len;
+
+   if (!eth_env_get_enetaddr("ethaddr", mac_addr)) {
+   len = meson_sm_read_efuse(EFUSE_MAC_OFFSET,
+ mac_addr, EFUSE_MAC_SIZE);
+   mac_addr[len] = '\0';
+   if (len == EFUSE_MAC_SIZE && is_valid_ethaddr(mac_addr))
+   eth_env_set_enetaddr("ethaddr", mac_addr);
+   else
+   meson_generate_serial_ethaddr();
+   }
+
+   if (!env_get("serial#")) {
+   len = meson_sm_read_efuse(EFUSE_SN_OFFSET, serial,
+   EFUSE_SN_SIZE);
+   serial[len] = '\0';
+   if (len == EFUSE_SN_SIZE)
+   env_set("serial#", serial);
+   }
+
+   return 0;
+}
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index 6ad04570022..11d9795e05d 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -1,5 +1,7 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="libretech-ac"
+CONFIG_SYS_VENDOR="libre-computer"
+CONFIG_SYS_BOARD="aml-s805x-ac"
 CONFIG_ARCH_MESON=y
 CONFIG_TEXT_BASE=0x0100
 CONFIG_NR_DRAM_BANKS=1

-- 
2.34.1



[PATCH 2/2] board: libre-computer: aml-s805-cc: Enable capsule updates

2024-09-16 Thread Neil Armstrong
Since the aml-s805-cc works well using EFI, and now the capsule updates
backend has been merged, let's enable the missing configs and add
the required structures to support it.

The GUID is dynamically generated for the board, to get it:
=> efidebug capsule esrt

ESRT: fw_resource_count=1
ESRT: fw_resource_count_max=1
ESRT: fw_resource_version=1
[entry 0]==
ESRT: fw_class=B8079027-9B2C-57D4-86AA-CC782ADA598C
ESRT: fw_type=unknown
ESRT: fw_version=0
ESRT: lowest_supported_fw_version=0
ESRT: capsule_flags=0
ESRT: last_attempt_version=0
ESRT: last_attempt_status=success


On the host (with the aml_encrypt_gxl result binary):
$ eficapsule --guid B8079027-9B2C-57D4-86AA-CC782ADA598C -i 1 u-boot.bin 
u-boot.cap

On the board (from USB disk containing u-boot.cap at root):
=> load usb 0:1 $kernel_addr_r u-boot.cap
=> efidebug capsule update $kernel_addr_r

The binary will then be flashed on the SPI.

Signed-off-by: Neil Armstrong 
---
 board/libre-computer/aml-s805x-ac/aml-s805x-ac.c | 14 ++
 configs/libretech-ac_defconfig   |  5 +
 2 files changed, 19 insertions(+)

diff --git a/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c 
b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
index ae9834c0bf8..ba14df54967 100644
--- a/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
+++ b/board/libre-computer/aml-s805x-ac/aml-s805x-ac.c
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -19,6 +20,19 @@
 #define EFUSE_MAC_OFFSET   52
 #define EFUSE_MAC_SIZE 6
 
+struct efi_fw_image fw_images[] = {
+   {
+   .fw_name = u"AML_S805X_AC_BOOT",
+   .image_index = 1,
+   },
+};
+
+struct efi_capsule_update_info update_info = {
+   .dfu_string = "sf 0:0=u-boot-bin raw 0 0x1",
+   .num_images = ARRAY_SIZE(fw_images),
+   .images = fw_images,
+};
+
 int misc_init_r(void)
 {
u8 mac_addr[EFUSE_MAC_SIZE + 1];
diff --git a/configs/libretech-ac_defconfig b/configs/libretech-ac_defconfig
index 11d9795e05d..f146a495654 100644
--- a/configs/libretech-ac_defconfig
+++ b/configs/libretech-ac_defconfig
@@ -35,6 +35,7 @@ CONFIG_SYS_MAXARGS=32
 # CONFIG_CMD_IMI is not set
 CONFIG_CMD_ADC=y
 CONFIG_CMD_DFU=y
+CONFIG_CMD_NVEDIT_EFI=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
@@ -42,6 +43,7 @@ CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_EFIDEBUG=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_REGULATOR=y
 CONFIG_OF_CONTROL=y
@@ -49,6 +51,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_SYS_RELOC_GD_ENV_ADDR=y
 CONFIG_SARADC_MESON=y
 CONFIG_DFU_RAM=y
+CONFIG_DFU_SF=y
 CONFIG_MMC_MESON_GX=y
 CONFIG_MTD=y
 CONFIG_DM_MTD=y
@@ -98,3 +101,5 @@ CONFIG_VIDEO_BMP_RLE8=y
 CONFIG_BMP_16BPP=y
 CONFIG_BMP_24BPP=y
 CONFIG_BMP_32BPP=y
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y

-- 
2.34.1



[PATCH 0/2] ARM: meson: libretech-ac: add suppor for EFI Capsules Update

2024-09-16 Thread Neil Armstrong
The necessary changes were made in U-Boot to easily support
EFI Capsules Update and be compliant with Arm SystemReady SR.

Let's add support for the libretech-ac/AML-S805X-CC since
it's an easy well-supported target having a dedicated SPI
Flash to store U-Boot.

Signed-off-by: Neil Armstrong 
---
Neil Armstrong (2):
  board: libretech-ac: move board support into dedicated directory
  board: libre-computer: aml-s805-cc: Enable capsule updates

 board/amlogic/p212/MAINTAINERS   |  2 -
 board/libre-computer/aml-s805x-ac/MAINTAINERS|  8 
 board/libre-computer/aml-s805x-ac/Makefile   |  6 +++
 board/libre-computer/aml-s805x-ac/aml-s805x-ac.c | 61 
 configs/libretech-ac_defconfig   |  7 +++
 5 files changed, 82 insertions(+), 2 deletions(-)
---
base-commit: df84c019c46e6833cc79385bdb23efba4882c09d
change-id: 20240916-u-boot-topic-dynamic-uuid-a871c25236a4

Best regards,
-- 
Neil Armstrong 



Re: Assistance Required: U-Boot Access Issues on Amlogic A113X SoC

2024-09-12 Thread neil . armstrong

Hi Mike,

On 06/09/2024 19:00, Mike wrote:

Dear U-Boot Community,

I am working on a project involving the Amlogic A113X SoC and have
encountered an issue with U-Boot during the boot process over UART. While I
am able to connect via UART and observe the boot log, the system does not
allow any interaction or command input. It seems that the manufacturer may
have restricted this access, potentially violating the GNU GPL license.


It surely does, it's quite common in embedded, they do not want you to
change the software running on the device even if the License allows you to.



Here are the details:

- *SoC:* Amlogic A113X


Good news, this device is very well supported on the mainline U-boot branch ;-)

=> https://linux-meson.com/u-boot.html
=> https://docs.u-boot.org/en/latest/board/amlogic/index.html

Neil


- *Bootloader:* U-Boot 2015.01 (Jan 13 2023 - 10:30:19)
- *Issue:* The device does not respond to input during the boot process
over UART (no response to Ctrl+C, Enter, etc.)
- *UART Log:*


AXG:BL1:d1dbf2:a4926f;FEAT:F0DC31BC:2000;POC:F;EMMC:800;NAND:0;READ:0;0.0;0.0;CHK:0;
sdio debug board detected
TE: 139689

BL2 Built : 10:38:43, Apr 14 2020. axg gf27ed33 - jenkins@walle02-sh

set vcck to 1100 mv
set vddee to 950 mv
Board ID = 3
CPU clk: 1200MHz
DDR low power enabled
DDR3 chl: Rank0 16bit @ 912MHz
bist_test rank: 0 1c 07 32 26 10 3c 1e 06 36 27 10 3f 00 00 00 00 00 00
00 00 00 00 00 00 772   - PASS
Rank0: 256MB(auto)-2T-13
AddrBus test pass!
NAND init
Load FIP HDR from NAND, src: 0xc000, des: 0x0170, size:
0x4000, part: 0
Load BL3x from NAND, src: 0x0001, des: 0x01704000, size: 0x000b7c00,
part: 0
NOTICE:  BL31: v1.3(release):3edeb02
NOTICE:  BL31: Built : 16:43:54, Apr 14 2020
NOTICE:  BL31: AXG secure boot!
NOTICE:  BL31: BL33 decompress pass
OPS=0x43
[Image: axg_v1.1.3494-9ec8345 2020-04-17 18:16:39 jenkins@walle02-sh]
25 0c 43 00 c3 ac bf b3 9f 7a e1 5b 3a 07 57 99
bl30:axg ver: 9 mode: 0
bl30:axg thermal0
[0.015883 Inits done]
secure task start!
high task start!
low task start!
ERROR:   Error initializing runtime service opteed_fast


U-Boot 2015.01 (Jan 13 2023 - 10:30:19)

DRAM:  256 MiB
Relocation Offset is: 0eeb
mmu cfg end: 0x2000
mmu cfg end: 0x2000
register usb cfg[0][1] = 0ff6e198
aml_i2c_init_port init regs for 2
NAND:  get_sys_clk_rate_mtd() 292, clock setting 200!
bus cycle0: 6,timing: 7
NAND device id: 98 da 90 15 76 16
NAND device: Manufacturer ID: 0x98, Chip ID: 0x98 (Toshiba A revision
NAND 2Gib TC58NVG1S3HBAI4 )
get_sys_clk_rate_mtd() 292, clock setting 200!
m3_nand_adjust_timing() sys_clk_rate 200, bus_c 6, bus_t 7
oob_fill_cnt =32 oob_size =64, bch_bytes =14
ecc mode:6 ecc_page_num=2 eep_need_oobsize=16
plane_num=1 writesize=0x800 ecc.size=0x200 bch_mode=1
oob avail size 6
Creating 1 MTD partitions on "A revision NAND 2Gib TC58NVG1S3HBAI4 ":
0x-0x0020 : "bootloader"
A revision NAND 2Gib TC58NVG1S3HBAI4  initialized ok
get_sys_clk_rate_mtd() 292, clock setting 200!
bus cycle0: 6,timing: 7
NAND device id: 98 da 90 15 76 16
NAND device: Manufacturer ID: 0x98, Chip ID: 0x98 (Toshiba A revision
NAND 2Gib TC58NVG1S3HBAI4 )
get_sys_clk_rate_mtd() 292, clock setting 200!
m3_nand_adjust_timing() sys_clk_rate 200, bus_c 6, bus_t 7
oob_fill_cnt =32 oob_size =64, bch_bytes =14
ecc mode:6 ecc_page_num=2 eep_need_oobsize=16
PLANE change!
plane_num=1 writesize=0x800 ecc.size=0x200 bch_mode=1
aml_nand_init :oobmul=1,oobfree.length=8,
- oob_size=64
oob avail size 8
nbbt=20
nenv=24
nkey=32
ndtb=40
nddr=44
bbt_start=20 env_start=24 key_start=32 dtb_start=40 ddr_start=44
nbbt: info size=0x800 max_scan_blk=24, start_blk=20
nbbt : phy_blk_addr=20, ec=0, phy_page_addr=0, timestamp=1
nbbt free list:
blockN=21, ec=-1, dirty_flag=0
blockN=22, ec=-1, dirty_flag=0
blockN=23, ec=-1, dirty_flag=0
aml_nand_scan_rsv_info 1134: page_num=1
aml_nand_scan_rsv_info 1137
nbbt valid addr: 28
aml_nand_bbt_check 1258 bbt is valid, reading.
aml_nand_read_rsv_info:446,read nbbt info to 28
nenv: info size=0x1 max_scan_blk=32, start_blk=24
nenv : phy_blk_addr=24, ec=0, phy_page_addr=0, timestamp=5
nenv free list:
blockN=25, ec=0, dirty_flag=1
blockN=26, ec=-1, dirty_flag=0
blockN=27, ec=-1, dirty_flag=0
blockN=28, ec=-1, dirty_flag=0
blockN=29, ec=-1, dirty_flag=0
blockN=30, ec=-1, dirty_flag=0
blockN=31, ec=-1, dirty_flag=0
aml_nand_scan_rsv_info 1134: page_num=32
aml_nand_scan_rsv_info 1137
nenv valid addr: 31
nkey: info size=0x8000 max_scan_blk=40, start_blk=32
nkey : phy_blk_addr=33, ec=0, phy_page_addr=0, timestamp=2
nkey fr

[PATCH v2 2/2] pinctr: qcom: sm8250: add special pins pins configuration data

2024-09-11 Thread Neil Armstrong
Add the special pins configuration data to allow setup the bias
of the UFS and SDCard pins on the SM8250 SoC.

Signed-off-by: Neil Armstrong 
---
 drivers/pinctrl/qcom/pinctrl-sm8250.c | 42 +++
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c 
b/drivers/pinctrl/qcom/pinctrl-sm8250.c
index dac24f11bc2..cab42fa64ed 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c
@@ -18,8 +18,37 @@
 static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
 
 static const struct pinctrl_function msm_pinctrl_functions[] = { { "qup12", 1 
},
-{ "gpio", 0 },
-{ "sdc2_clk", 
0 } };
+{ "gpio", 0 }, 
};
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)  \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = ctl, \
+   .io_reg = 0,\
+   .pull_bit = pull,   \
+   .drv_bit = drv, \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = -1,  \
+   }
+
+#define UFS_RESET(pg_name, offset) \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = offset,  \
+   .io_reg = offset + 0x4, \
+   .pull_bit = 3,  \
+   .drv_bit = 0,   \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = 0,   \
+   }
+
+static const struct msm_special_pin_data sm8250_special_pins_data[] = {
+   [0] = UFS_RESET("ufs_reset", SOUTH + 0xb8000),
+   [1] = SDC_PINGROUP("sdc2_clk", NORTH + 0xb7000, 14, 6),
+   [2] = SDC_PINGROUP("sdc2_cmd", NORTH + 0xb7000, 11, 3),
+   [3] = SDC_PINGROUP("sdc2_data", NORTH + 0xb7000, 9, 0),
+};
 
 static const unsigned int sm8250_pin_offsets[] = {
[0] = SOUTH,   [1] = SOUTH,   [2] = SOUTH,   [3] = SOUTH,   [4] = 
NORTH,   [5] = NORTH,
@@ -52,7 +81,6 @@ static const unsigned int sm8250_pin_offsets[] = {
[162] = WEST,  [163] = WEST,  [164] = WEST,  [165] = WEST,  [166] = 
WEST,  [167] = WEST,
[168] = WEST,  [169] = WEST,  [170] = WEST,  [171] = WEST,  [172] = 
WEST,  [173] = WEST,
[174] = WEST,  [175] = WEST,  [176] = WEST,  [177] = WEST,  [178] = 
WEST,  [179] = WEST,
-   [180] = 0, [181] = 0, [182] = 0, [183] = 0,
 };
 
 static const char *sm8250_get_function_name(struct udevice *dev, unsigned int 
selector)
@@ -62,7 +90,12 @@ static const char *sm8250_get_function_name(struct udevice 
*dev, unsigned int se
 
 static const char *sm8250_get_pin_name(struct udevice *dev, unsigned int 
selector)
 {
-   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+   if (selector >= 180 && selector <= 183)
+   snprintf(pin_name, MAX_PIN_NAME_LEN,
+sm8250_special_pins_data[selector - 180].name);
+   else
+   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+
return pin_name;
 }
 
@@ -76,6 +109,7 @@ static struct msm_pinctrl_data sm8250_data = {
.pin_offsets = sm8250_pin_offsets,
.pin_count = ARRAY_SIZE(sm8250_pin_offsets),
.special_pins_start = 180,
+   .special_pins_data = sm8250_special_pins_data,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = sm8250_get_function_name,

-- 
2.34.1



[PATCH v2 1/2] gpio: msm: add support for special pins

2024-09-11 Thread Neil Armstrong
Leverage the data introduced in the struct msm_special_pin_data to allow
setting the gpio direction and value if supported by the pin data.

Signed-off-by: Neil Armstrong 
---
 drivers/gpio/msm_gpio.c | 97 +
 1 file changed, 89 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index 2fb266f1285..cea073b3297 100644
--- a/drivers/gpio/msm_gpio.c
+++ b/drivers/gpio/msm_gpio.c
@@ -34,13 +34,31 @@ struct msm_gpio_bank {
 #define GPIO_IN_OUT_REG(dev, x) \
(GPIO_CONFIG_REG(dev, x) + 0x4)
 
+static void msm_gpio_direction_input_special(struct msm_gpio_bank *priv,
+unsigned int gpio)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return;
+
+   data = &priv->pin_data->special_pins_data[offset];
+
+   if (!data->ctl_reg || data->oe_bit >= 31)
+   return;
+
+   /* switch direction */
+   clrsetbits_le32(priv->base + data->ctl_reg,
+   BIT(data->oe_bit), 0);
+}
+
 static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
 {
struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-   /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
-   return;
+   msm_gpio_direction_input_special(priv, gpio);
 
/* Disable OE bit */
clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
@@ -49,13 +67,33 @@ static void msm_gpio_direction_input(struct udevice *dev, 
unsigned int gpio)
return;
 }
 
+static int msm_gpio_set_value_special(struct msm_gpio_bank *priv,
+ unsigned int gpio, int value)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return 0;
+
+   data = &priv->pin_data->special_pins_data[offset];
+
+   if (!data->io_reg || data->out_bit >= 31)
+   return 0;
+
+   value = !!value;
+   /* set value */
+   writel(value << data->out_bit, priv->base + data->io_reg);
+
+   return 0;
+}
+
 static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int 
value)
 {
struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-   /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
-   return 0;
+   return msm_gpio_set_value_special(priv, gpio, value);
 
value = !!value;
/* set value */
@@ -64,14 +102,42 @@ static int msm_gpio_set_value(struct udevice *dev, 
unsigned int gpio, int value)
return 0;
 }
 
+static int msm_gpio_direction_output_special(struct msm_gpio_bank *priv,
+unsigned int gpio,
+int value)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return 0;
+
+   data = &priv->pin_data->special_pins_data[offset];
+
+   if (!data->io_reg || data->out_bit >= 31)
+   return 0;
+
+   value = !!value;
+   /* set value */
+   writel(value << data->out_bit, priv->base + data->io_reg);
+
+   if (!data->ctl_reg || data->oe_bit >= 31)
+   return 0;
+
+   /* switch direction */
+   clrsetbits_le32(priv->base + data->ctl_reg,
+   BIT(data->oe_bit), BIT(data->oe_bit));
+
+   return 0;
+}
+
 static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
 int value)
 {
struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-   /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
-   return 0;
+   return msm_gpio_direction_output_special(priv, gpio, value);
 
value = !!value;
/* set value */
@@ -100,13 +166,28 @@ static int msm_gpio_set_flags(struct udevice *dev, 
unsigned int gpio, ulong flag
return 0;
 }
 
+static int msm_gpio_get_value_special(struct msm_gpio_bank *priv, unsigned int 
gpio)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return 0;
+
+   data = &priv->pin_data->special_pins_data[offse

[PATCH v2 0/2] qcom: allow msm_gpio to set special pins direction & value

2024-09-11 Thread Neil Armstrong
After struct msm_special_pin_data was introduced in [1], use the data
to setup the pin direction and/or value if supported by the pin data.

Add the proper msm_special_pin_data for sm8250 after sm8550 and sm8650.

[1] 
https://lore.kernel.org/all/20240528-topic-sm8x50-pinctrl-pinconf-v1-0-54d1e9ad7...@linaro.org/

Signed-off-by: Neil Armstrong 
---
Changes in v2:
- dropped last line of sm8250_pin_offsets
- Link to v1: 
https://lore.kernel.org/r/20240910-topic-sm8x50-msm-gpio-special-pins-sm8250-v1-0-50623a7e4...@linaro.org

---
Neil Armstrong (2):
  gpio: msm: add support for special pins
  pinctr: qcom: sm8250: add special pins pins configuration data

 drivers/gpio/msm_gpio.c   | 97 ---
 drivers/pinctrl/qcom/pinctrl-sm8250.c | 42 +--
 2 files changed, 127 insertions(+), 12 deletions(-)
---
base-commit: ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac
change-id: 20240910-topic-sm8x50-msm-gpio-special-pins-sm8250-943311b483e2

Best regards,
-- 
Neil Armstrong 



Re: [PATCH v3 2/3] pinctrl: qcom: add driver for SM8150 SoC

2024-09-11 Thread Neil Armstrong
T,  [106] = WEST,  [107] = WEST,
+   [108] = WEST,  [109] = WEST,  [110] = WEST,  [111] = WEST,
+   [112] = WEST,  [113] = WEST,  [114] = SOUTH, [115] = SOUTH,
+   [116] = SOUTH, [117] = SOUTH, [118] = SOUTH, [119] = SOUTH,
+   [120] = SOUTH, [121] = SOUTH, [122] = SOUTH, [123] = SOUTH,
+   [124] = SOUTH, [125] = WEST,  [126] = SOUTH, [127] = SOUTH,
+   [128] = SOUTH, [129] = SOUTH, [130] = SOUTH, [131] = SOUTH,
+   [132] = SOUTH, [133] = SOUTH, [134] = SOUTH, [135] = SOUTH,
+   [136] = SOUTH, [137] = SOUTH, [138] = SOUTH, [139] = SOUTH,
+   [140] = SOUTH, [141] = SOUTH, [142] = SOUTH, [143] = SOUTH,
+   [144] = SOUTH, [145] = SOUTH, [146] = SOUTH, [147] = SOUTH,
+   [148] = SOUTH, [149] = SOUTH, [150] = SOUTH, [151] = SOUTH,
+   [152] = SOUTH, [153] = SOUTH, [154] = SOUTH, [155] = WEST,
+   [156] = WEST,  [157] = WEST,  [158] = WEST,  [159] = WEST,
+   [160] = WEST,  [161] = WEST,  [162] = WEST,  [163] = WEST,
+   [164] = WEST,  [165] = WEST,  [166] = WEST,  [167] = WEST,
+   [168] = WEST,  [169] = NORTH, [170] = NORTH, [171] = NORTH,
+   [172] = NORTH, [173] = NORTH, [174] = NORTH,
+};
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = ctl, \
+   .io_reg = 0,\
+   .pull_bit = pull,   \
+   .drv_bit = drv, \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = -1,  \
+   }
+
+#define UFS_RESET(pg_name, offset)\
+   { \
+   .name = pg_name,  \
+   .ctl_reg = offset,\
+   .io_reg = offset + 0x04,  \
+   .pull_bit = 3,\
+   .drv_bit = 0, \
+   .oe_bit = -1, \
+   .in_bit = -1, \
+   .out_bit = 0, \
+   }
+
+static const struct msm_special_pin_data msm_special_pins_data[] = {
+   [0] = UFS_RESET("ufs_reset", SOUTH + 0xb6000),
+   [1] = SDC_QDSD_PINGROUP("sdc2_clk", NORTH + 0xb2000, 14, 6),
+   [2] = SDC_QDSD_PINGROUP("sdc2_cmd", NORTH + 0xb2000, 11, 3),
+   [3] = SDC_QDSD_PINGROUP("sdc2_data", NORTH + 0xb2000, 9, 0),
+};
+
+static const char *sm8150_get_function_name(struct udevice *dev,
+   unsigned int selector)
+{
+   return msm_pinctrl_functions[selector].name;
+}
+
+static const char *sm8150_get_pin_name(struct udevice *dev,
+  unsigned int selector)
+{
+   if (selector >= 175 && selector <= 178)
+   snprintf(pin_name, MAX_PIN_NAME_LEN,
+msm_special_pins_data[selector - 175].name);
+   else
+   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+
+   return pin_name;
+}
+
+static unsigned int sm8150_get_function_mux(__maybe_unused unsigned int pin,
+   unsigned int selector)
+{
+   return msm_pinctrl_functions[selector].val;
+}
+
+static struct msm_pinctrl_data sm8150_data = {
+   .pin_data = {
+   .pin_offsets = sm8150_pin_offsets,
+   .pin_count = 179,
+   .special_pins_start = 175,
+   .special_pins_data = msm_special_pins_data,
+   },
+   .functions_count = ARRAY_SIZE(msm_pinctrl_functions),
+   .get_function_name = sm8150_get_function_name,
+   .get_function_mux = sm8150_get_function_mux,
+   .get_pin_name = sm8150_get_pin_name,
+};
+
+static const struct udevice_id msm_pinctrl_ids[] = {
+   { .compatible = "qcom,sm8150-pinctrl", .data = (ulong)&sm8150_data },
+   { /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(pinctrl_sm8150) = {
+   .name   = "pinctrl_sm8150",
+   .id = UCLASS_NOP,
+   .of_match   = msm_pinctrl_ids,
+   .ops= &msm_pinctrl_ops,
+   .bind   = msm_pinctrl_bind,
+};



Reviewed-by: Neil Armstrong 


Re: [PATCH v3 3/3] config: qcom: add sm8150 to qcom_defconfig

2024-09-11 Thread Neil Armstrong

On 11/09/2024 19:13, Julius Lehmann wrote:

Enable clk and pinctrl for sm8150

Signed-off-by: Julius Lehmann 
Reviewed-by: Caleb Connolly 
---
  configs/qcom_defconfig | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index 2a2253f766..e7ed03ff0f 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -48,6 +48,7 @@ CONFIG_CLK_QCOM_QCS404=y
  CONFIG_CLK_QCOM_SC7280=y
  CONFIG_CLK_QCOM_SDM845=y
  CONFIG_CLK_QCOM_SM6115=y
+CONFIG_CLK_QCOM_SM8150=y
  CONFIG_CLK_QCOM_SM8250=y
  CONFIG_CLK_QCOM_SM8550=y
  CONFIG_CLK_QCOM_SM8650=y
@@ -86,6 +87,7 @@ CONFIG_PINCTRL_QCOM_QCM2290=y
  CONFIG_PINCTRL_QCOM_QCS404=y
  CONFIG_PINCTRL_QCOM_SDM845=y
  CONFIG_PINCTRL_QCOM_SM6115=y
+CONFIG_PINCTRL_QCOM_SM8150=y
  CONFIG_PINCTRL_QCOM_SM8250=y
  CONFIG_PINCTRL_QCOM_SM8550=y
  CONFIG_PINCTRL_QCOM_SM8650=y



Reviewed-by: Neil Armstrong 


Re: [PATCH v3 1/3] clk: qcom: add driver for SM8150 SoC

2024-09-11 Thread Neil Armstrong
  qcom_gate_clk_en(priv, GCC_USB3_SEC_PHY_AUX_CLK);
+   qcom_gate_clk_en(priv, GCC_USB3_SEC_PHY_COM_AUX_CLK);
+   break;
+   };
+
+   qcom_gate_clk_en(priv, clk->id);
+
+   return 0;
+}
+
+static const struct qcom_reset_map sm8150_gcc_resets[] = {
+   [GCC_EMAC_BCR] = { 0x6000 },
+   [GCC_GPU_BCR] = { 0x71000 },
+   [GCC_MMSS_BCR] = { 0xb000 },
+   [GCC_NPU_BCR] = { 0x4d000 },
+   [GCC_PCIE_0_BCR] = { 0x6b000 },
+   [GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+   [GCC_PCIE_1_BCR] = { 0x8d000 },
+   [GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
+   [GCC_PCIE_PHY_BCR] = { 0x6f000 },
+   [GCC_PDM_BCR] = { 0x33000 },
+   [GCC_PRNG_BCR] = { 0x34000 },
+   [GCC_QSPI_BCR] = { 0x24008 },
+   [GCC_QUPV3_WRAPPER_0_BCR] = { 0x17000 },
+   [GCC_QUPV3_WRAPPER_1_BCR] = { 0x18000 },
+   [GCC_QUPV3_WRAPPER_2_BCR] = { 0x1e000 },
+   [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
+   [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
+   [GCC_USB3_PHY_PRIM_BCR] = { 0x5 },
+   [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 },
+   [GCC_USB3_PHY_SEC_BCR] = { 0x5000c },
+   [GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 },
+   [GCC_SDCC2_BCR] = { 0x14000 },
+   [GCC_SDCC4_BCR] = { 0x16000 },
+   [GCC_TSIF_BCR] = { 0x36000 },
+   [GCC_UFS_CARD_BCR] = { 0x75000 },
+   [GCC_UFS_PHY_BCR] = { 0x77000 },
+   [GCC_USB30_PRIM_BCR] = { 0xf000 },
+   [GCC_USB30_SEC_BCR] = { 0x1 },
+   [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+};
+
+static const struct qcom_power_map sm8150_gcc_power_domains[] = {
+   [EMAC_GDSC] = { 0x6004 },
+   [PCIE_0_GDSC] = { 0x6b004 },
+   [PCIE_1_GDSC] = { 0x8d004 },
+   [UFS_CARD_GDSC] = { 0x75004 },
+   [UFS_PHY_GDSC] = { 0x77004 },
+   [USB30_PRIM_GDSC] = { 0xf004 },
+   [USB30_SEC_GDSC] = { 0x10004 },
+};
+
+static struct msm_clk_data sm8150_clk_data = {
+   .resets = sm8150_gcc_resets,
+   .num_resets = ARRAY_SIZE(sm8150_gcc_resets),
+   .clks = sm8150_clks,
+   .num_clks = ARRAY_SIZE(sm8150_clks),
+   .power_domains = sm8150_gcc_power_domains,
+   .num_power_domains = ARRAY_SIZE(sm8150_gcc_power_domains),
+
+   .enable = sm8150_clk_enable,
+   .set_rate = sm8150_clk_set_rate,
+};
+
+static const struct udevice_id gcc_sm8150_of_match[] = {
+   {
+   .compatible = "qcom,gcc-sm8150",
+   .data = (ulong)&sm8150_clk_data,
+   },
+   { }
+};
+
+U_BOOT_DRIVER(gcc_sm8150) = {
+   .name   = "gcc_sm8150",
+   .id = UCLASS_NOP,
+   .of_match   = gcc_sm8150_of_match,
+   .bind   = qcom_cc_bind,
+   .flags  = DM_FLAG_PRE_RELOC,
+};



Reviewed-by: Neil Armstrong 


Re: [PATCH 2/3] pinctrl: qcom: add driver for SM8150 SoC

2024-09-11 Thread neil . armstrong

On 10/09/2024 18:01, Julius Lehmann wrote:

Hi Neil and Caleb,

thank you for taking a look at my patch.

On 10.09.24 14:07, Neil Armstrong wrote:

On 10/09/2024 14:05, Caleb Connolly wrote:

Hi Julius,

Thanks for the patch!

On 09/09/2024 17:53, Julius Lehmann wrote:

Add pinctrl and GPIO driver for SM8150. Driver code is based on the
similar U-Boot drivers. All constants are taken from the corresponding
Linux driver. This drivers differs from the similar U-Boot drivers,
because SM8150 SoC have different function IDs for the same functions
on different pins.

Co-authored-by: Volodymyr Babchuk 
Signed-off-by: Julius Lehmann 
---

  drivers/pinctrl/qcom/Kconfig  |   8 ++
  drivers/pinctrl/qcom/Makefile |   1 +
  drivers/pinctrl/qcom/pinctrl-sm8150.c | 119 ++
  3 files changed, 128 insertions(+)
  create mode 100644 drivers/pinctrl/qcom/pinctrl-sm8150.c

diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index b326fa8514..501939f783 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -74,6 +74,14 @@ config PINCTRL_QCOM_SM8650
  select PINCTRL_QCOM
  help
    Say Y here to enable support for pinctrl on the Snapdragon SM8650 SoC,
+  as well as the associated GPIO driver.
+
+config PINCTRL_QCOM_SM8150
+    bool "Qualcomm SM8150 GCC"
+    select PINCTRL_QCOM
+    help
+  Say Y here to enable support for pinctrl on the Snapdragon SM8150 SoC,
+  as well as the associated GPIO driver.
    endmenu
  diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 4f1d96787b..cc3660a576 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o
  obj-$(CONFIG_PINCTRL_QCOM_SM8250) += pinctrl-sm8250.o
  obj-$(CONFIG_PINCTRL_QCOM_SM8550) += pinctrl-sm8550.o
  obj-$(CONFIG_PINCTRL_QCOM_SM8650) += pinctrl-sm8650.o
+obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c 
b/drivers/pinctrl/qcom/pinctrl-sm8150.c
new file mode 100644
index 00..c3af3448f6
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Qualcomm SM8150 pinctrl and GPIO driver
+ *
+ * Volodymyr Babchuk 
+ * Copyright (c) 2024 EPAM Systems.
+ *
+ * (C) Copyright 2024 Julius Lehmann 
+ *
+ * Based on similar U-Boot drivers. Constants were taken from the Linux driver
+ */
+
+#include 
+
+#include "pinctrl-qcom.h"
+
+#define WEST    0x0010
+#define EAST    0x0050
+#define NORTH    0x0090
+#define SOUTH    0x00D0
+
+#define MAX_PIN_NAME_LEN 32
+static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
+
+static const struct pinctrl_function msm_pinctrl_functions[] = { { "qup2", 1 },
+ { "gpio", 0 },
+    { "sdc4", 0 } };
+
+static const unsigned int sm8150_pin_offsets[] = {
+    [0]   = SOUTH, [1]   = SOUTH, [2]   = SOUTH, [3]   = SOUTH,
+    [4]   = SOUTH, [5]   = SOUTH, [6]   = SOUTH, [7]   = SOUTH,
+    [8]   = NORTH, [9]   = NORTH, [10]  = NORTH, [11]  = NORTH,
+    [12]  = NORTH, [13]  = NORTH, [14]  = NORTH, [15]  = NORTH,
+    [16]  = NORTH, [17]  = NORTH, [18]  = NORTH, [19]  = NORTH,
+    [20]  = NORTH, [21]  = EAST,  [22]  = EAST,  [23]  = EAST,
+    [24]  = EAST,  [25]  = EAST,  [26]  = EAST,  [27]  = EAST,
+    [28]  = EAST,  [29]  = EAST,  [30]  = EAST,  [31]  = NORTH,
+    [32]  = NORTH, [33]  = NORTH, [34]  = NORTH, [35]  = NORTH,
+    [36]  = NORTH, [37]  = NORTH, [38]  = SOUTH, [39]  = NORTH,
+    [40]  = NORTH, [41]  = NORTH, [42]  = NORTH, [43]  = EAST,
+    [44]  = EAST,  [45]  = EAST,  [46]  = EAST,  [47]  = EAST,
+    [48]  = EAST,  [49]  = EAST,  [50]  = EAST,  [51]  = SOUTH,
+    [52]  = SOUTH, [53]  = SOUTH, [54]  = SOUTH, [55]  = SOUTH,
+    [56]  = SOUTH, [57]  = SOUTH, [58]  = SOUTH, [59]  = SOUTH,
+    [60]  = SOUTH, [61]  = SOUTH, [62]  = SOUTH, [63]  = SOUTH,
+    [64]  = SOUTH, [65]  = SOUTH, [66]  = SOUTH, [67]  = SOUTH,
+    [68]  = SOUTH, [69]  = SOUTH, [70]  = SOUTH, [71]  = SOUTH,
+    [72]  = SOUTH, [73]  = SOUTH, [74]  = SOUTH, [75]  = SOUTH,
+    [76]  = SOUTH, [77]  = SOUTH, [78]  = SOUTH, [79]  = SOUTH,
+    [80]  = SOUTH, [81]  = SOUTH, [82]  = SOUTH, [83]  = NORTH,
+    [84]  = NORTH, [85]  = NORTH, [86]  = NORTH, [87]  = EAST,
+    [88]  = NORTH, [89]  = NORTH, [90]  = NORTH, [91]  = NORTH,
+    [92]  = NORTH, [93]  = NORTH, [94]  = NORTH, [95]  = NORTH,
+    [96]  = NORTH, [97]  = NORTH, [98]  = SOUTH, [99]  = SOUTH,
+    [100] = SOUTH, [101] = SOUTH, [102] = NORTH, [103] = NORTH,
+    [104] = NORTH, [105] = WEST,  [106] = WEST,  [107] = WEST,
+    [108] = WEST,  [109] = WEST,  [110] = WEST,  [111] = WEST,
+    [112] = WEST,  [113] = WEST,  [114] = SOUTH, [115] = SOUTH,
+    [116] = SOUTH, [117] = SOUTH, [118] = SOUTH, [119] = S

Re: [PATCH 12/13] ufs: core: remove link_startup_again logic

2024-09-10 Thread Neil Armstrong

Hi,

On 10/09/2024 13:36, Neha Malcom Francis wrote:

Hi Neil

On 10/09/24 14:50, Neil Armstrong wrote:

The link_startup_again logic was added in Linux to handle device
that were set in LinkDown state, which should not be the case since U-boot
doesn't set LinkDown state are init, and Linux sets the device active
in ufshcd_init() for the first link startup.

While it worked to far, it breaks link startup for Qualcomm Controllers v5,
let's just remove the logic.

Signed-off-by: Neil Armstrong 


I had sent a review comment here 
https://patchwork.ozlabs.org/project/uboot/patch/20240528-topic-sm8x50-ufs-core-link-startup-again-v1-1-146ca43e8...@linaro.org/


Indeed I missed it, I'll fix the commit msg.

Nevertheless, as I explain in the cover letter the double link startup is
not done in Linux for the initial power-up:
https://elixir.bootlin.com/linux/v6.10.9/source/drivers/ufs/core/ufshcd.c#L10548

ufshcd_set_ufs_dev_active(hba) is called at ufshcd_init() right before
scheduling an ufshcd_async_scan that will call ufshcd_device_init() then 
ufshcd_link_startup().

The comment in probe says:
/*
 * We are assuming that device wasn't put in sleep/power-down
 * state exclusively during the boot stage before kernel.
 * This assumption helps avoid doing link startup twice during
 * ufshcd_probe_hba().
 */
we can assume the same from U-boot.

Neil


Would like Bhupesh to also have a look at this.


---
  drivers/ufs/ufs.c | 8 
  1 file changed, 8 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index d2df5c26f76..e34e4586224 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -462,9 +462,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
  {
  int ret;
  int retries = DME_LINKSTARTUP_RETRIES;
-    bool link_startup_again = true;
-link_startup:
  do {
  ufshcd_ops_link_startup_notify(hba, PRE_CHANGE);
@@ -490,12 +488,6 @@ link_startup:
  /* failed to get the link up... retire */
  goto out;
-    if (link_startup_again) {
-    link_startup_again = false;
-    retries = DME_LINKSTARTUP_RETRIES;
-    goto link_startup;
-    }
-
  /* Mark that link is up in PWM-G1, 1-lane, SLOW-AUTO mode */
  ufshcd_init_pwr_info(hba);







Re: [PATCH 2/2] pinctr: qcom: sm8250: add special pins pins configuration data

2024-09-10 Thread Neil Armstrong

On 10/09/2024 14:14, Caleb Connolly wrote:



On 10/09/2024 10:58, Neil Armstrong wrote:

Add the special pins configuration data to allow setup the bias
of the UFS and SDCard pins on the SM8250 SoC.

Signed-off-by: Neil Armstrong 
---
  drivers/pinctrl/qcom/pinctrl-sm8250.c | 41 ---
  1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c 
b/drivers/pinctrl/qcom/pinctrl-sm8250.c
index dac24f11bc2..69c907e3868 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c
@@ -18,8 +18,37 @@
  static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
  
  static const struct pinctrl_function msm_pinctrl_functions[] = { { "qup12", 1 },

-{ "gpio", 0 },
-{ "sdc2_clk", 
0 } };
+{ "gpio", 0 }, 
};
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)  \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = ctl, \
+   .io_reg = 0,\
+   .pull_bit = pull,   \
+   .drv_bit = drv, \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = -1,  \
+   }
+
+#define UFS_RESET(pg_name, offset) \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = offset,  \
+   .io_reg = offset + 0x4, \
+   .pull_bit = 3,  \
+   .drv_bit = 0,   \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = 0,   \
+   }
+
+static const struct msm_special_pin_data sm8250_special_pins_data[] = {
+   [0] = UFS_RESET("ufs_reset", SOUTH + 0xb8000),
+   [1] = SDC_PINGROUP("sdc2_clk", NORTH + 0xb7000, 14, 6),
+   [2] = SDC_PINGROUP("sdc2_cmd", NORTH + 0xb7000, 11, 3),
+   [3] = SDC_PINGROUP("sdc2_data", NORTH + 0xb7000, 9, 0),
+};
  
  static const unsigned int sm8250_pin_offsets[] = {


Could you also remove the special pin entries at the end of this array?


Sure !

Neil



Kind regards,

[0] = SOUTH,   [1] = SOUTH,   [2] = SOUTH,   [3] = SOUTH,   [4] = 
NORTH,   [5] = NORTH,
@@ -62,7 +91,12 @@ static const char *sm8250_get_function_name(struct udevice 
*dev, unsigned int se
  
  static const char *sm8250_get_pin_name(struct udevice *dev, unsigned int selector)

  {
-   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+   if (selector >= 180 && selector <= 183)
+   snprintf(pin_name, MAX_PIN_NAME_LEN,
+sm8250_special_pins_data[selector - 180].name);
+   else
+   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+
return pin_name;
  }
  
@@ -76,6 +110,7 @@ static struct msm_pinctrl_data sm8250_data = {

.pin_offsets = sm8250_pin_offsets,
.pin_count = ARRAY_SIZE(sm8250_pin_offsets),
.special_pins_start = 180,
+   .special_pins_data = sm8250_special_pins_data,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = sm8250_get_function_name,







Re: [PATCH 2/3] pinctrl: qcom: add driver for SM8150 SoC

2024-09-10 Thread Neil Armstrong

On 10/09/2024 14:05, Caleb Connolly wrote:

Hi Julius,

Thanks for the patch!

On 09/09/2024 17:53, Julius Lehmann wrote:

Add pinctrl and GPIO driver for SM8150. Driver code is based on the
similar U-Boot drivers. All constants are taken from the corresponding
Linux driver. This drivers differs from the similar U-Boot drivers,
because SM8150 SoC have different function IDs for the same functions
on different pins.

Co-authored-by: Volodymyr Babchuk 
Signed-off-by: Julius Lehmann 
---

  drivers/pinctrl/qcom/Kconfig  |   8 ++
  drivers/pinctrl/qcom/Makefile |   1 +
  drivers/pinctrl/qcom/pinctrl-sm8150.c | 119 ++
  3 files changed, 128 insertions(+)
  create mode 100644 drivers/pinctrl/qcom/pinctrl-sm8150.c

diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index b326fa8514..501939f783 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -74,6 +74,14 @@ config PINCTRL_QCOM_SM8650
select PINCTRL_QCOM
help
  Say Y here to enable support for pinctrl on the Snapdragon SM8650 SoC,
+ as well as the associated GPIO driver.
+
+config PINCTRL_QCOM_SM8150
+   bool "Qualcomm SM8150 GCC"
+   select PINCTRL_QCOM
+   help
+ Say Y here to enable support for pinctrl on the Snapdragon SM8150 SoC,
+ as well as the associated GPIO driver.
  
  endmenu
  
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile

index 4f1d96787b..cc3660a576 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_PINCTRL_QCOM_SM6115) += pinctrl-sm6115.o
  obj-$(CONFIG_PINCTRL_QCOM_SM8250) += pinctrl-sm8250.o
  obj-$(CONFIG_PINCTRL_QCOM_SM8550) += pinctrl-sm8550.o
  obj-$(CONFIG_PINCTRL_QCOM_SM8650) += pinctrl-sm8650.o
+obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o
diff --git a/drivers/pinctrl/qcom/pinctrl-sm8150.c 
b/drivers/pinctrl/qcom/pinctrl-sm8150.c
new file mode 100644
index 00..c3af3448f6
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-sm8150.c
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Qualcomm SM8150 pinctrl and GPIO driver
+ *
+ * Volodymyr Babchuk 
+ * Copyright (c) 2024 EPAM Systems.
+ *
+ * (C) Copyright 2024 Julius Lehmann 
+ *
+ * Based on similar U-Boot drivers. Constants were taken from the Linux driver
+ */
+
+#include 
+
+#include "pinctrl-qcom.h"
+
+#define WEST   0x0010
+#define EAST   0x0050
+#define NORTH  0x0090
+#define SOUTH  0x00D0
+
+#define MAX_PIN_NAME_LEN 32
+static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
+
+static const struct pinctrl_function msm_pinctrl_functions[] = { { "qup2", 1 },
+{ "gpio", 0 },
+   { "sdc4", 0 } };
+
+static const unsigned int sm8150_pin_offsets[] = {
+   [0]   = SOUTH, [1]   = SOUTH, [2]   = SOUTH, [3]   = SOUTH,
+   [4]   = SOUTH, [5]   = SOUTH, [6]   = SOUTH, [7]   = SOUTH,
+   [8]   = NORTH, [9]   = NORTH, [10]  = NORTH, [11]  = NORTH,
+   [12]  = NORTH, [13]  = NORTH, [14]  = NORTH, [15]  = NORTH,
+   [16]  = NORTH, [17]  = NORTH, [18]  = NORTH, [19]  = NORTH,
+   [20]  = NORTH, [21]  = EAST,  [22]  = EAST,  [23]  = EAST,
+   [24]  = EAST,  [25]  = EAST,  [26]  = EAST,  [27]  = EAST,
+   [28]  = EAST,  [29]  = EAST,  [30]  = EAST,  [31]  = NORTH,
+   [32]  = NORTH, [33]  = NORTH, [34]  = NORTH, [35]  = NORTH,
+   [36]  = NORTH, [37]  = NORTH, [38]  = SOUTH, [39]  = NORTH,
+   [40]  = NORTH, [41]  = NORTH, [42]  = NORTH, [43]  = EAST,
+   [44]  = EAST,  [45]  = EAST,  [46]  = EAST,  [47]  = EAST,
+   [48]  = EAST,  [49]  = EAST,  [50]  = EAST,  [51]  = SOUTH,
+   [52]  = SOUTH, [53]  = SOUTH, [54]  = SOUTH, [55]  = SOUTH,
+   [56]  = SOUTH, [57]  = SOUTH, [58]  = SOUTH, [59]  = SOUTH,
+   [60]  = SOUTH, [61]  = SOUTH, [62]  = SOUTH, [63]  = SOUTH,
+   [64]  = SOUTH, [65]  = SOUTH, [66]  = SOUTH, [67]  = SOUTH,
+   [68]  = SOUTH, [69]  = SOUTH, [70]  = SOUTH, [71]  = SOUTH,
+   [72]  = SOUTH, [73]  = SOUTH, [74]  = SOUTH, [75]  = SOUTH,
+   [76]  = SOUTH, [77]  = SOUTH, [78]  = SOUTH, [79]  = SOUTH,
+   [80]  = SOUTH, [81]  = SOUTH, [82]  = SOUTH, [83]  = NORTH,
+   [84]  = NORTH, [85]  = NORTH, [86]  = NORTH, [87]  = EAST,
+   [88]  = NORTH, [89]  = NORTH, [90]  = NORTH, [91]  = NORTH,
+   [92]  = NORTH, [93]  = NORTH, [94]  = NORTH, [95]  = NORTH,
+   [96]  = NORTH, [97]  = NORTH, [98]  = SOUTH, [99]  = SOUTH,
+   [100] = SOUTH, [101] = SOUTH, [102] = NORTH, [103] = NORTH,
+   [104] = NORTH, [105] = WEST,  [106] = WEST,  [107] = WEST,
+   [108] = WEST,  [109] = WEST,  [110] = WEST,  [111] = WEST,
+   [112] = WEST,  [113] = WEST,  [114] = SOUTH, [115] = SOUTH,
+   [116] = SOUTH, [117] = SOUTH, [118] = SOUTH, [119] = SOUTH,
+   [120] = SOUTH, [121] = SOUT

[PATCH 0/4] ufs: add support for Qualcomm UFS Controller

2024-09-10 Thread Neil Armstrong
This iass Add Support for the Host Controller driver for UFS HC
present on Qualcomm Snapdragon SoCs.

It adds 2 ops to allow more control on the UFS device.

It has been successfully tested on SDM845, SM8250, SM8550 ant SM8650 SoCs.

It builds-depends on the following serie:
https://lore.kernel.org/all/20240910-topic-ufs-enhancements-v1-0-3ee0bffac...@linaro.org/

And at runtime it depends on:
https://lore.kernel.org/all/20240910-topic-ufs-qcom-phy-v1-0-21ff4b87b...@linaro.org/

Signed-off-by: Neil Armstrong 
---
Bhupesh Sharma (1):
  ufs: Add Support for Qualcomm UFS HC driver

Neil Armstrong (3):
  ufs: add device_reset callback
  ufs: add get_max_pwr_mode callback
  ufs: allow UFSHCI version 4.0

 drivers/ufs/Kconfig|   7 +
 drivers/ufs/Makefile   |   1 +
 drivers/ufs/ufs-qcom.c | 670 +
 drivers/ufs/ufs-qcom.h | 147 +++
 drivers/ufs/ufs.c  |  13 +-
 drivers/ufs/ufs.h  |  21 ++
 drivers/ufs/unipro.h   |   6 +
 7 files changed, 863 insertions(+), 2 deletions(-)
---
base-commit: 7725e4eb07c03ca0842b0a7ed425af28e1b8ed37
change-id: 20240910-topic-ufs-qcom-controller-4b2905610963

Best regards,
-- 
Neil Armstrong 



[PATCH 4/4] ufs: Add Support for Qualcomm UFS HC driver

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Add Support for the Host Controller driver for UFS HC
present on Qualcomm Snapdragon SoCs.

It has been successfully tested on SDM845, SM8250,
SM8550 ant SM8650 SoCs.

Signed-off-by: Bhupesh Sharma 
Signed-off-by: Neil Armstrong 
---
 drivers/ufs/Kconfig|   7 +
 drivers/ufs/Makefile   |   1 +
 drivers/ufs/ufs-qcom.c | 670 +
 drivers/ufs/ufs-qcom.h | 147 +++
 drivers/ufs/unipro.h   |   6 +
 5 files changed, 831 insertions(+)

diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig
index 7da46faed6b..0ca1f2ae7dc 100644
--- a/drivers/ufs/Kconfig
+++ b/drivers/ufs/Kconfig
@@ -26,6 +26,13 @@ config UFS_PCI
 
  If unsure, say N.
 
+config QCOM_UFS
+   bool "Qualcomm Host Controller driver for UFS"
+   depends on UFS && ARCH_SNAPDRAGON
+help
+ This selects the platform driver for the UFS host
+ controller present on Qualcomm Snapdragon SoCs.
+
 config TI_J721E_UFS
bool "Glue Layer driver for UFS on TI J721E devices"
help
diff --git a/drivers/ufs/Makefile b/drivers/ufs/Makefile
index 67c42621aba..024382cd2ce 100644
--- a/drivers/ufs/Makefile
+++ b/drivers/ufs/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_UFS) += ufs.o ufs-uclass.o
 obj-$(CONFIG_CADENCE_UFS) += cdns-platform.o
+obj-$(CONFIG_QCOM_UFS) += ufs-qcom.o
 obj-$(CONFIG_TI_J721E_UFS) += ti-j721e-ufs.o
 obj-$(CONFIG_UFS_PCI) += ufs-pci.o
 obj-$(CONFIG_UFS_RENESAS) += ufs-renesas.o
diff --git a/drivers/ufs/ufs-qcom.c b/drivers/ufs/ufs-qcom.c
new file mode 100644
index 000..843585726c7
--- /dev/null
+++ b/drivers/ufs/ufs-qcom.c
@@ -0,0 +1,670 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
+ * Copyright (C) 2023-2024 Linaro Limited
+ * Authors:
+ * - Bhupesh Sharma 
+ * - Neil Armstrong 
+ *
+ * Based on Linux driver
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "ufs.h"
+#include "ufs-qcom.h"
+
+#define ceil(freq, div) ((freq) % (div) == 0 ? ((freq) / (div)) : ((freq) / 
(div) + 1))
+
+static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_hba *hba, bool enable);
+
+static int ufs_qcom_enable_clks(struct ufs_qcom_priv *priv)
+{
+   int err;
+
+   if (priv->is_clks_enabled)
+   return 0;
+
+   err = clk_enable_bulk(&priv->clks);
+   if (err)
+   return err;
+
+   priv->is_clks_enabled = true;
+
+   return 0;
+}
+
+static int ufs_qcom_init_clks(struct ufs_qcom_priv *priv)
+{
+   int err;
+   struct udevice *dev = priv->hba->dev;
+
+   err = clk_get_bulk(dev, &priv->clks);
+   if (err)
+   return err;
+
+   return 0;
+}
+
+static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
+{
+   int err, retry_count = 50;
+   u32 tx_fsm_val = 0;
+
+   do {
+   err = ufshcd_dme_get(hba,
+   UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+   UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+   &tx_fsm_val);
+   if (err || tx_fsm_val == TX_FSM_HIBERN8)
+   break;
+
+   /* max. 200us */
+   udelay(200);
+   retry_count--;
+   } while (retry_count != 0);
+
+   /* Check the state again */
+   err = ufshcd_dme_get(hba,
+   UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+   UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+   &tx_fsm_val);
+
+   if (err) {
+   dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
+   __func__, err);
+   } else if (tx_fsm_val != TX_FSM_HIBERN8) {
+   err = tx_fsm_val;
+   dev_err(hba->dev, "%s: invalid TX_FSM_STATE = %d\n",
+   __func__, err);
+   }
+
+   return err;
+}
+
+static void ufs_qcom_select_unipro_mode(struct ufs_qcom_priv *priv)
+{
+   ufshcd_rmwl(priv->hba, QUNIPRO_SEL, QUNIPRO_SEL, REG_UFS_CFG1);
+
+   if (priv->hw_ver.major >= 0x05)
+   ufshcd_rmwl(priv->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0);
+}
+
+/*
+ * ufs_qcom_reset - reset host controller and PHY
+ */
+static int ufs_qcom_reset(struct ufs_hba *hba)
+{
+   struct ufs_qcom_priv *priv = dev_get_priv(hba->dev);
+   int ret;
+
+   ret = reset_assert(&priv->core_reset);
+   if (ret) {
+   dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n",
+   __func__, ret);
+   return ret;
+   }
+
+   /*
+* The hardware requirement for delay between assert/deassert
+* is at least 3-4 sleep clock (32.7KHz) cycles, which comes to
+* ~125us (4/3276

[PATCH 3/4] ufs: allow UFSHCI version 4.0

2024-09-10 Thread Neil Armstrong
Add UFSHCI version 4.0 found on the recent Qualcomm UFS Controllers.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 3 ++-
 drivers/ufs/ufs.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 1edd31677b2..f7d8c40c448 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -1974,7 +1974,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct 
ufs_hba_ops *hba_ops)
hba->version != UFSHCI_VERSION_20 &&
hba->version != UFSHCI_VERSION_21 &&
hba->version != UFSHCI_VERSION_30 &&
-   hba->version != UFSHCI_VERSION_31)
+   hba->version != UFSHCI_VERSION_31 &&
+   hba->version != UFSHCI_VERSION_40)
dev_err(hba->dev, "invalid UFS version 0x%x\n",
hba->version);
 
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index fb47d0cd3a4..2ab593455e9 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -906,6 +906,7 @@ enum {
UFSHCI_VERSION_21 = 0x0210, /* 2.1 */
UFSHCI_VERSION_30 = 0x0300, /* 3.0 */
UFSHCI_VERSION_31 = 0x0310, /* 3.1 */
+   UFSHCI_VERSION_40 = 0x0400, /* 4.0 */
 };
 
 /* Interrupt disable masks */

-- 
2.34.1



[PATCH 2/4] ufs: add get_max_pwr_mode callback

2024-09-10 Thread Neil Armstrong
Add a new get_max_pwr_mode callback to permit the UFS controller
driver manipulate the max_pwr_mode struct right before setting
the new pwr_mode to the UFS device.

It can be used to limit the HS Gear with errata and hardware
limitations on some UFS controllers.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c |  2 +-
 drivers/ufs/ufs.h | 11 +++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index de8ba011d57..1edd31677b2 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -1744,7 +1744,7 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba)
}
 
hba->max_pwr_info.is_valid = true;
-   return 0;
+   return ufshcd_ops_get_max_pwr_mode(hba, &hba->max_pwr_info);
 }
 
 static int ufshcd_change_power_mode(struct ufs_hba *hba,
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index faaebf1f9f7..fb47d0cd3a4 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -696,6 +696,8 @@ struct ufs_dev_cmd {
 
 struct ufs_hba_ops {
int (*init)(struct ufs_hba *hba);
+   int (*get_max_pwr_mode)(struct ufs_hba *hba,
+   struct ufs_pwr_mode_info *max_pwr_info);
int (*hce_enable_notify)(struct ufs_hba *hba,
 enum ufs_notify_change_status);
int (*link_startup_notify)(struct ufs_hba *hba,
@@ -861,6 +863,15 @@ static inline int ufshcd_ops_init(struct ufs_hba *hba)
return 0;
 }
 
+static inline int ufshcd_ops_get_max_pwr_mode(struct ufs_hba *hba,
+ struct ufs_pwr_mode_info 
*max_pwr_info)
+{
+   if (hba->ops && hba->ops->get_max_pwr_mode)
+   return hba->ops->get_max_pwr_mode(hba, max_pwr_info);
+
+   return 0;
+}
+
 static inline int ufshcd_ops_hce_enable_notify(struct ufs_hba *hba,
bool status)
 {

-- 
2.34.1



[PATCH 1/4] ufs: add device_reset callback

2024-09-10 Thread Neil Armstrong
Add device_reset op to permit resetting the UFS device if
the UFS controller drivers supports the operation.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 8 
 drivers/ufs/ufs.h | 9 +
 2 files changed, 17 insertions(+)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index e34e4586224..de8ba011d57 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -125,6 +125,11 @@ static void ufshcd_print_pwr_info(struct ufs_hba *hba)
hba->pwr_info.hs_rate);
 }
 
+static void ufshcd_device_reset(struct ufs_hba *hba)
+{
+   ufshcd_vops_device_reset(hba);
+}
+
 /**
  * ufshcd_ready_for_uic_cmd - Check if controller is ready
  *to accept UIC commands
@@ -1997,6 +2002,9 @@ int ufshcd_probe(struct udevice *ufs_dev, struct 
ufs_hba_ops *hba_ops)
 
mb();
 
+   /* Reset the attached device */
+   ufshcd_device_reset(hba);
+
err = ufshcd_hba_enable(hba);
if (err) {
dev_err(hba->dev, "Host controller enable failed\n");
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index e8a14411560..faaebf1f9f7 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -701,6 +701,7 @@ struct ufs_hba_ops {
int (*link_startup_notify)(struct ufs_hba *hba,
   enum ufs_notify_change_status);
int (*phy_initialization)(struct ufs_hba *hba);
+   int (*device_reset)(struct ufs_hba *hba);
 };
 
 struct ufs_hba {
@@ -878,6 +879,14 @@ static inline int ufshcd_ops_link_startup_notify(struct 
ufs_hba *hba,
return 0;
 }
 
+static inline int ufshcd_vops_device_reset(struct ufs_hba *hba)
+{
+   if (hba->ops && hba->ops->device_reset)
+   return hba->ops->device_reset(hba);
+
+   return 0;
+}
+
 /* Controller UFSHCI version */
 enum {
UFSHCI_VERSION_10 = 0x0001, /* 1.0 */

-- 
2.34.1



[PATCH 13/13] MAINTAINERS: Add myself to the list of UFS maintainers

2024-09-10 Thread Neil Armstrong
Adding myself to continue Bhupesh's work to enhance and fix UFS
support in U-boot, especially for Qualcomm SoCs, and help review
patches and maintain the UFS subsystem.

Signed-off-by: Neil Armstrong 
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7ab39d91a55..14809c057c9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1707,6 +1707,7 @@ T:git 
https://source.denx.de/u-boot/custodians/u-boot-ubi.git
 F: drivers/mtd/ubi/
 
 UFS
+M: Neil Armstrong 
 M: Bhupesh Sharma 
 M: Neha Malcom Francis 
 S: Maintained

-- 
2.34.1



[PATCH 11/13] ufs: Fix debug message in 'ufs_start'

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Minor typo fix and rewording of printf message
inside 'ufs_start' which announces the availability
of the UFS device.

Signed-off-by: Bhupesh Sharma 
---
 drivers/ufs/ufs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 5d4e5424358..d2df5c26f76 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -1925,7 +1925,7 @@ int ufs_start(struct ufs_hba *hba)
return ret;
}
 
-   printf("Device at %s up at:", hba->dev->name);
+   debug("UFS Device %s is up!\n", hba->dev->name);
ufshcd_print_pwr_info(hba);
}
 

-- 
2.34.1



[PATCH 09/13] ufs: Sync possible UFS Quirks with Linux UFS driver

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Sync u-boot UFS driver to add all possible UFS Quirks
as supported by Linux UFS driver as well.

Signed-off-by: Bhupesh Sharma 
---
 drivers/ufs/ufs.h | 151 +++---
 1 file changed, 120 insertions(+), 31 deletions(-)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index 555f8a6857d..e8a14411560 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -712,38 +712,127 @@ struct ufs_hba {
u32 version;
u32 intr_mask;
u32 quirks;
-/*
- * If UFS host controller is having issue in processing LCC (Line
- * Control Command) coming from device then enable this quirk.
- * When this quirk is enabled, host controller driver should disable
- * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
- * attribute of device to 0).
- */
-#define UFSHCD_QUIRK_BROKEN_LCCBIT(0)
 
-/*
- * This quirk needs to be enabled if the host controller has
- * 64-bit addressing supported capability but it doesn't work.
- */
-#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  BIT(1)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * auto-hibernate capability but it's FASTAUTO only.
- */
-#define UFSHCD_QUIRK_HIBERN_FASTAUTO   BIT(2)
-
-/*
- * This quirk needs to be enabled if the host controller has
- * 64-bit addressing supported capability but it doesn't work.
- */
-#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
-
-/*
- * This quirk needs to be enabled if the host controller has
- * auto-hibernate capability but it's FASTAUTO only.
- */
-#define UFSHCD_QUIRK_HIBERN_FASTAUTO   0x4
+   /* Interrupt aggregation support is broken */
+#define UFSHCD_QUIRK_BROKEN_INTR_AGGR  (1 << 0)
+
+   /*
+* delay before each dme command is required as the unipro
+* layer has shown instabilities
+*/
+#define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS (1 << 1)
+
+   /*
+* If UFS host controller is having issue in processing LCC (Line
+* Control Command) coming from device then enable this quirk.
+* When this quirk is enabled, host controller driver should disable
+* the LCC transmission on UFS device (by clearing TX_LCC_ENABLE
+* attribute of device to 0).
+*/
+#define UFSHCD_QUIRK_BROKEN_LCC(1 << 2)
+
+   /*
+* The attribute PA_RXHSUNTERMCAP specifies whether or not the
+* inbound Link supports unterminated line in HS mode. Setting this
+* attribute to 1 fixes moving to HS gear.
+*/
+#define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP   (1 << 3)
+
+   /*
+* This quirk needs to be enabled if the host controller only allows
+* accessing the peer dme attributes in AUTO mode (FAST AUTO or
+* SLOW AUTO).
+*/
+#define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE (1 << 4)
+
+   /*
+* This quirk needs to be enabled if the host controller doesn't
+* advertise the correct version in UFS_VER register. If this quirk
+* is enabled, standard UFS host driver will call the vendor specific
+* ops (get_ufs_hci_version) to get the correct version.
+*/
+#define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION(1 << 5)
+
+   /*
+* Clear handling for transfer/task request list is just opposite.
+*/
+#define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR   (1 << 6)
+
+   /*
+* This quirk needs to be enabled if host controller doesn't allow
+* that the interrupt aggregation timer and counter are reset by s/w.
+*/
+#define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR  (1 << 7)
+
+   /*
+* This quirks needs to be enabled if host controller cannot be
+* enabled via HCE register.
+*/
+#define UFSHCI_QUIRK_BROKEN_HCE(1 << 8)
+
+   /*
+* This quirk needs to be enabled if the host controller regards
+* resolution of the values of PRDTO and PRDTL in UTRD as byte.
+*/
+#define UFSHCD_QUIRK_PRDT_BYTE_GRAN(1 << 9)
+
+   /*
+* This quirk needs to be enabled if the host controller reports
+* OCS FATAL ERROR with device error through sense data
+*/
+#define UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR(1 << 10)
+
+   /*
+* This quirk needs to be enabled if the host controller has
+* auto-hibernate capability but it doesn't work.
+*/
+#define UFSHCD_QUIRK_BROKEN_AUTO_HIBERN8   (1 << 11)
+
+   /*
+* This quirk needs to disable manual flush for write booster
+*/
+#define UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL (1 << 12)
+
+   /*
+* This quirk needs to disable unipro timeout values
+* before power mode change
+*/
+#define UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING   (1 << 13)
+
+   /*
+* Align DMA SG 

[PATCH 00/13] ufs: enhancements to support Qualcomm UFS controllers

2024-09-10 Thread Neil Armstrong
This serie regroups all the fixes and base enhancements required to
support the Qualcomm UFS controllers in U-Boot.

This syncs headers & defines from Linux, and includes 2 set of
fixes that were sent separately:
- ufs: core: remove link_startup_again logic
- ufs: properly fix cache operations

Without those 2 sets, UFS cannot initialize on Qualcomm controlers
since v5, and a numerous of Cache issues makes any UFS controller
fail to initialize.

Since UFS core hasn't changed for a while, and since UFS is core
technology for the Qualcomm SoCs, I volunteer maintaininig the
UFS subsystem if Bhupesh & Neha Malcom Francis are ok with that.

Signed-off-by: Neil Armstrong 
---
Bhupesh Sharma (5):
  ufs/ufs.h: Add definition of 'ufshcd_rmwl()'
  ufs: Clear UECPA once due to LINERESET has happened during LINK_STARTUP
  ufs: Sync possible UFS Quirks with Linux UFS driver
  ufs: Add missing memory barriers
  ufs: Fix debug message in 'ufs_start'

Marek Vasut (2):
  ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS
  ufs: Add UFSHCD_QUIRK_HIBERN_FASTAUTO

Neil Armstrong (6):
  ufs: allocate descriptors with size aligned with DMA_MINALIGN
  ufs: fix dcache flush and invalidate range calculation
  ufs: split flush and invalidate to only invalidate when required
  ufs: use dcache helpers for scsi_cmd data and only invalidate if necessary
  ufs: core: remove link_startup_again logic
  MAINTAINERS: Add myself to the list of UFS maintainers

 MAINTAINERS   |   1 +
 drivers/ufs/ufs.c |  98 --
 drivers/ufs/ufs.h | 157 +++---
 3 files changed, 197 insertions(+), 59 deletions(-)
---
base-commit: ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac
change-id: 20240910-topic-ufs-enhancements-fe8ef9ce39d8

Best regards,
-- 
Neil Armstrong 



[PATCH 12/13] ufs: core: remove link_startup_again logic

2024-09-10 Thread Neil Armstrong
The link_startup_again logic was added in Linux to handle device
that were set in LinkDown state, which should not be the case since U-boot
doesn't set LinkDown state are init, and Linux sets the device active
in ufshcd_init() for the first link startup.

While it worked to far, it breaks link startup for Qualcomm Controllers v5,
let's just remove the logic.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index d2df5c26f76..e34e4586224 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -462,9 +462,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
 {
int ret;
int retries = DME_LINKSTARTUP_RETRIES;
-   bool link_startup_again = true;
 
-link_startup:
do {
ufshcd_ops_link_startup_notify(hba, PRE_CHANGE);
 
@@ -490,12 +488,6 @@ link_startup:
/* failed to get the link up... retire */
goto out;
 
-   if (link_startup_again) {
-   link_startup_again = false;
-   retries = DME_LINKSTARTUP_RETRIES;
-   goto link_startup;
-   }
-
/* Mark that link is up in PWM-G1, 1-lane, SLOW-AUTO mode */
ufshcd_init_pwr_info(hba);
 

-- 
2.34.1



[PATCH 10/13] ufs: Add missing memory barriers

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Add missing wmb() and mb() barriers in the u-boot UFS core
framework driver to allow registers updates to happen before
follow-up read operations.

This makes the barrier placement similar to the Linux UFS driver.

Signed-off-by: Bhupesh Sharma 
---
 drivers/ufs/ufs.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 565a6af1404..5d4e5424358 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -432,6 +432,12 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
ufshcd_writel(hba, upper_32_bits((dma_addr_t)hba->utmrdl),
  REG_UTP_TASK_REQ_LIST_BASE_H);
 
+   /*
+* Make sure base address and interrupt setup are updated before
+* enabling the run/stop registers below.
+*/
+   wmb();
+
/*
 * UCRDY, UTMRLDY and UTRLRDY bits must be 1
 */
@@ -861,6 +867,9 @@ static int ufshcd_send_command(struct ufs_hba *hba, 
unsigned int task_tag)
 
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
 
+   /* Make sure doorbell reg is updated before reading interrupt status */
+   wmb();
+
start = get_timer(0);
do {
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
@@ -1994,6 +2003,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct 
ufs_hba_ops *hba_ops)
  REG_INTERRUPT_STATUS);
ufshcd_writel(hba, 0, REG_INTERRUPT_ENABLE);
 
+   mb();
+
err = ufshcd_hba_enable(hba);
if (err) {
dev_err(hba->dev, "Host controller enable failed\n");

-- 
2.34.1



[PATCH 08/13] ufs: Clear UECPA once due to LINERESET has happened during LINK_STARTUP

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Clear UECPA once in u-boot UFS driver due to LINERESET has happened
during LINK_STARTUP. This makes the u-boot ufs driver behavior related
to UECPA similar to Linux UFS driver.

Signed-off-by: Bhupesh Sharma 
---
 drivers/ufs/ufs.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index d99dcdef7d0..565a6af1404 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -504,6 +504,8 @@ link_startup:
if (ret)
goto out;
 
+   /* Clear UECPA once due to LINERESET has happened during LINK_STARTUP */
+   ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
ret = ufshcd_make_hba_operational(hba);
 out:
if (ret)

-- 
2.34.1



[PATCH 06/13] ufs: Add UFSHCD_QUIRK_HIBERN_FASTAUTO

2024-09-10 Thread neil . armstrong
From: Marek Vasut 

Add UFSHCD_QUIRK_HIBERN_FASTAUTO quirk for host controllers which supports
auto-hibernate the capability but only FASTAUTO mode.

Ported from Linux kernel commit
2f11bbc2c7f3 ("scsi: ufs: core: Add UFSHCD_QUIRK_HIBERN_FASTAUTO")

Signed-off-by: Marek Vasut 
---
 drivers/ufs/ufs.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index c92f47d82b5..b55c4a9e996 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -738,6 +738,12 @@ struct ufs_hba {
  */
 #define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
 
+/*
+ * This quirk needs to be enabled if the host controller has
+ * auto-hibernate capability but it's FASTAUTO only.
+ */
+#define UFSHCD_QUIRK_HIBERN_FASTAUTO   0x4
+
/* Virtual memory reference */
struct utp_transfer_cmd_desc *ucdl;
struct utp_transfer_req_desc *utrdl;

-- 
2.34.1



[PATCH 07/13] ufs/ufs.h: Add definition of 'ufshcd_rmwl()'

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Add definition of 'ufshcd_rmwl()' helper function
which would be later used by Qualcomm UFS driver
to read-modify-write registers.

Signed-off-by: Bhupesh Sharma 
---
 drivers/ufs/ufs.h | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index b55c4a9e996..555f8a6857d 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -3,6 +3,7 @@
 #define __UFS_H
 
 #include 
+#include 
 #include "unipro.h"
 
 struct udevice;
@@ -933,6 +934,23 @@ enum {
 #define ufshcd_readl(hba, reg) \
readl((hba)->mmio_base + (reg))
 
+/**
+ * ufshcd_rmwl - perform read/modify/write for a controller register
+ * @hba: per adapter instance
+ * @mask: mask to apply on read value
+ * @val: actual value to write
+ * @reg: register address
+ */
+static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
+{
+   u32 tmp;
+
+   tmp = ufshcd_readl(hba, reg);
+   tmp &= ~mask;
+   tmp |= (val & mask);
+   ufshcd_writel(hba, tmp, reg);
+}
+
 /* UTRLRSR - UTP Transfer Request Run-Stop Register 60h */
 #define UTP_TRANSFER_REQ_LIST_RUN_STOP_BIT 0x1
 

-- 
2.34.1



[PATCH 05/13] ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS

2024-09-10 Thread neil . armstrong
From: Marek Vasut 

Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not
support 64-bit addressing.

Ported from Linux kernel commit
6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS")
with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.

Signed-off-by: Marek Vasut 
---
 drivers/ufs/ufs.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index 43042c294bb..c92f47d82b5 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -732,6 +732,12 @@ struct ufs_hba {
  */
 #define UFSHCD_QUIRK_HIBERN_FASTAUTO   BIT(2)
 
+/*
+ * This quirk needs to be enabled if the host controller has
+ * 64-bit addressing supported capability but it doesn't work.
+ */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS  0x2
+
/* Virtual memory reference */
struct utp_transfer_cmd_desc *ucdl;
struct utp_transfer_req_desc *utrdl;

-- 
2.34.1



[PATCH 04/13] ufs: use dcache helpers for scsi_cmd data and only invalidate if necessary

2024-09-10 Thread Neil Armstrong
Now we have proper flush and invalidate helpers, we can use them
directly to operate on the scsi_cmd data.

Likewise, we do not need to flush then invalidate, just flush _or_
invalidate depending on the data direction.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 5845fd694d3..d99dcdef7d0 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -1468,7 +1468,6 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
struct scsi_cmd *pccb)
 {
struct utp_transfer_req_desc *req_desc = hba->utrdl;
struct ufshcd_sg_entry *prd_table = hba->ucd_prdt_ptr;
-   uintptr_t aaddr = (uintptr_t)(pccb->pdata) & ~(ARCH_DMA_MINALIGN - 1);
ulong datalen = pccb->datalen;
int table_length;
u8 *buf;
@@ -1480,15 +1479,6 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
struct scsi_cmd *pccb)
return;
}
 
-   if (pccb->dma_dir == DMA_TO_DEVICE) {   /* Write to device */
-   flush_dcache_range(aaddr,
-  ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
-   }
-
-   /* In any case, invalidate cache to avoid stale data in it. */
-   invalidate_dcache_range(aaddr,
-   ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
-
table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY);
buf = pccb->pdata;
i = table_length;
@@ -1517,8 +1507,12 @@ static int ufs_scsi_exec(struct udevice *scsi_dev, 
struct scsi_cmd *pccb)
ufshcd_prepare_utp_scsi_cmd_upiu(hba, pccb, upiu_flags);
prepare_prdt_table(hba, pccb);
 
+   ufshcd_cache_flush(pccb->pdata, pccb->datalen);
+
ufshcd_send_command(hba, TASK_TAG);
 
+   ufshcd_cache_invalidate(pccb->pdata, pccb->datalen);
+
ocs = ufshcd_get_tr_ocs(hba);
switch (ocs) {
case OCS_SUCCESS:

-- 
2.34.1



[PATCH 03/13] ufs: split flush and invalidate to only invalidate when required

2024-09-10 Thread Neil Armstrong
There is no need to flush and invalidate all data updated by the
driver, mainly because on ARM platforms flush also invalidates
the cachelines.

Split the function in two and add the appropriate cacheline
invalidates after the UFS DMA operation finishes to make sure
we read from memory.

Flushing then invalidating cacheline unaligned data causes data
corruption issues on Qualcomm platforms, and is largely unnecessary
anyway, so let's cleanup the cache operations.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 45 ++---
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 3d9a7d7ee12..5845fd694d3 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -696,17 +696,28 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_cache_flush_and_invalidate - Flush and invalidate cache
+ * ufshcd_cache_flush - Flush cache
  *
- * Flush and invalidate cache in aligned address..address+size range.
- * The invalidation is in place to avoid stale data in cache.
+ * Flush cache in aligned address..address+size range.
  */
-static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size)
+static void ufshcd_cache_flush(void *addr, unsigned long size)
 {
uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
 
flush_dcache_range(start_addr, end_addr);
+}
+
+/**
+ * ufshcd_cache_invalidate - Invalidate cache
+ *
+ * Invalidate cache in aligned address..address+size range.
+ */
+static void ufshcd_cache_invalidate(void *addr, unsigned long size)
+{
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
+
invalidate_dcache_range(start_addr, end_addr);
 }
 
@@ -754,7 +765,7 @@ static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
 
req_desc->prd_table_length = 0;
 
-   ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc));
+   ufshcd_cache_flush(req_desc, sizeof(*req_desc));
 }
 
 static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
@@ -785,13 +796,13 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
/* Copy the Descriptor */
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
memcpy(ucd_req_ptr + 1, query->descriptor, len);
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 2 * 
sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, 2 * sizeof(*ucd_req_ptr));
} else {
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 
sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
}
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba)
@@ -809,8 +820,8 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct 
ufs_hba *hba)
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 /**
@@ -877,6 +888,8 @@ static int ufshcd_send_command(struct ufs_hba *hba, 
unsigned int task_tag)
  */
 static inline int ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
 {
+   ufshcd_cache_invalidate(ucd_rsp_ptr, sizeof(*ucd_rsp_ptr));
+
return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24;
 }
 
@@ -888,6 +901,8 @@ static inline int ufshcd_get_tr_ocs(struct ufs_hba *hba)
 {
struct utp_transfer_req_desc *req_desc = hba->utrdl;
 
+   ufshcd_cache_invalidate(req_desc, sizeof(*req_desc));
+
return le32_to_cpu(req_desc->header.dword_2) & MASK_OCS;
 }
 
@@ -1437,8 +1452,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufs_hba *hba,
memcpy(ucd_req_ptr->sc.cdb, pccb->cmd, cdb_len);
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 static inline void prepare_prdt_desc(struct ufshcd_sg_entry *entry,
@@ -1461,7 +1476,7 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
str

[PATCH 02/13] ufs: fix dcache flush and invalidate range calculation

2024-09-10 Thread Neil Armstrong
The current calculation will omit doing a flush/invalidate on the last
cacheline if the base address is not aligned with DMA_MINALIGN.

This causes commands failures and write corruptions on Qualcomm
platforms.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index e005cc90608..3d9a7d7ee12 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -703,11 +703,11 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
  */
 static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size)
 {
-   uintptr_t aaddr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
-   unsigned long asize = ALIGN(size, ARCH_DMA_MINALIGN);
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
 
-   flush_dcache_range(aaddr, aaddr + asize);
-   invalidate_dcache_range(aaddr, aaddr + asize);
+   flush_dcache_range(start_addr, end_addr);
+   invalidate_dcache_range(start_addr, end_addr);
 }
 
 /**
@@ -1466,13 +1466,13 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
struct scsi_cmd *pccb)
}
 
if (pccb->dma_dir == DMA_TO_DEVICE) {   /* Write to device */
-   flush_dcache_range(aaddr, aaddr +
-  ALIGN(datalen, ARCH_DMA_MINALIGN));
+   flush_dcache_range(aaddr,
+  ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
}
 
/* In any case, invalidate cache to avoid stale data in it. */
-   invalidate_dcache_range(aaddr, aaddr +
-   ALIGN(datalen, ARCH_DMA_MINALIGN));
+   invalidate_dcache_range(aaddr,
+   ALIGN((uintptr_t)pccb->pdata + datalen, 
ARCH_DMA_MINALIGN));
 
table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY);
buf = pccb->pdata;

-- 
2.34.1



[PATCH 01/13] ufs: allocate descriptors with size aligned with DMA_MINALIGN

2024-09-10 Thread Neil Armstrong
Align the allocation size with DMA_MINALIGN to make sure we do not
flush/invalidate data from following allocations.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index be64bf971f1..e005cc90608 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -633,7 +633,9 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate one Transfer Request Descriptor
 * Should be aligned to 1k boundary.
 */
-   hba->utrdl = memalign(1024, sizeof(struct utp_transfer_req_desc));
+   hba->utrdl = memalign(1024,
+ ALIGN(sizeof(struct utp_transfer_req_desc),
+   ARCH_DMA_MINALIGN));
if (!hba->utrdl) {
dev_err(hba->dev, "Transfer Descriptor memory allocation 
failed\n");
return -ENOMEM;
@@ -642,7 +644,9 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
/* Allocate one Command Descriptor
 * Should be aligned to 1k boundary.
 */
-   hba->ucdl = memalign(1024, sizeof(struct utp_transfer_cmd_desc));
+   hba->ucdl = memalign(1024,
+ALIGN(sizeof(struct utp_transfer_cmd_desc),
+  ARCH_DMA_MINALIGN));
if (!hba->ucdl) {
dev_err(hba->dev, "Command descriptor memory allocation 
failed\n");
return -ENOMEM;

-- 
2.34.1



[PATCH 2/2] phy: qcom: Add QMP UFS PHY driver

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Add Qualcomm QMP UFS PHY driver which is available on the following
Snapdragon SoCs - SDM845, SM8250, SM8550 and SM8650 SoCs.

Signed-off-by: Bhupesh Sharma 
Signed-off-by: Neil Armstrong 
---
 drivers/phy/qcom/Kconfig|6 +
 drivers/phy/qcom/Makefile   |1 +
 drivers/phy/qcom/phy-qcom-qmp-ufs.c | 1116 +++
 drivers/phy/qcom/phy-qcom-qmp.h |  115 
 4 files changed, 1238 insertions(+)

diff --git a/drivers/phy/qcom/Kconfig b/drivers/phy/qcom/Kconfig
index 3aae1813352..5c77203d606 100644
--- a/drivers/phy/qcom/Kconfig
+++ b/drivers/phy/qcom/Kconfig
@@ -12,6 +12,12 @@ config PHY_QCOM_IPQ4019_USB
help
  Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s.
 
+config PHY_QCOM_QMP_UFS
+   tristate "Qualcomm QMP UFS PHY driver"
+   depends on PHY && ARCH_SNAPDRAGON
+   help
+ Enable this to support the UFS QMP PHY on various Qualcomm chipsets.
+
 config PHY_QCOM_QUSB2
tristate "Qualcomm USB QUSB2 PHY driver"
depends on PHY && ARCH_SNAPDRAGON
diff --git a/drivers/phy/qcom/Makefile b/drivers/phy/qcom/Makefile
index a5153061dfb..dc3ed492696 100644
--- a/drivers/phy/qcom/Makefile
+++ b/drivers/phy/qcom/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
+obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o
 obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
 obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2) += phy-qcom-snps-femto-v2.o
 obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2) += phy-qcom-snps-eusb2.o
diff --git a/drivers/phy/qcom/phy-qcom-qmp-ufs.c 
b/drivers/phy/qcom/phy-qcom-qmp-ufs.c
new file mode 100644
index 000..8908a34df54
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-ufs.c
@@ -0,0 +1,1116 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2023-2024 Linaro Limited
+ * Authors:
+ * - Bhupesh Sharma 
+ * - Neil Armstrong 
+ *
+ * Based on Linux driver
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "phy-qcom-qmp.h"
+#include "phy-qcom-qmp-pcs-ufs-v2.h"
+#include "phy-qcom-qmp-pcs-ufs-v3.h"
+#include "phy-qcom-qmp-pcs-ufs-v4.h"
+#include "phy-qcom-qmp-pcs-ufs-v5.h"
+#include "phy-qcom-qmp-pcs-ufs-v6.h"
+
+#include "phy-qcom-qmp-qserdes-com-v4.h"
+#include "phy-qcom-qmp-qserdes-com-v6.h"
+#include "phy-qcom-qmp-qserdes-txrx-v4.h"
+#include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h"
+
+/* QPHY_SW_RESET bit */
+#define SW_RESET   BIT(0)
+/* QPHY_POWER_DOWN_CONTROL */
+#define SW_PWRDN   BIT(0)
+/* QPHY_START_CONTROL bits */
+#define SERDES_START   BIT(0)
+#define PCS_START  BIT(1)
+/* QPHY_PCS_READY_STATUS bit */
+#define PCS_READY  BIT(0)
+
+#define PHY_INIT_COMPLETE_TIMEOUT  (200 * 1)
+
+struct qmp_ufs_init_tbl {
+   unsigned int offset;
+   unsigned int val;
+   /*
+* mask of lanes for which this register is written
+* for cases when second lane needs different values
+*/
+   u8 lane_mask;
+};
+
+#define QMP_PHY_INIT_CFG(o, v) \
+   {   \
+   .offset = o,\
+   .val = v,   \
+   .lane_mask = 0xff,  \
+   }
+
+#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
+   {   \
+   .offset = o,\
+   .val = v,   \
+   .lane_mask = l, \
+   }
+
+/* set of registers with offsets different per-PHY */
+enum qphy_reg_layout {
+   /* PCS registers */
+   QPHY_SW_RESET,
+   QPHY_START_CTRL,
+   QPHY_PCS_READY_STATUS,
+   QPHY_PCS_POWER_DOWN_CONTROL,
+   /* Keep last to ensure regs_layout arrays are properly initialized */
+   QPHY_LAYOUT_SIZE
+};
+
+static const unsigned int ufsphy_v2_regs_layout[QPHY_LAYOUT_SIZE] = {
+   [QPHY_START_CTRL]   = QPHY_V2_PCS_UFS_PHY_START,
+   [QPHY_PCS_READY_STATUS] = QPHY_V2_PCS_UFS_READY_STATUS,
+   [QPHY_PCS_POWER_DOWN_CONTROL]   = QPHY_V2_PCS_UFS_POWER_DOWN_CONTROL,
+};
+
+static const unsigned int ufsphy_v3_regs_layout[QPHY_LAYOUT_SIZE] = {
+   [QPHY_START_CTRL]   = QPHY_V3_PCS_UFS_PHY_START,
+   [QPHY_PCS_READY_STATUS] = QPHY_V3_PCS_UFS_READY_STATUS,
+   [QPHY_PCS_POWER_DOWN_CONTROL]   = QPHY_V3_PCS_UFS_POWER_DOWN_CONTROL,
+};
+
+static const unsigned int ufsphy_v4_regs_layout[QPHY_LAYOUT_SIZE] = {
+   [QPHY_START_CTRL]   = QPHY_V4_PCS_UFS_PHY_START,
+ 

[PATCH 0/2] phy: qcom: add QMP UFS PHY support

2024-09-10 Thread neil . armstrong
This serie imports the QMP UFS PHY headers then adds
the QMP PHY driver in order to support enabling the UFS
PHY on the SDM845, SM8250, SM8550 and SM8650 platforms.

Signed-off-by: Neil Armstrong 
---
Bhupesh Sharma (2):
  phy: qcom: Import QMP phy related header files from Linux
  phy: qcom: Add QMP UFS PHY driver

 drivers/phy/qcom/Kconfig   |6 +
 drivers/phy/qcom/Makefile  |1 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v2.h |   25 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v3.h |   21 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v4.h |   31 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v5.h |   32 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v6.h |   38 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-v2.h |   43 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-v3.h |  145 +++
 drivers/phy/qcom/phy-qcom-qmp-pcs-v4.h |  135 +++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v3.h |  111 ++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v4.h |  123 +++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v6.h |   89 ++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com.h|  140 +++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-pll.h|   69 ++
 .../phy/qcom/phy-qcom-qmp-qserdes-txrx-ufs-v6.h|   52 +
 drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v3.h|   68 ++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v4.h|  233 
 drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx.h   |  205 
 drivers/phy/qcom/phy-qcom-qmp-ufs.c| 1116 
 drivers/phy/qcom/phy-qcom-qmp.h|  115 ++
 21 files changed, 2798 insertions(+)
---
base-commit: ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac
change-id: 20240910-topic-ufs-qcom-phy-c3d5d0f4138d

Best regards,
-- 
Neil Armstrong 



[PATCH 1/2] phy: qcom: Import QMP phy related header files from Linux

2024-09-10 Thread neil . armstrong
From: Bhupesh Sharma 

Import Qualcomm QMP phy related header files from Linux v6.11-rc7,
limit to headers needed to setup QMP v2 to v6 UFS PHYs.

Signed-off-by: Bhupesh Sharma 
Signed-off-by: Neil Armstrong 
---
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v2.h |  25 +++
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v3.h |  21 ++
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v4.h |  31 +++
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v5.h |  32 +++
 drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v6.h |  38 
 drivers/phy/qcom/phy-qcom-qmp-pcs-v2.h |  43 
 drivers/phy/qcom/phy-qcom-qmp-pcs-v3.h | 145 +
 drivers/phy/qcom/phy-qcom-qmp-pcs-v4.h | 135 
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v3.h | 111 ++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v4.h | 123 +++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v6.h |  89 
 drivers/phy/qcom/phy-qcom-qmp-qserdes-com.h| 140 +
 drivers/phy/qcom/phy-qcom-qmp-qserdes-pll.h|  69 ++
 .../phy/qcom/phy-qcom-qmp-qserdes-txrx-ufs-v6.h|  52 +
 drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v3.h|  68 ++
 drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v4.h| 233 +
 drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx.h   | 205 ++
 17 files changed, 1560 insertions(+)

diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v2.h 
b/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v2.h
new file mode 100644
index 000..a0803a8783d
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v2.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_UFS_V2_H_
+#define QCOM_PHY_QMP_PCS_UFS_V2_H_
+
+#define QPHY_V2_PCS_UFS_PHY_START  0x000
+#define QPHY_V2_PCS_UFS_POWER_DOWN_CONTROL 0x004
+
+#define QPHY_V2_PCS_UFS_TX_LARGE_AMP_DRV_LVL   0x034
+#define QPHY_V2_PCS_UFS_TX_LARGE_AMP_POST_EMP_LVL  0x038
+#define QPHY_V2_PCS_UFS_TX_SMALL_AMP_DRV_LVL   0x03c
+#define QPHY_V2_PCS_UFS_TX_SMALL_AMP_POST_EMP_LVL  0x040
+
+#define QPHY_V2_PCS_UFS_RX_MIN_STALL_NOCONFIG_TIME_CAP 0x0cc
+#define QPHY_V2_PCS_UFS_RX_SYM_RESYNC_CTRL 0x13c
+#define QPHY_V2_PCS_UFS_RX_MIN_HIBERN8_TIME0x140
+#define QPHY_V2_PCS_UFS_RX_SIGDET_CTRL20x148
+#define QPHY_V2_PCS_UFS_RX_PWM_GEAR_BAND   0x154
+
+#define QPHY_V2_PCS_UFS_READY_STATUS   0x168
+
+#endif
diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v3.h 
b/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v3.h
new file mode 100644
index 000..adea13c3a9e
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v3.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_UFS_V3_H_
+#define QCOM_PHY_QMP_PCS_UFS_V3_H_
+
+#define QPHY_V3_PCS_UFS_PHY_START  0x000
+#define QPHY_V3_PCS_UFS_POWER_DOWN_CONTROL 0x004
+#define QPHY_V3_PCS_UFS_TX_LARGE_AMP_DRV_LVL   0x02c
+#define QPHY_V3_PCS_UFS_TX_SMALL_AMP_DRV_LVL   0x034
+#define QPHY_V3_PCS_UFS_RX_SYM_RESYNC_CTRL 0x134
+#define QPHY_V3_PCS_UFS_RX_MIN_HIBERN8_TIME0x138
+#define QPHY_V3_PCS_UFS_RX_SIGDET_CTRL10x13c
+#define QPHY_V3_PCS_UFS_RX_SIGDET_CTRL20x140
+#define QPHY_V3_PCS_UFS_READY_STATUS   0x160
+#define QPHY_V3_PCS_UFS_TX_MID_TERM_CTRL1  0x1bc
+#define QPHY_V3_PCS_UFS_MULTI_LANE_CTRL1   0x1c4
+
+#endif
diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v4.h 
b/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v4.h
new file mode 100644
index 000..a1c7d3d1715
--- /dev/null
+++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-ufs-v4.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef QCOM_PHY_QMP_PCS_UFS_V4_H_
+#define QCOM_PHY_QMP_PCS_UFS_V4_H_
+
+/* Only for QMP V4 PHY - UFS PCS registers */
+#define QPHY_V4_PCS_UFS_PHY_START  0x000
+#define QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL 0x004
+#define QPHY_V4_PCS_UFS_SW_RESET   0x008
+#define QPHY_V4_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB   0x00c
+#define QPHY_V4_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB   0x010
+#define QPHY_V4_PCS_UFS_PLL_CNTL   0x02c
+#define QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL   0x030
+#define QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL   0x038
+#define QPHY_V4_PCS_UFS_BIST_FIXED_PAT_CTRL0x060
+#define QPHY_V4_PCS_UFS_TX_HSGEAR_CAPABILITY   0x074
+#define QPHY_V4_PCS_UFS_RX_HSGEAR_CAPABILITY   0x0b4
+#define QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL   0x124
+#define

[PATCH 2/2] pinctr: qcom: sm8250: add special pins pins configuration data

2024-09-10 Thread Neil Armstrong
Add the special pins configuration data to allow setup the bias
of the UFS and SDCard pins on the SM8250 SoC.

Signed-off-by: Neil Armstrong 
---
 drivers/pinctrl/qcom/pinctrl-sm8250.c | 41 ---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c 
b/drivers/pinctrl/qcom/pinctrl-sm8250.c
index dac24f11bc2..69c907e3868 100644
--- a/drivers/pinctrl/qcom/pinctrl-sm8250.c
+++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c
@@ -18,8 +18,37 @@
 static char pin_name[MAX_PIN_NAME_LEN] __section(".data");
 
 static const struct pinctrl_function msm_pinctrl_functions[] = { { "qup12", 1 
},
-{ "gpio", 0 },
-{ "sdc2_clk", 
0 } };
+{ "gpio", 0 }, 
};
+#define SDC_PINGROUP(pg_name, ctl, pull, drv)  \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = ctl, \
+   .io_reg = 0,\
+   .pull_bit = pull,   \
+   .drv_bit = drv, \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = -1,  \
+   }
+
+#define UFS_RESET(pg_name, offset) \
+   {   \
+   .name = pg_name,\
+   .ctl_reg = offset,  \
+   .io_reg = offset + 0x4, \
+   .pull_bit = 3,  \
+   .drv_bit = 0,   \
+   .oe_bit = -1,   \
+   .in_bit = -1,   \
+   .out_bit = 0,   \
+   }
+
+static const struct msm_special_pin_data sm8250_special_pins_data[] = {
+   [0] = UFS_RESET("ufs_reset", SOUTH + 0xb8000),
+   [1] = SDC_PINGROUP("sdc2_clk", NORTH + 0xb7000, 14, 6),
+   [2] = SDC_PINGROUP("sdc2_cmd", NORTH + 0xb7000, 11, 3),
+   [3] = SDC_PINGROUP("sdc2_data", NORTH + 0xb7000, 9, 0),
+};
 
 static const unsigned int sm8250_pin_offsets[] = {
[0] = SOUTH,   [1] = SOUTH,   [2] = SOUTH,   [3] = SOUTH,   [4] = 
NORTH,   [5] = NORTH,
@@ -62,7 +91,12 @@ static const char *sm8250_get_function_name(struct udevice 
*dev, unsigned int se
 
 static const char *sm8250_get_pin_name(struct udevice *dev, unsigned int 
selector)
 {
-   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+   if (selector >= 180 && selector <= 183)
+   snprintf(pin_name, MAX_PIN_NAME_LEN,
+sm8250_special_pins_data[selector - 180].name);
+   else
+   snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+
return pin_name;
 }
 
@@ -76,6 +110,7 @@ static struct msm_pinctrl_data sm8250_data = {
.pin_offsets = sm8250_pin_offsets,
.pin_count = ARRAY_SIZE(sm8250_pin_offsets),
.special_pins_start = 180,
+   .special_pins_data = sm8250_special_pins_data,
},
.functions_count = ARRAY_SIZE(msm_pinctrl_functions),
.get_function_name = sm8250_get_function_name,

-- 
2.34.1



[PATCH 1/2] gpio: msm: add support for special pins

2024-09-10 Thread Neil Armstrong
Leverage the data introduced in the struct msm_special_pin_data to allow
setting the gpio direction and value if supported by the pin data.

Signed-off-by: Neil Armstrong 
---
 drivers/gpio/msm_gpio.c | 97 +
 1 file changed, 89 insertions(+), 8 deletions(-)

diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c
index 2fb266f1285..cea073b3297 100644
--- a/drivers/gpio/msm_gpio.c
+++ b/drivers/gpio/msm_gpio.c
@@ -34,13 +34,31 @@ struct msm_gpio_bank {
 #define GPIO_IN_OUT_REG(dev, x) \
(GPIO_CONFIG_REG(dev, x) + 0x4)
 
+static void msm_gpio_direction_input_special(struct msm_gpio_bank *priv,
+unsigned int gpio)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return;
+
+   data = &priv->pin_data->special_pins_data[offset];
+
+   if (!data->ctl_reg || data->oe_bit >= 31)
+   return;
+
+   /* switch direction */
+   clrsetbits_le32(priv->base + data->ctl_reg,
+   BIT(data->oe_bit), 0);
+}
+
 static void msm_gpio_direction_input(struct udevice *dev, unsigned int gpio)
 {
struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-   /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
-   return;
+   msm_gpio_direction_input_special(priv, gpio);
 
/* Disable OE bit */
clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio),
@@ -49,13 +67,33 @@ static void msm_gpio_direction_input(struct udevice *dev, 
unsigned int gpio)
return;
 }
 
+static int msm_gpio_set_value_special(struct msm_gpio_bank *priv,
+ unsigned int gpio, int value)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return 0;
+
+   data = &priv->pin_data->special_pins_data[offset];
+
+   if (!data->io_reg || data->out_bit >= 31)
+   return 0;
+
+   value = !!value;
+   /* set value */
+   writel(value << data->out_bit, priv->base + data->io_reg);
+
+   return 0;
+}
+
 static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int 
value)
 {
struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-   /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
-   return 0;
+   return msm_gpio_set_value_special(priv, gpio, value);
 
value = !!value;
/* set value */
@@ -64,14 +102,42 @@ static int msm_gpio_set_value(struct udevice *dev, 
unsigned int gpio, int value)
return 0;
 }
 
+static int msm_gpio_direction_output_special(struct msm_gpio_bank *priv,
+unsigned int gpio,
+int value)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return 0;
+
+   data = &priv->pin_data->special_pins_data[offset];
+
+   if (!data->io_reg || data->out_bit >= 31)
+   return 0;
+
+   value = !!value;
+   /* set value */
+   writel(value << data->out_bit, priv->base + data->io_reg);
+
+   if (!data->ctl_reg || data->oe_bit >= 31)
+   return 0;
+
+   /* switch direction */
+   clrsetbits_le32(priv->base + data->ctl_reg,
+   BIT(data->oe_bit), BIT(data->oe_bit));
+
+   return 0;
+}
+
 static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio,
 int value)
 {
struct msm_gpio_bank *priv = dev_get_priv(dev);
 
-   /* Always NOP for special pins, assume they're in the correct state */
if (qcom_is_special_pin(priv->pin_data, gpio))
-   return 0;
+   return msm_gpio_direction_output_special(priv, gpio, value);
 
value = !!value;
/* set value */
@@ -100,13 +166,28 @@ static int msm_gpio_set_flags(struct udevice *dev, 
unsigned int gpio, ulong flag
return 0;
 }
 
+static int msm_gpio_get_value_special(struct msm_gpio_bank *priv, unsigned int 
gpio)
+{
+   unsigned int offset = gpio - priv->pin_data->special_pins_start;
+   const struct msm_special_pin_data *data;
+
+   if (!priv->pin_data->special_pins_data)
+   return 0;
+
+   data = &priv->pin_data->special_pins_data[offse

[PATCH 0/2] qcom: allow msm_gpio to set special pins direction & value

2024-09-10 Thread Neil Armstrong
After struct msm_special_pin_data was introduced in [1], use the data
to setup the pin direction and/or value if supported by the pin data.

Add the proper msm_special_pin_data for sm8250 after sm8550 and sm8650.

[1] 
https://lore.kernel.org/all/20240528-topic-sm8x50-pinctrl-pinconf-v1-0-54d1e9ad7...@linaro.org/

Signed-off-by: Neil Armstrong 
---
Neil Armstrong (2):
  gpio: msm: add support for special pins
  pinctr: qcom: sm8250: add special pins pins configuration data

 drivers/gpio/msm_gpio.c   | 97 ---
 drivers/pinctrl/qcom/pinctrl-sm8250.c | 41 +--
 2 files changed, 127 insertions(+), 11 deletions(-)
---
base-commit: ca55cf8104c0dd78aae45fa66dd8400ef1b3d0ac
change-id: 20240910-topic-sm8x50-msm-gpio-special-pins-sm8250-943311b483e2

Best regards,
-- 
Neil Armstrong 



Re: [PATCH] Revert "gpio: qcom_pmic: add a quirk to skip GPIO configuration"

2024-09-09 Thread Neil Armstrong

On 09/09/2024 14:06, Caleb Connolly wrote:

This reverts commit 19f000b72b2fa7e4540f7cdb91287aff594239bd.

The bug in writing was caused by a long-standing error in the SPMI
driver which has since been fixed - c2de620d64d4 ("spmi: msm: fix
version 5 support"). We can safely enable writing GPIO configuration
now.

Signed-off-by: Caleb Connolly 
---
Tested on SDM845/pm8998 (OnePlus 6)
---
  drivers/gpio/qcom_pmic_gpio.c | 27 +--
  1 file changed, 5 insertions(+), 22 deletions(-)

diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c
index 80fee841ee3f..f2ef4e5ce144 100644
--- a/drivers/gpio/qcom_pmic_gpio.c
+++ b/drivers/gpio/qcom_pmic_gpio.c
@@ -68,19 +68,8 @@
  
  #define REG_EN_CTL 0x46

  #define REG_EN_CTL_ENABLE  (1 << 7)
  
-/**

- * pmic_gpio_match_data - platform specific configuration
- *
- * @PMIC_MATCH_READONLY: treat all GPIOs as readonly, don't attempt to 
configure them.
- * This is a workaround for an unknown bug on some platforms where trying to 
write the
- * GPIO configuration registers causes the board to hang.
- */
-enum pmic_gpio_quirks {
-   QCOM_PMIC_QUIRK_READONLY = (1 << 0),
-};
-
  struct qcom_pmic_gpio_data {
uint32_t pid; /* Peripheral ID on SPMI bus */
bool lv_mv_type; /* If subtype is GPIO_LV(0x10) or GPIO_MV(0x11) */
u32 pin_count;
@@ -127,15 +116,10 @@ static int qcom_gpio_set_direction(struct udevice *dev, 
unsigned int offset,
   bool input, int value)
  {
struct qcom_pmic_gpio_data *plat = dev_get_plat(dev);
uint32_t gpio_base = plat->pid + REG_OFFSET(offset);
-   ulong quirks = dev_get_driver_data(dev);
int ret = 0;
  
-	/* Some PMICs don't like their GPIOs being configured */

-   if (quirks & QCOM_PMIC_QUIRK_READONLY)
-   return 0;
-
/* Disable the GPIO */
ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL,
  REG_EN_CTL_ENABLE, 0);
if (ret < 0)
@@ -277,9 +261,8 @@ static const struct dm_gpio_ops qcom_gpio_ops = {
  static int qcom_gpio_bind(struct udevice *dev)
  {
  
  	struct qcom_pmic_gpio_data *plat = dev_get_plat(dev);

-   ulong quirks = dev_get_driver_data(dev);
struct udevice *child;
struct driver *drv;
int ret;
  
@@ -291,9 +274,9 @@ static int qcom_gpio_bind(struct udevice *dev)
  
  	/* Bind the GPIO driver as a child of the PMIC. */

ret = device_bind_with_driver_data(dev, drv,
   dev->name,
-  quirks, dev_ofnode(dev), &child);
+  0, dev_ofnode(dev), &child);
if (ret)
return log_msg_ret("bind", ret);
  
  	dev_set_plat(child, plat);

@@ -360,13 +343,13 @@ static int qcom_gpio_probe(struct udevice *dev)
  
  static const struct udevice_id qcom_gpio_ids[] = {

{ .compatible = "qcom,pm8916-gpio" },
{ .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */
-   { .compatible = "qcom,pm8998-gpio", .data = QCOM_PMIC_QUIRK_READONLY },
+   { .compatible = "qcom,pm8998-gpio" },
{ .compatible = "qcom,pms405-gpio" },
-   { .compatible = "qcom,pm6125-gpio", .data = QCOM_PMIC_QUIRK_READONLY },
-   { .compatible = "qcom,pm8150-gpio", .data = QCOM_PMIC_QUIRK_READONLY },
-   { .compatible = "qcom,pm8550-gpio", .data = QCOM_PMIC_QUIRK_READONLY },
+   { .compatible = "qcom,pm6125-gpio" },
+   { .compatible = "qcom,pm8150-gpio" },
+   { .compatible = "qcom,pm8550-gpio" },
{ }
  };
  
  U_BOOT_DRIVER(qcom_pmic_gpio) = {


Reviewed-by: Neil Armstrong 


[PATCH 1/2] soc: qcom: rpmh-rsc: add back __tcs_set_trigger() for SM8550/SM8650

2024-09-03 Thread Neil Armstrong
The TCS writes has no effect after the removal of the __tcs_set_trigger()
call, obviously it seems the RSC version 3 requires it to complete the 
transactions.

Fixes: 80c5be164ad ("soc: qcom: rpmh-rsc: drop unused multi-threading and 
non-active TCS support")
Signed-off-by: Neil Armstrong 
---
 drivers/soc/qcom/rpmh-rsc.c | 43 +++
 1 file changed, 43 insertions(+)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 61fb2e69558..aee9e55194e 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -293,6 +293,48 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable);
 }
 
+/**
+ * __tcs_set_trigger() - Start xfer on a TCS or unset trigger on a borrowed TCS
+ * @drv: The controller.
+ * @tcs_id:  The global ID of this TCS.
+ * @trigger: If true then untrigger/retrigger. If false then just untrigger.
+ *
+ * In the normal case we only ever call with "trigger=true" to start a
+ * transfer. That will un-trigger/disable the TCS from the last transfer
+ * then trigger/enable for this transfer.
+ *
+ * If we borrowed a wake TCS for an active-only transfer we'll also call
+ * this function with "trigger=false" to just do the un-trigger/disable
+ * before using the TCS for wake purposes again.
+ *
+ * Note that the AP is only in charge of triggering active-only transfers.
+ * The AP never triggers sleep/wake values using this function.
+ */
+static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger)
+{
+   u32 enable;
+   u32 reg = drv->regs[RSC_DRV_CONTROL];
+
+   /*
+* HW req: Clear the DRV_CONTROL and enable TCS again
+* While clearing ensure that the AMC mode trigger is cleared
+* and then the mode enable is cleared.
+*/
+   enable = read_tcs_reg(drv, reg, tcs_id);
+   enable &= ~TCS_AMC_MODE_TRIGGER;
+   write_tcs_reg_sync(drv, reg, tcs_id, enable);
+   enable &= ~TCS_AMC_MODE_ENABLE;
+   write_tcs_reg_sync(drv, reg, tcs_id, enable);
+
+   if (trigger) {
+   /* Enable the AMC mode on the TCS and then trigger the TCS */
+   enable = TCS_AMC_MODE_ENABLE;
+   write_tcs_reg_sync(drv, reg, tcs_id, enable);
+   enable |= TCS_AMC_MODE_TRIGGER;
+   write_tcs_reg(drv, reg, tcs_id, enable);
+   }
+}
+
 /**
  * rpmh_rsc_send_data() - Write / trigger active-only message.
  * @drv: The controller.
@@ -348,6 +390,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct 
tcs_request *msg)
 *   of __tcs_set_trigger() below.
 */
__tcs_buffer_write(drv, tcs_id, 0, msg);
+   __tcs_set_trigger(drv, tcs_id, true);
 
/* U-Boot: Now wait for the TCS to be cleared, indicating that we're 
done */
for (i = 0; i < USEC_PER_SEC; i++) {

-- 
2.34.1



[PATCH 2/2] regulator: qcom-rpmh-regulator: add support for PM8550 & related regulators

2024-09-03 Thread Neil Armstrong
Add the PM8550 & related regulators found on the SM8550 and SM8650 platforms.
The tables are imported from the Linux driver.

Signed-off-by: Neil Armstrong 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 136 ++
 1 file changed, 136 insertions(+)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 06fd3f31956..2dc261d83e3 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -357,6 +357,69 @@ static const struct dm_regulator_ops 
rpmh_regulator_vrm_drms_ops = {
.get_mode = rpmh_regulator_vrm_get_mode,
 };
 
+static struct dm_regulator_mode pmic_mode_map_pmic5_bob[] = {
+   {
+   .id = REGULATOR_MODE_LPM,
+   .register_value = PMIC5_BOB_MODE_PFM,
+   .name = "PMIC5_BOB_MODE_PFM"
+   }, {
+   .id = REGULATOR_MODE_AUTO,
+   .register_value = PMIC5_BOB_MODE_AUTO,
+   .name = "PMIC5_BOB_MODE_AUTO"
+   }, {
+   .id = REGULATOR_MODE_HPM,
+   .register_value = PMIC5_BOB_MODE_PWM,
+   .name = "PMIC5_BOB_MODE_PWM"
+   },
+};
+
+static struct dm_regulator_mode pmic_mode_map_pmic5_smps[] = {
+   {
+   .id = REGULATOR_MODE_RETENTION,
+   .register_value = PMIC5_SMPS_MODE_RETENTION,
+   .name = "PMIC5_SMPS_MODE_RETENTION"
+   }, {
+   .id = REGULATOR_MODE_LPM,
+   .register_value = PMIC5_SMPS_MODE_PFM,
+   .name = "PMIC5_SMPS_MODE_PFM"
+   }, {
+   .id = REGULATOR_MODE_AUTO,
+   .register_value = PMIC5_SMPS_MODE_AUTO,
+   .name = "PMIC5_SMPS_MODE_AUTO"
+   }, {
+   .id = REGULATOR_MODE_HPM,
+   .register_value = PMIC5_SMPS_MODE_PWM,
+   .name = "PMIC5_SMPS_MODE_PWM"
+   },
+};
+
+static const struct rpmh_vreg_hw_data pmic5_bob = {
+   .regulator_type = VRM,
+   .ops = &rpmh_regulator_vrm_drms_ops,
+   .voltage_range = REGULATOR_LINEAR_RANGE(300, 0, 31, 32000),
+   .n_voltages = 32,
+   .pmic_mode_map = pmic_mode_map_pmic5_bob,
+   .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_bob),
+};
+
+static const struct rpmh_vreg_hw_data pmic5_ftsmps525_lv = {
+   .regulator_type = VRM,
+   .ops = &rpmh_regulator_vrm_drms_ops,
+   .voltage_range = REGULATOR_LINEAR_RANGE(30, 0, 267, 4000),
+   .n_voltages = 268,
+   .pmic_mode_map = pmic_mode_map_pmic5_smps,
+   .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_smps),
+};
+
+static const struct rpmh_vreg_hw_data pmic5_ftsmps525_mv = {
+   .regulator_type = VRM,
+   .ops = &rpmh_regulator_vrm_drms_ops,
+   .voltage_range = REGULATOR_LINEAR_RANGE(60, 0, 267, 8000),
+   .n_voltages = 268,
+   .pmic_mode_map = pmic_mode_map_pmic5_smps,
+   .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_smps),
+};
+
 static struct dm_regulator_mode pmic_mode_map_pmic5_ldo[] = {
{
.id = REGULATOR_MODE_RETENTION,
@@ -393,6 +456,16 @@ static const struct rpmh_vreg_hw_data pmic5_pldo_lv = {
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
 };
 
+static const struct rpmh_vreg_hw_data pmic5_nldo515 = {
+   .regulator_type = VRM,
+   .ops = &rpmh_regulator_vrm_drms_ops,
+   .voltage_range = REGULATOR_LINEAR_RANGE(32, 0, 210, 8000),
+   .n_voltages = 211,
+   .hpm_min_load_uA = 3,
+   .pmic_mode_map = pmic_mode_map_pmic5_ldo,
+   .n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
+};
+
 #define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \
 { \
.name   = _name, \
@@ -412,6 +485,57 @@ static const struct rpmh_vreg_init_data 
pm8150l_vreg_data[] = {
{}
 };
 
+static const struct rpmh_vreg_init_data pm8550_vreg_data[] = {
+   RPMH_VREG("ldo1",   "ldo%s1",  &pmic5_nldo515,"vdd-l1-l4-l10"),
+   RPMH_VREG("ldo2",   "ldo%s2",  &pmic5_pldo,"vdd-l2-l13-l14"),
+   RPMH_VREG("ldo3",   "ldo%s3",  &pmic5_nldo515,"vdd-l3"),
+   RPMH_VREG("ldo4",   "ldo%s4",  &pmic5_nldo515,"vdd-l1-l4-l10"),
+   RPMH_VREG("ldo5",   "ldo%s5",  &pmic5_pldo,"vdd-l5-l16"),
+   RPMH_VREG("ldo6",   "ldo%s6",  &pmic5_pldo, "vdd-l6-l7"),
+   RPMH_VREG("ldo7",   "ldo%s7",  &pmic5_pldo, "vdd-l6-l7"),
+   RPMH_VREG("ldo8",   "ldo%s8",  &pmic5_pldo, "vdd-l8-l9"),
+   RPMH_VREG("ldo9",   "ldo%s9",  &pmic5_pldo,"vdd-l8-l9"),
+   RPMH_VREG("ldo10",  "ldo%s10", &pmic5_nldo

[PATCH 0/2] regulators: qcom-rpmh: support SM8550 and SM8650 platforms

2024-09-03 Thread Neil Armstrong
Fix the RSC and add the tables for the PM8550 and related regulators.

Signed-off-by: Neil Armstrong 
---
Neil Armstrong (2):
  soc: qcom: rpmh-rsc: add back __tcs_set_trigger() for SM8550/SM8650
  regulator: qcom-rpmh-regulator: add support for PM8550 & related 
regulators

 drivers/power/regulator/qcom-rpmh-regulator.c | 136 ++
 drivers/soc/qcom/rpmh-rsc.c   |  43 
 2 files changed, 179 insertions(+)
---
base-commit: bb403c895887eb5b29652f916646f886b34c6309
change-id: 20240903-topic-sm8x50-regulators-support-b149f2417299

Best regards,
-- 
Neil Armstrong 



[GIT PULL] Please pull u-boot-amlogic-next-20240902

2024-09-02 Thread Neil Armstrong

Hi Tom,

A simple set of changes to allow using the bootrom NAND pages, ported from 
Linux.

Thanks,
Neil

The following changes since commit ee2af844ba1b27b2e959c4e649e4b769fbeb4074:

  Merge tag 'efi-2024-10-rc4' of 
https://source.denx.de/u-boot/custodians/u-boot-efi (2024-08-24 14:03:28 -0600)

are available in the Git repository at:

  https://source.denx.de/u-boot/custodians/u-boot-amlogic.git 
tags/u-boot-amlogic-next-20240902

for you to fetch changes up to 35ff967a99e97b523732096628bdbc78758922f6:

  mtd: rawnand: meson: read/write access for boot ROM pages (2024-08-28 
16:05:45 +0200)


- meson_nand: R/W support for pages used by boot ROM


Arseniy Krasnov (3):
  mtd: rawnand: nand_base: support for 'NAND_IS_BOOT_MEDIUM' flag
  mtd: rawnand: meson: refactor use of 'meson_nfc_cmd_access()'
  mtd: rawnand: meson: read/write access for boot ROM pages

 drivers/mtd/nand/raw/meson_nand.c | 84 ++-
 drivers/mtd/nand/raw/nand_base.c  |  3 ++
 include/linux/mtd/rawnand.h   |  5 +++
 3 files changed, 65 insertions(+), 27 deletions(-)


Re: [u-boot-test-hooks PATCH v4 3/3] Provide some basic scripts for Labgrid integration

2024-08-30 Thread neil . armstrong

On 30/08/2024 03:09, Simon Glass wrote:

Hi Tom,

On Thu, 29 Aug 2024 at 09:20, Tom Rini  wrote:


On Thu, Aug 29, 2024 at 09:02:38AM -0600, Simon Glass wrote:

Hi Neil,

On Thu, 29 Aug 2024 at 08:44,  wrote:


On 29/08/2024 14:17, Simon Glass wrote:

Hi Peter,

On Thu, 29 Aug 2024 at 04:43, Peter Robinson  wrote:


On Wed, 28 Aug 2024 at 22:25, Simon Glass  wrote:


Hi Peter,

On Wed, 28 Aug 2024 at 12:14, Peter Robinson  wrote:


Hi Simon,


With Labgrid we don't need to specify the various methods, except for
the console, which simply calls labgrid-client.

This allows supporting any boards in your lab, without adding per-board
configuration to these hooks.

Provide ellesmere files as an example.


What's ellesmere?


It is a lake but also the name of a computer.




Signed-off-by: Simon Glass 
---

Changes in v4:
- Support pytest fully with dual-build boards like Beagleplay

Changes in v3:
- Update scripts for latest version of Labgrid integration
- Add poweroff.none and poweron.none
- Provide -n flag when querying board info
- Target the grpc version of Labgrid which is now in -master
- Update README to cover the changes

Changes in v2:
- Make use of the common script (only) to set bin_dir

   README.md| 50 


Maybe that should be in a separate labsgrid readme?


My hope is that Labgrid becomes the normal way of running these tests,


Generally I agree with automated testing platforms, I think  makes sense, there's a bunch like
Linaro and a bunch in the arm ecosystem use LAVA [1] and  there's a
bunch more that I'm aware of.


I am somewhat familiar with LAVA and I believe it can be used to test
U-Boot, although I need to learn how. Looking at a test run [2] for
beaglebone black I see that it is using a recent kernel but the U-Boot
seems to be older.



Does it make sense, of course at some point in the future post this
being merged, make sense to look at a general way of making it easier
to plugin these sort of HW test platforms using this as a basis? I ask
mostly because putting a bunch of my devices into some sort of
platform can auto test things and of course everyone has an opinion to
which is the best one :-P


Yes. I had heard from Tom that Labgrid is the new hotness for now.
Having dug into it I believe it is a good solution, although it can
certainly be improved to handle scale better.

Anyway, IMO the current test hooks are not a great solution, just
because the configuration is spread all over the place and it relies
on lots of little shell scripts. So I believe that the Labgrid
integration is a closer to where we want to be with others that come
along.


I'd say all those scripts are actually here to ease integration with any
system, booting U-Boot and Linux are two different beasts.


That's fine, go ahead and use the scripts. My point is that Labgrid
doesn't need them and in fact it makes everything pretty painful if we
try to use all of them.


I guess I really need to clean-up and post my former co-workers scripts
as I strongly disagree with that statement.


See some examples below. Bear in mind also that my goal has been to
get my lab fully running, that includes interactive access to boards,
as well as running tests. For that I have been using tbot (with
integrated build and software-loading features). WIth Labgrid I have
been able to replace most of the pytest scripts, tbot and Labman with
Labgrid + 60 patches and some configuration files.

Let's look through the scripts:

u-boot-test-common - new script

u-boot-test-console - needed

u-boot-test-flash - here's an example:

. poweroff.${power_impl}
sleep 0.1
. flash.sdwire_common_mount
. poweron.${power_impl}

Here's another:

# Handles the common SDwire mounting (caller does power control)

mount_dir=/media/${mount_point}

# Switch over to get USB card access
sd-mux-ctrl --device-serial ${sdwire_serial} --ts

complete=false
for i in {0..9}; do
 if out="$(mount UUID=${mount_uuid} 2>&1)"; then
 complete=true
 break
 fi
 echo $out

 # If it is already mounted, try to unmount it first. It may have been
 # mounted by another user so we won't have the access we need. If this 
gives
 # an error then we know we cannot continue
 if [[ $out == *"already mounted"* ]]; then
 umount UUID=${mount_uuid}
 fi
 sleep 1
done
if [[ $complete = false ]]; then
 echo "Failed to mount UUID ${mount_uuid} after 10 tries"
 exit 1
fi

# Sanity check
if ! mountpoint -q ${mount_dir}; then
 echo "Mount ${mount_dir} not available after 'mount'"
 exit 1
fi

# Perform the write, pass along as much environment as possible
. writer.${flash_writer}

complete=false
for i in {0..9}; do
 if out="$(umount ${mount_dir} 2>&1)"; then
 complete=true
 break
 fi
 echo $out
 sleep 1
done

if [[ $complete = false ]]; then
 echo "Failed to umount UUID ${mount_uuid} after 10 tries"
 exit 1
fi

# Sanity check
if 

Re: [u-boot-test-hooks PATCH v4 3/3] Provide some basic scripts for Labgrid integration

2024-08-29 Thread neil . armstrong

On 29/08/2024 14:17, Simon Glass wrote:

Hi Peter,

On Thu, 29 Aug 2024 at 04:43, Peter Robinson  wrote:


On Wed, 28 Aug 2024 at 22:25, Simon Glass  wrote:


Hi Peter,

On Wed, 28 Aug 2024 at 12:14, Peter Robinson  wrote:


Hi Simon,


With Labgrid we don't need to specify the various methods, except for
the console, which simply calls labgrid-client.

This allows supporting any boards in your lab, without adding per-board
configuration to these hooks.

Provide ellesmere files as an example.


What's ellesmere?


It is a lake but also the name of a computer.




Signed-off-by: Simon Glass 
---

Changes in v4:
- Support pytest fully with dual-build boards like Beagleplay

Changes in v3:
- Update scripts for latest version of Labgrid integration
- Add poweroff.none and poweron.none
- Provide -n flag when querying board info
- Target the grpc version of Labgrid which is now in -master
- Update README to cover the changes

Changes in v2:
- Make use of the common script (only) to set bin_dir

  README.md| 50 


Maybe that should be in a separate labsgrid readme?


My hope is that Labgrid becomes the normal way of running these tests,


Generally I agree with automated testing platforms, I think  makes sense, there's a bunch like
Linaro and a bunch in the arm ecosystem use LAVA [1] and  there's a
bunch more that I'm aware of.


I am somewhat familiar with LAVA and I believe it can be used to test
U-Boot, although I need to learn how. Looking at a test run [2] for
beaglebone black I see that it is using a recent kernel but the U-Boot
seems to be older.



Does it make sense, of course at some point in the future post this
being merged, make sense to look at a general way of making it easier
to plugin these sort of HW test platforms using this as a basis? I ask
mostly because putting a bunch of my devices into some sort of
platform can auto test things and of course everyone has an opinion to
which is the best one :-P


Yes. I had heard from Tom that Labgrid is the new hotness for now.
Having dug into it I believe it is a good solution, although it can
certainly be improved to handle scale better.

Anyway, IMO the current test hooks are not a great solution, just
because the configuration is spread all over the place and it relies
on lots of little shell scripts. So I believe that the Labgrid
integration is a closer to where we want to be with others that come
along.


I'd say all those scripts are actually here to ease integration with any
system, booting U-Boot and Linux are two different beasts.
Most of the time you need special jumpers enabled to setup vendor-specific
bootrom mode to reflash or ram-boot U-Boot.
So forcing us people to switch to Labgrid because it matches your boards
behavior is a little adventurous, and while we can add some enhancement
to the actual pytest and hooks, I'm against saying Labgrid should be the
golden CI system.

Neil



I would love for you to add a board into Labgrid and see how you go.



[1] https://validation.linaro.org/


so having it in the main place (and perhaps eventually removing the
old way) is my goal.




  bin/console.labgrid  | 42 ++
  bin/ellesmere/common-labgrid | 46 +
  bin/ellesmere/conf.all   | 24 +
  bin/getrole.labgrid  | 25 ++
  bin/release.labgrid  | 22 
  bin/release.none | 22 
  bin/u-boot-test-getrole  | 38 +++
  bin/u-boot-test-release  | 26 +++
  9 files changed, 295 insertions(+)
  create mode 100644 bin/console.labgrid
  create mode 100755 bin/ellesmere/common-labgrid
  create mode 100644 bin/ellesmere/conf.all
  create mode 100644 bin/getrole.labgrid
  create mode 100644 bin/release.labgrid
  create mode 100644 bin/release.none
  create mode 100755 bin/u-boot-test-getrole
  create mode 100755 bin/u-boot-test-release



[..]

Regards,
Simon


Regards,
Simon

[2] https://validation.linaro.org/scheduler/job/4089871#results_482796468




Re: [PATCH v5 01/20] test: Allow signaling that U-Boot is ready

2024-08-29 Thread Neil Armstrong

On 29/08/2024 16:22, neil.armstr...@linaro.org wrote:

On 29/08/2024 00:08, Simon Glass wrote:

When Labgrid is used, it can get U-Boot ready for running tests. It
prints a message when it has done so.

Add logic to detect this message and accept it.


So labgrid can boot and wait for `board_type & board_identity` itself right ?


Sorry bad copy paste, I was meaning `Hit any key to stop autoboot: `



It's cool, but if the boots fails for a reason, what would happen ?
Having the U-Boot pytest to parse the U-Boot boot log makes sure we can 
identify crash
and report them in the pytest log.

And this adds a labgrid-only string to parse, which could potentially
collide with pre-uboot or whatever log when not using labgrid.

Neil



Signed-off-by: Simon Glass 
---

(no changes since v1)

  test/py/u_boot_console_base.py | 9 +
  1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
index 76a550d45a1..882d04cd1e9 100644
--- a/test/py/u_boot_console_base.py
+++ b/test/py/u_boot_console_base.py
@@ -22,6 +22,7 @@ pattern_stop_autoboot_prompt = re.compile('Hit any key to 
stop autoboot: ')
  pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')
  pattern_error_notification = re.compile('## Error: ')
  pattern_error_please_reset = re.compile('### ERROR ### Please RESET the board 
###')
+pattern_ready_prompt = re.compile('U-Boot is ready')
  PAT_ID = 0
  PAT_RE = 1
@@ -196,15 +197,15 @@ class ConsoleBase(object):
  self.bad_pattern_ids[m - 1])
  self.u_boot_version_string = self.p.after
  while True:
-    m = self.p.expect([self.prompt_compiled,
+    m = self.p.expect([self.prompt_compiled, pattern_ready_prompt,
  pattern_stop_autoboot_prompt] + self.bad_patterns)
-    if m == 0:
+    if m == 0 or m == 1:
  break
-    if m == 1:
+    if m == 2:
  self.p.send(' ')
  continue
  raise Exception('Bad pattern found on console: ' +
-    self.bad_pattern_ids[m - 2])
+    self.bad_pattern_ids[m - 3])
  except Exception as ex:
  self.log.error(str(ex))






Re: [PATCH v5 17/20] test: Try to shut down the lab console gracefully

2024-08-29 Thread neil . armstrong

On 29/08/2024 00:08, Simon Glass wrote:

Send the Labgrid quit characters to ask it to exit gracefully. This
typically allows it to power off the board being used.


Sending those characters every time could collide with other CI systems,
I don't think it's a good idea.



If that doesn't work, try the less graceful approach.

Signed-off-by: Simon Glass 
---

(no changes since v1)

  test/py/u_boot_spawn.py | 17 +++--
  1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/test/py/u_boot_spawn.py b/test/py/u_boot_spawn.py
index c0ff0813554..ec1fa465047 100644
--- a/test/py/u_boot_spawn.py
+++ b/test/py/u_boot_spawn.py
@@ -16,6 +16,9 @@ import termios
  import time
  import traceback
  
+# Character to send (twice) to exit the terminal

+EXIT_CHAR = 0x1d# FS (Ctrl + ])
+
  class Timeout(Exception):
  """An exception sub-class that indicates that a timeout occurred."""
  
@@ -304,15 +307,25 @@ class Spawn:

  None.
  
  Returns:

-Nothing.
+str: Type of closure completed
  """
+self.send(chr(EXIT_CHAR) * 2)
  
+# Wait about 10 seconds for Labgrid to close and power off the board

+for _ in range(100):
+if not self.isalive():
+return 'normal'
+time.sleep(0.1)
+
+# That didn't work, so try closing the PTY
  os.close(self.fd)
  for _ in range(100):
  if not self.isalive():
-break
+return 'break'
  time.sleep(0.1)
  
+return 'timeout'

+
  def get_expect_output(self):
  """Return the output read by expect()
  




Re: [PATCH v5 03/20] test: Pass stderr to stdout

2024-08-29 Thread neil . armstrong

On 29/08/2024 00:08, Simon Glass wrote:

Some tests may output things to stderr. Ensure that this output is not
dropped, by redirecting it to stdout


Can't you make sure to output all labgrid output to stdout in the hook script 
instead ?



Signed-off-by: Simon Glass 
---

(no changes since v1)

  test/py/u_boot_spawn.py | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/test/py/u_boot_spawn.py b/test/py/u_boot_spawn.py
index 97e95e07c80..81a09a9d639 100644
--- a/test/py/u_boot_spawn.py
+++ b/test/py/u_boot_spawn.py
@@ -10,6 +10,7 @@ import re
  import pty
  import signal
  import select
+import sys
  import time
  import traceback
  
@@ -59,6 +60,7 @@ class Spawn:

  signal.signal(signal.SIGHUP, signal.SIG_DFL)
  if cwd:
  os.chdir(cwd)
+sys.stderr = sys.stdout
  os.execvp(args[0], args)
  except:
  print('CHILD EXECEPTION:')




Re: [PATCH v5 01/20] test: Allow signaling that U-Boot is ready

2024-08-29 Thread neil . armstrong

On 29/08/2024 00:08, Simon Glass wrote:

When Labgrid is used, it can get U-Boot ready for running tests. It
prints a message when it has done so.

Add logic to detect this message and accept it.


So labgrid can boot and wait for `board_type & board_identity` itself right ?

It's cool, but if the boots fails for a reason, what would happen ?
Having the U-Boot pytest to parse the U-Boot boot log makes sure we can 
identify crash
and report them in the pytest log.

And this adds a labgrid-only string to parse, which could potentially
collide with pre-uboot or whatever log when not using labgrid.

Neil



Signed-off-by: Simon Glass 
---

(no changes since v1)

  test/py/u_boot_console_base.py | 9 +
  1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py
index 76a550d45a1..882d04cd1e9 100644
--- a/test/py/u_boot_console_base.py
+++ b/test/py/u_boot_console_base.py
@@ -22,6 +22,7 @@ pattern_stop_autoboot_prompt = re.compile('Hit any key to 
stop autoboot: ')
  pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')
  pattern_error_notification = re.compile('## Error: ')
  pattern_error_please_reset = re.compile('### ERROR ### Please RESET the board 
###')
+pattern_ready_prompt = re.compile('U-Boot is ready')
  
  PAT_ID = 0

  PAT_RE = 1
@@ -196,15 +197,15 @@ class ConsoleBase(object):
  self.bad_pattern_ids[m - 1])
  self.u_boot_version_string = self.p.after
  while True:
-m = self.p.expect([self.prompt_compiled,
+m = self.p.expect([self.prompt_compiled, pattern_ready_prompt,
  pattern_stop_autoboot_prompt] + self.bad_patterns)
-if m == 0:
+if m == 0 or m == 1:
  break
-if m == 1:
+if m == 2:
  self.p.send(' ')
  continue
  raise Exception('Bad pattern found on console: ' +
-self.bad_pattern_ids[m - 2])
+self.bad_pattern_ids[m - 3])
  
  except Exception as ex:

  self.log.error(str(ex))




Re: [PATCH v5 08/20] test: Introduce the concept of a role

2024-08-29 Thread neil . armstrong

Hi,

On 29/08/2024 00:08, Simon Glass wrote:

In Labgrid there is the concept of a 'role', which is similar to the
U-Boot board ID in U-Boot's pytest subsystem.

The role indicates both the target and information about the U-Boot
build to use. It can also provide any amount of other configuration.
The information is obtained using the 'labgrid-client query' operation.

Make use of this in tests, so that only the role is required in gitlab
and other situations. The board type and other things can be queried
as needed.

Use a new 'u-boot-test-getrole' script to obtain the requested
information.

With this it is possible to run lab tests in gitlab with just a single
'ROLE' variable for each board.


Can't this be in the hook script ? I mean allmost no CI system have a 1:1
usage of board_type & board_identity, but we use those fields and transform
them accordingly.

u-boot-test-getrole is labgrid only, all script receives board_type & 
board_identity,
so why add some labgrind specific python here ?

Neil



Signed-off-by: Simon Glass 
---

Changes in v5:
- Add a few more comments
- Comment out the debugging, which might be useful later

  test/py/conftest.py | 38 ++
  1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/test/py/conftest.py b/test/py/conftest.py
index 6547c6922c6..03dfd8ab562 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -23,6 +23,7 @@ from pathlib import Path
  import pytest
  import re
  from _pytest.runner import runtestprotocol
+import subprocess
  import sys
  
  # Globals: The HTML log file, and the connection to the U-Boot console.

@@ -79,6 +80,7 @@ def pytest_addoption(parser):
  parser.addoption('--gdbserver', default=None,
  help='Run sandbox under gdbserver. The argument is the channel '+
  'over which gdbserver should communicate, e.g. localhost:1234')
+parser.addoption('--role', help='U-Boot board role (for Labgrid)')
  parser.addoption('--no-prompt-wait', default=False, action='store_true',
  help="Assume that U-Boot is ready and don't wait for a prompt")
  
@@ -130,12 +132,40 @@ def get_details(config):

  str: Build directory
  str: Source directory
  """
-board_type = config.getoption('board_type')
-board_identity = config.getoption('board_identity')
+role = config.getoption('role')
+
+# Get a few provided parameters
  build_dir = config.getoption('build_dir')
+if role:
+# When using a role, build_dir and build_dir_extra are normally not 
set,
+# since they are picked up from Labgrid via the u-boot-test-getrole
+# script
+board_identity = role
+cmd = ['u-boot-test-getrole', role, '--configure']
+env = os.environ.copy()
+if build_dir:
+env['U_BOOT_BUILD_DIR'] = build_dir
+proc = subprocess.run(cmd, capture_output=True, encoding='utf-8',
+  env=env)
+if proc.returncode:
+raise ValueError(proc.stderr)
+# For debugging
+# print('conftest: lab:', proc.stdout)
+vals = {}
+for line in proc.stdout.splitlines():
+item, value = line.split(' ', maxsplit=1)
+k = item.split(':')[-1]
+vals[k] = value
+# For debugging
+# print('conftest: lab info:', vals)
+board_type, default_build_dir, source_dir = (vals['board'],
+vals['build_dir'], vals['source_dir'])
+else:
+board_type = config.getoption('board_type')
+board_identity = config.getoption('board_identity')
  
-source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))

-default_build_dir = source_dir + '/build-' + board_type
+source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR))
+default_build_dir = source_dir + '/build-' + board_type
  if not build_dir:
  build_dir = default_build_dir
  




Re: [PATCH v3 0/3] Meson: R/W support for pages used by boot ROM

2024-08-28 Thread Neil Armstrong
Hi,

On Mon, 26 Aug 2024 16:17:07 +0300, Arseniy Krasnov wrote:
> Patchset is based on patchset for Linux (today merged to nand-next):
> https://lore.kernel.org/linux-mtd/20240507230903.3399594-1-avkras...@salutedevices.com/
> 
> Here is description from it:
> 
>  >  Amlogic's boot ROM code needs that some pages on NAND must be written
>  >  in special "short" ECC mode with scrambling enabled. Such pages:
>  >  1) Contain some metadata about hardware.
>  >  2) Located with some interval starting from 0 offset, until some
>  > specified offset. Interval and second offset are set in the
>  > device tree.
>  >
>  >  This patchset adds R/W support for such pages. To enable it we can setup
>  >  it in dts:
>  >
>  >  nand-is-boot-medium;
>  >  amlogic,boot-pages = <1024>;
>  >  amlogic,boot-page-step = <128>;
>  >
>  >  It means that each 128th page in range 0 to 1024 pages will be accessed
>  >  in special mode ("short" ECC + scrambling). In practice this feature is
>  >  needed when we want to update first block of NAND - driver will enable
>  >  required mode by itself using value from device tree.
> 
> [...]

Thanks, Applied to https://source.denx.de/u-boot/custodians/u-boot-amlogic 
(u-boot-amlogic-next)

[1/3] mtd: rawnand: nand_base: support for 'NAND_IS_BOOT_MEDIUM' flag
  
https://source.denx.de/u-boot/custodians/u-boot-amlogic/-/commit/9905e77edaa9b4a43285e587317c600ffa7be7ca
[2/3] mtd: rawnand: meson: refactor use of 'meson_nfc_cmd_access()'
  
https://source.denx.de/u-boot/custodians/u-boot-amlogic/-/commit/33acfbf41819d06e13bcccf1ffdf7d01160f4b1e
[3/3] mtd: rawnand: meson: read/write access for boot ROM pages
  
https://source.denx.de/u-boot/custodians/u-boot-amlogic/-/commit/35ff967a99e97b523732096628bdbc78758922f6

-- 
Neil



Re: [PATCH] doc/develop/sending_patches.rst: Reword where our git tree is slightly

2024-08-27 Thread neil . armstrong

On 26/08/2024 19:01, Tom Rini wrote:

We shouldn't have had the link to our git tree be contained within "``"
as that meant that it did not work as a link, so remove those. And
rather than make this a link plus text, keep this as a link within the
text for overall clarity.

Suggested-by: Quentin Schulz 
Signed-off-by: Tom Rini 
---
  doc/develop/sending_patches.rst | 9 -
  1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/doc/develop/sending_patches.rst b/doc/develop/sending_patches.rst
index 82efb717b179..990cb9912a92 100644
--- a/doc/develop/sending_patches.rst
+++ b/doc/develop/sending_patches.rst
@@ -76,11 +76,10 @@ General Patch Submission Rules
compression, no attachments. Just plain text. The best way the generate
patches is by using the ``git format-patch`` command. For a patch that is
fixing a bug or regression of some sort, please use the ``master`` branch of
-  the mainline U-Boot git repository
-  (``https://source.denx.de/u-boot/u-boot.git``) as reference. For new
-  features, if the ``next`` branch has been opened (which happens with the
-  release of ``-rc2``) that branch should be used, otherwise ``master`` is
-  acceptable.
+  the mainline U-Boot git repository located at
+  https://source.denx.de/u-boot/u-boot.git as reference. For new features, if
+  the ``next`` branch has been opened (which happens with the release of
+  ``-rc2``) that branch should be used, otherwise ``master`` is acceptable.
  
  * Make sure that your mailer does not mangle the patch by automatic changes

like wrapping of longer lines etc.


Reviewed-by: Neil Armstrong 


Re: [PATCH v2 0/3] Meson: R/W support for pages used by boot ROM

2024-08-23 Thread Neil Armstrong

On 23/08/2024 10:29, Arseniy Krasnov wrote:

Hi! Got it, thanks!

On 23.08.2024 11:10, Michael Nazzareno Trimarchi wrote:

Hi Arseniy

On Thu, Aug 22, 2024 at 9:04 AM Arseniy Krasnov
 wrote:


Hi, thanks!

Thanks, Arseniy

On 22.08.2024 00:17, Michael Nazzareno Trimarchi wrote:

Hi

I will read them tomorrow ;)

Thank you for understanding



All the series are delegated to Neil. I will review anyway but I think
that will then pick from him


Sure I can pick them if reviewed!

Neil



Michael


Michael

Il mer 21 ago 2024, 22:25 Arseniy Krasnov  ha
scritto:


Hi, sorry, pls ping  😄

Thanks

On 08.07.2024 10:13, Arseniy Krasnov wrote:

Patchset is based on patchset for Linux (today merged to nand-next):


https://lore.kernel.org/linux-mtd/20240507230903.3399594-1-avkras...@salutedevices.com/


Here is description from it:

  >  Amlogic's boot ROM code needs that some pages on NAND must be written
  >  in special "short" ECC mode with scrambling enabled. Such pages:
  >  1) Contain some metadata about hardware.
  >  2) Located with some interval starting from 0 offset, until some
  > specified offset. Interval and second offset are set in the
  > device tree.
  >
  >  This patchset adds R/W support for such pages. To enable it we can

setup

  >  it in dts:
  >
  >  nand-is-boot-medium;
  >  amlogic,boot-pages = <1024>;
  >  amlogic,boot-page-step = <128>;
  >
  >  It means that each 128th page in range 0 to 1024 pages will be

accessed

  >  in special mode ("short" ECC + scrambling). In practice this feature

is

  >  needed when we want to update first block of NAND - driver will

enable

  >  required mode by itself using value from device tree.

The only difference is that patchset for Linux updates DT bindings, while
this adds NAND_IS_BOOT_MEDIUM flag support.

Changelog:
  v1 -> v2:
  * Pls see per-patch changelog.

Arseniy Krasnov (3):
   mtd: rawnand: nand_base: support for 'NAND_IS_BOOT_MEDIUM' flag
   mtd: rawnand: meson: refactor use of 'meson_nfc_cmd_access()'
   mtd: rawnand: meson: read/write access for boot ROM pages

  drivers/mtd/nand/raw/meson_nand.c | 84 +--
  drivers/mtd/nand/raw/nand_base.c  |  3 ++
  include/linux/mtd/rawnand.h   |  5 ++
  3 files changed, 65 insertions(+), 27 deletions(-)













Re: [PATCH v2 1/7] clk/qcom: add initial clock driver for sc7280

2024-08-22 Thread Neil Armstrong

On 22/08/2024 14:12, Caleb Connolly wrote:



On 22/08/2024 04:59, Simon Glass wrote:

Hi Caleb,

On Wed, 21 Aug 2024 at 14:33, Caleb Connolly  wrote:




On 21/08/2024 20:27, Simon Glass wrote:

Hi Caleb,

On Wed, 21 Aug 2024 at 10:47, Caleb Connolly  wrote:




On 21/08/2024 18:16, Simon Glass wrote:

Hi Caleb,

On Wed, 21 Aug 2024 at 08:49, Caleb Connolly  wrote:




On 21/08/2024 16:37, Simon Glass wrote:

Hi Caleb,

On Wed, 21 Aug 2024 at 08:11, Caleb Connolly  wrote:


Hi Simon,

+U_BOOT_DRIVER(gcc_sc7280) = {
+   .name   = "gcc_sc7280",
+   .id = UCLASS_NOP,
+   .of_match   = gcc_sc7280_of_match,
+   .bind   = qcom_cc_bind,
+   .flags  = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
+};


This should use driver model, with a UCLASS_CLK and UCLASS_RESET


Please refer to qcom_cc_bind() which binds the clock, reset, and power
domain drivers.


Gosh, why? Are these devices not in the devicetree?


They are, the gcc block contains clock, reset, and pd parts. On Linux
this is not an issue because a single device can be multiple different
classes (e..g when you register a reset you do it for a device) whereas
U-Boot requires a device per class.

e.g. see devm_reset_controller_register() in Linux, it populates a
struct reset_controller_dev which references the struct device created
for the node. In U-Boot you have to create a new device which _is_ the
reset controller.


OK, I see. Rockchip has a CRU (Clock & Reset Unit) which uses syscon
to access registers. The clock driver 'owns' the node in U-Boot and it
manually binds a reset driver. It isn't great, either.

Looking at drivers/clk/qcom/clock-sdm845.c (for example), I can't
actually find "qcom,gcc-sdm845" (for example) in U-Boot, except as a
binding. Can you please point me to the node?


It's in dts/upstream/src/arm64/qcom/sdm845.dtsi



Re devm_reset_controller_register(), yes the U-Boot driver model is a
lot more regular, e.g. we don't really want drivers creating their own
struct udevice. We want all devices to be created automatically by the
devicetree and most memory allocations to be done automatically. This
helps to reduce code size and execution time. You probably know all
this :-)


Yeah, U-Boot's model is simpler for most cases. This makes sense. But it
doesn't reflect the reality of DT so well in cases like this.


To a significant degree, the devicetree bindings are created without
much thought to efficient operation in U-Boot. I hope that eventually
this might change.


I strongly disagree with this mental model. This is the approach I see
vendors take in their BSP sources and the result is not pleasant.

DT should (within reason) never be written with the OS in mind. It is an
agnostic structure to describe the hardware. I think the new power
sequencing subsystem in Linux does a good job at embodying how we should
approach consuming DT.


I'm only really involved in mainline and don't really see vendor trees
much. An example is where pinctrl has a GPIO controller but it is not
mentioned in the devicetree. It would be better for U-Boot to add a
subnode for each GPIO controller. In general, if the SoC has a device,
it should be in the devicetree.


The concept of a device is an OS one. DT is not "telling the OS how to
use the hardware", it is describing the hardware.

This distinction is important because it's the only way to ensure that
future OS changes can be done regardless of the DT. And also of course
because different OS's will have different ideas of how to model devices
(case in point).

The GCC block on Qualcomm platforms is a single hardware block. The
datasheets and hardware programming guides describe it as such. The
clocks, resets, and GDSCs are all entwined at the hardware level. They
also have overlapping register addresses.

The further away DT gets from describing the hardware in favour of
simplifying the OS, the more likely we are to start running into issues
with fitting hardware changes into our arbitrary model.


I completely agree with everything you are saying, but you don't go
far enough. We should additionally require that all hardware has a
description in the devicetree. See for example the GPIO controller I
mentioned. When Linux wants it, it gets it, when it doesn't, it isn't
there. Sorry to have to say it, but that's not right.


If it's only used in U-Boot, that's justification enough to add the node 
upstream?






Part of this difference (between U-Boot and Linux) comes about because
Linux device setup is fairly manual, whereas U-Boot tries to put all
of that in common DM code. Whenever you are including
dm/device-internal.h that is often a sign that the binding is causing
issues.


To me this indicates an inability for U-Boot's DM to handle complicated
devices. I don't think U-Boot should dictate the design of devicetree.

I don't know how else to describe this. This issue has been litigated
over and over again on the kernel mailing list. Every

Re: [PATCH] board/qualcomm: add debug config fragments for some SoCs

2024-08-21 Thread Neil Armstrong

On 21/08/2024 01:00, Caleb Connolly wrote:

We already have some documentation describing how to enable debug UART
for Qualcomm SoCs. However the UART address varies per-soc... Add some
config fragments to enable debug UART for few well supported SoCs.

These can be used like:

$ make qcom_defconfig debug-sdm845.config

Signed-off-by: Caleb Connolly 
---
  board/qualcomm/debug-sdm845.config | 5 +
  board/qualcomm/debug-sm6115.config | 5 +
  board/qualcomm/debug-sm8250.config | 5 +
  3 files changed, 15 insertions(+)
  create mode 100644 board/qualcomm/debug-sdm845.config
  create mode 100644 board/qualcomm/debug-sm6115.config
  create mode 100644 board/qualcomm/debug-sm8250.config

diff --git a/board/qualcomm/debug-sdm845.config 
b/board/qualcomm/debug-sdm845.config
new file mode 100644
index ..31ad6d02a3a7
--- /dev/null
+++ b/board/qualcomm/debug-sdm845.config
@@ -0,0 +1,5 @@
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_BASE=0xa84000
+CONFIG_DEBUG_UART_MSM_GENI=y
+CONFIG_DEBUG_UART_CLOCK=7372800
diff --git a/board/qualcomm/debug-sm6115.config 
b/board/qualcomm/debug-sm6115.config
new file mode 100644
index ..131c6e230de8
--- /dev/null
+++ b/board/qualcomm/debug-sm6115.config
@@ -0,0 +1,5 @@
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_BASE=0x4a9
+CONFIG_DEBUG_UART_MSM_GENI=y
+CONFIG_DEBUG_UART_CLOCK=14745600
diff --git a/board/qualcomm/debug-sm8250.config 
b/board/qualcomm/debug-sm8250.config
new file mode 100644
index ..4d3cc4cc97f4
--- /dev/null
+++ b/board/qualcomm/debug-sm8250.config
@@ -0,0 +1,5 @@
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_DEBUG_UART_BASE=0xa9
+CONFIG_DEBUG_UART_MSM_GENI=y
+CONFIG_DEBUG_UART_CLOCK=14745600


Reviewed-by: Neil Armstrong 


Re: [PATCH 5/7] qcom_defconfig: enable SC7280 clocks

2024-08-19 Thread Neil Armstrong

On 09/08/2024 02:48, Caleb Connolly wrote:

Enable clocks on SC7280

Signed-off-by: Caleb Connolly 
---
  configs/qcom_defconfig | 1 +
  1 file changed, 1 insertion(+)

diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index 24b71ba7be29..1a079264a554 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -44,8 +44,9 @@ CONFIG_CLK=y
  CONFIG_CLK_QCOM_APQ8016=y
  CONFIG_CLK_QCOM_APQ8096=y
  CONFIG_CLK_QCOM_QCM2290=y
  CONFIG_CLK_QCOM_QCS404=y
+CONFIG_CLK_QCOM_SC7280=y
  CONFIG_CLK_QCOM_SDM845=y
  CONFIG_CLK_QCOM_SM6115=y
  CONFIG_CLK_QCOM_SM8250=y
  CONFIG_CLK_QCOM_SM8550=y



Reviewed-by: Neil Armstrong 


Re: [PATCH 4/7] iommu: qcom-smmu: add sc7280-smmu-500 compatible

2024-08-19 Thread Neil Armstrong

On 09/08/2024 02:48, Caleb Connolly wrote:

This soc doesn't have the generic compatible.

Signed-off-by: Caleb Connolly 
---
  drivers/iommu/qcom-hyp-smmu.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/qcom-hyp-smmu.c b/drivers/iommu/qcom-hyp-smmu.c
index 7b646d840dd4..1b5a09bb7b39 100644
--- a/drivers/iommu/qcom-hyp-smmu.c
+++ b/drivers/iommu/qcom-hyp-smmu.c
@@ -380,8 +380,9 @@ static struct iommu_ops qcom_smmu_ops = {
  };
  
  static const struct udevice_id qcom_smmu500_ids[] = {

{ .compatible = "qcom,sdm845-smmu-500" },
+   { .compatible = "qcom,sc7280-smmu-500" },
{ .compatible = "qcom,smmu-500", },
{ /* sentinel */ }
  };
  



Reviewed-by: Neil Armstrong 


Re: [PATCH 1/7] clk/qcom: add initial clock driver for sc7280

2024-08-19 Thread Neil Armstrong
USB3_PRIM_AXI_CLK:
+   qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK);
+   fallthrough;
+   case GCC_USB30_PRIM_MASTER_CLK:
+   qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
+   qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
+   break;
+   }
+
+   qcom_gate_clk_en(priv, clk->id);
+
+   return 0;
+}
+
+static const struct qcom_reset_map sc7280_gcc_resets[] = {
+   [GCC_PCIE_0_BCR] = { 0x6b000 },
+   [GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+   [GCC_PCIE_1_BCR] = { 0x8d000 },
+   [GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
+   [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
+   [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
+   [GCC_SDCC1_BCR] = { 0x75000 },
+   [GCC_SDCC2_BCR] = { 0x14000 },
+   [GCC_SDCC4_BCR] = { 0x16000 },
+   [GCC_UFS_PHY_BCR] = { 0x77000 },
+   [GCC_USB30_PRIM_BCR] = { 0xf000 },
+   [GCC_USB30_SEC_BCR] = { 0x9e000 },
+   [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 },
+   [GCC_USB3_PHY_PRIM_BCR] = { 0x5 },
+   [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 },
+   [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+};
+
+static const struct qcom_power_map sc7280_gdscs[] = {
+   [GCC_UFS_PHY_GDSC] = { 0x77004 },
+   [GCC_USB30_PRIM_GDSC] = { 0xf004 },
+};
+
+static struct msm_clk_data qcs404_gcc_data = {
+   .resets = sc7280_gcc_resets,
+   .num_resets = ARRAY_SIZE(sc7280_gcc_resets),
+   .clks = sc7280_clks,
+   .num_clks = ARRAY_SIZE(sc7280_clks),
+
+   .power_domains = sc7280_gdscs,
+   .num_power_domains = ARRAY_SIZE(sc7280_gdscs),
+
+   .enable = sc7280_enable,
+   .set_rate = sc7280_set_rate,
+};
+
+static const struct udevice_id gcc_sc7280_of_match[] = {
+   {
+   .compatible = "qcom,gcc-sc7280",
+   .data = (ulong)&qcs404_gcc_data,
+   },
+   { }
+};
+
+U_BOOT_DRIVER(gcc_sc7280) = {
+   .name   = "gcc_sc7280",
+   .id = UCLASS_NOP,
+   .of_match   = gcc_sc7280_of_match,
+   .bind   = qcom_cc_bind,
+   .flags  = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
+};



Reviewed-by: Neil Armstrong 


Re: [PATCH 00/11] mach-snapdragon: various improvements for newer boards

2024-08-19 Thread Neil Armstrong

On 09/08/2024 01:59, Caleb Connolly wrote:

Supporting the newer SM8550 and SM8650 SoCs unfortunately requires a
bump in complexity for us. Qualcomm changed a lot about how the memory
map is handed over to the "kernel", adding many holes, not mapping
certain regions, and adding regions with 0 size. The SM8650 HDK has a
whopping 14 memory regions, some as small as 44k.

Supporting this properly has proven to be a bit of a headache, but I
think this implementation is "pretty good".

In addition, we set a valid fallback fdt_addr_r in the U-Boot
environment, allocate a buffer for fastboot, and set the loadaddr
variable too.

board_fdt_blob_setup() is refactored for readability and potential
future expansion (e.g. if supporting multi-dtb FIT becomes desirable).

Finally, a function is proposed to allow for mapping new memory regions
at runtime, and the cmd-db driver makes use of it to map itself, since
SM8650 boards don't seem to include it in their memory map.

Tested on SM8650 HDK, SDM845 OnePlus 6, SM6115 RB2, SM8250 RB5.

---
Caleb Connolly (10):
   mach-snapdragon: refactor board_fdt_blob_setup()
   mach-snapdragon: parse memory ourselves
   mach-snapdragon: set serial number
   mach-snapdragon: allocate fastboot buffer dynamically
   mach-snapdragon: populate fallback FDT
   mach-snapdragon: set loadaddr
   armv8: mmu: add a way to map additional regions
   soc: qcom: cmd-db: use strncmp() instead of memcmp()
   soc: qcom: cmd-db: map cmd-db region
   qcom_defconfig: bump CONFIG_NR_DRAM_BANKS

Neil Armstrong (1):
   mach-snapdragon: use 1MiB for get_page_table_size()

  arch/arm/cpu/armv8/cache_v8.c|  25 +
  arch/arm/include/asm/system.h|  10 ++
  arch/arm/mach-snapdragon/board.c | 203 ++-
  configs/qcom_defconfig   |   1 +
  drivers/soc/qcom/cmd-db.c|  11 ++-
  5 files changed, 221 insertions(+), 29 deletions(-)
---
change-id: 20240809-b4-snapdragon-improvements-fd6d714a7fbd
base-commit: a2ce853383b18a2cf920268ee341f2585a11adef

// Caleb (they/them)



Thanks for posting those :-)

Please add my:
Reviewed-by: Neil Armstrong 

I'll rebase my tree and test it ASAP !

Neil


[PATCH v2 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling

2024-07-24 Thread Neil Armstrong
On Qualcomm systems, the setup buffer and even buffers are in
a bad state at interrupt handling, so invalidate the dcache lines
for the setup_buf and event buffer to make sure we read correct
data written by the hardware.

This fixes the following error:
dwc3-generic-peripheral usb@a60: UNKNOWN IRQ type -1
dwc3-generic-peripheral usb@a60: UNKNOWN IRQ type 4673109

and invalid situation in dwc3_gadget_giveback() because setup_buf content
is read at 0s and leads to fatal crash fixed by [1].

[1] 
https://lore.kernel.org/all/20240528-topic-sm8x50-dwc3-gadget-crash-fix-v1-1-58434ab4b...@linaro.org/

Reviewed-by: Mattijs Korpershoek 
Signed-off-by: Neil Armstrong 
---
 drivers/usb/dwc3/ep0.c| 2 ++
 drivers/usb/dwc3/gadget.c | 2 ++
 drivers/usb/dwc3/io.h | 8 
 3 files changed, 12 insertions(+)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 0c7e0123368..fc1d5892106 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -743,6 +743,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
if (!dwc->gadget_driver)
goto out;
 
+   dwc3_invalidate_cache(ctrl, sizeof(*ctrl));
+
len = le16_to_cpu(ctrl->wLength);
if (!len) {
dwc->three_stage_setup = false;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index d41b590afb8..0bc9aee4daa 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2503,6 +2503,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 
*dwc, u32 buf)
while (left > 0) {
union dwc3_event event;
 
+   dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
+
event.raw = *(u32 *) (evt->buf + evt->lpos);
 
dwc3_process_event_entry(dwc, &event);
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 1aaf5413c6d..7cf05203b0d 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -55,4 +55,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int 
length)
 
flush_dcache_range(start_addr, end_addr);
 }
+
+static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
+{
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + length, ARCH_DMA_MINALIGN);
+
+   invalidate_dcache_range(start_addr, end_addr);
+}
 #endif /* __DRIVERS_USB_DWC3_IO_H */

-- 
2.34.1



[PATCH v2 2/3] usb: dwc3: fix dcache flush range calculation

2024-07-24 Thread Neil Armstrong
The current flush operation will omit doing a flush/invalidate on
the first and last bytes if the base address and size are not aligned
with DMA_MINALIGN.

This causes operation failures Qualcomm platforms.

Take in account the alignment and size of the buffer and also
flush the previous and last cacheline.

Reviewed-by: Mattijs Korpershoek 
Signed-off-by: Neil Armstrong 
---
 drivers/usb/dwc3/io.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 04791d4c9be..1aaf5413c6d 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -50,6 +50,9 @@ static inline void dwc3_writel(void __iomem *base, u32 
offset, u32 value)
 
 static inline void dwc3_flush_cache(uintptr_t addr, int length)
 {
-   flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + length, ARCH_DMA_MINALIGN);
+
+   flush_dcache_range(start_addr, end_addr);
 }
 #endif /* __DRIVERS_USB_DWC3_IO_H */

-- 
2.34.1



[PATCH v2 0/3] dwc3: gadget: properly fix cache operations

2024-07-24 Thread Neil Armstrong
We experience huge problems with cache handling on Qualcomm
systems, and it appears the dcache handling in the DWC3 gadget
code is quite wrong and causes operational issues.

This serie fixes the dcache operations on unaligned data,
and properly invalidate buffers when reading back data from
hardware.

Signed-off-by: Neil Armstrong 
---
Changes in v2:
- Fix typo in drivers/usb/dwc3/core.h and rewrite patch 1 commit message
- Link to v1: 
https://lore.kernel.org/r/20240719-u-boot-dwc3-gadget-dcache-fixup-v1-0-58a5f026e...@linaro.org

---
Neil Armstrong (3):
  usb: dwc3: allocate setup_buf with dma_alloc_coherent()
  usb: dwc3: fix dcache flush range calculation
  usb: dwc3: invalidate dcache on buffer used in interrupt handling

 drivers/usb/dwc3/core.h   |  2 ++
 drivers/usb/dwc3/ep0.c|  6 --
 drivers/usb/dwc3/gadget.c | 10 ++
 drivers/usb/dwc3/io.h | 13 -
 4 files changed, 24 insertions(+), 7 deletions(-)
---
base-commit: 3f772959501c99fbe5aa0b22a36efe3478d1ae1c
change-id: 20240719-u-boot-dwc3-gadget-dcache-fixup-ea1e92758663

Best regards,
-- 
Neil Armstrong 



[PATCH v2 1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent()

2024-07-24 Thread Neil Armstrong
Since setup_buf is also consumed by hardware DMA, aligns it's
allocation like other hardware buffers by introduce setup_buf_addr
populated by dma_alloc_coherent(), and use it to pass the physical
address of the buffer to the hardware.

Reviewed-by: Mattijs Korpershoek 
Signed-off-by: Neil Armstrong 
---
 drivers/usb/dwc3/core.h   | 2 ++
 drivers/usb/dwc3/ep0.c| 4 ++--
 drivers/usb/dwc3/gadget.c | 8 
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 7374ce950da..b572ea340c8 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -670,6 +670,7 @@ struct dwc3_scratchpad_array {
  * @ep0_trb: dma address of ep0_trb
  * @ep0_usb_req: dummy req used while handling STD USB requests
  * @ep0_bounce_addr: dma address of ep0_bounce
+ * @setup_buf_addr: dma address of setup_buf
  * @scratch_addr: dma address of scratchbuf
  * @lock: for synchronizing
  * @dev: pointer to our struct device
@@ -757,6 +758,7 @@ struct dwc3 {
dma_addr_t  ep0_trb_addr;
dma_addr_t  ep0_bounce_addr;
dma_addr_t  scratch_addr;
+   dma_addr_t  setup_buf_addr;
struct dwc3_request ep0_usb_req;
 
/* device lock */
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 16b11ce3d9f..0c7e0123368 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -381,7 +381,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
-   dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+   dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
 
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@@ -663,7 +663,7 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct 
usb_ctrlrequest *ctrl)
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
-   dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+   dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
 
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7d6bcc2627f..d41b590afb8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2622,8 +2622,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err1;
}
 
-   dwc->setup_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
- DWC3_EP0_BOUNCE_SIZE);
+   dwc->setup_buf = dma_alloc_coherent(DWC3_EP0_BOUNCE_SIZE,
+   (unsigned long *)&dwc->setup_buf_addr);
if (!dwc->setup_buf) {
ret = -ENOMEM;
goto err2;
@@ -2670,7 +2670,7 @@ err4:
dma_free_coherent(dwc->ep0_bounce);
 
 err3:
-   kfree(dwc->setup_buf);
+   dma_free_coherent(dwc->setup_buf);
 
 err2:
dma_free_coherent(dwc->ep0_trb);
@@ -2692,7 +2692,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
dma_free_coherent(dwc->ep0_bounce);
 
-   kfree(dwc->setup_buf);
+   dma_free_coherent(dwc->setup_buf);
 
dma_free_coherent(dwc->ep0_trb);
 

-- 
2.34.1



Re: [PATCH 1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent()

2024-07-24 Thread Neil Armstrong

On 24/07/2024 17:03, Mattijs Korpershoek wrote:

Hi Neil,

Thank you for the patch.

On ven., juil. 19, 2024 at 15:56, Neil Armstrong  
wrote:


Also allocate the setup_buf with dma_alloc_coherent() since it's


The subject of the patch says:

"usb: dwc3: allocate setup_buf with dma_alloc_coherent()"

Isn't this line just repeating the title?


also consumed by the hardware DMA.


Yeah it's a verbose rewrite of the subject, I'll rewrite it to be less bad!

thanks
Neil



Signed-off-by: Neil Armstrong 
---
  drivers/usb/dwc3/core.h   | 2 ++
  drivers/usb/dwc3/ep0.c| 4 ++--
  drivers/usb/dwc3/gadget.c | 8 
  3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 7374ce950da..ce35460c405 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -670,6 +670,7 @@ struct dwc3_scratchpad_array {
   * @ep0_trb: dma address of ep0_trb
   * @ep0_usb_req: dummy req used while handling STD USB requests
   * @ep0_bounce_addr: dma address of ep0_bounce
+ * @setup_buf_addr: dma address if setup_buf


if -> of

Both remarks being minor, please add:

Reviewed-by: Mattijs Korpershoek 


   * @scratch_addr: dma address of scratchbuf
   * @lock: for synchronizing
   * @dev: pointer to our struct device
@@ -757,6 +758,7 @@ struct dwc3 {
dma_addr_t  ep0_trb_addr;
dma_addr_t  ep0_bounce_addr;
dma_addr_t  scratch_addr;
+   dma_addr_t  setup_buf_addr;
struct dwc3_request ep0_usb_req;
  
  	/* device lock */

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 16b11ce3d9f..0c7e0123368 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -381,7 +381,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
-   dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+   dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
  
  	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);

@@ -663,7 +663,7 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct 
usb_ctrlrequest *ctrl)
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
-   dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+   dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
  
  	return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7d6bcc2627f..d41b590afb8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2622,8 +2622,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err1;
}
  
-	dwc->setup_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,

- DWC3_EP0_BOUNCE_SIZE);
+   dwc->setup_buf = dma_alloc_coherent(DWC3_EP0_BOUNCE_SIZE,
+   (unsigned long *)&dwc->setup_buf_addr);
if (!dwc->setup_buf) {
ret = -ENOMEM;
goto err2;
@@ -2670,7 +2670,7 @@ err4:
dma_free_coherent(dwc->ep0_bounce);
  
  err3:

-   kfree(dwc->setup_buf);
+   dma_free_coherent(dwc->setup_buf);
  
  err2:

dma_free_coherent(dwc->ep0_trb);
@@ -2692,7 +2692,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
  
  	dma_free_coherent(dwc->ep0_bounce);
  
-	kfree(dwc->setup_buf);

+   dma_free_coherent(dwc->setup_buf);
  
  	dma_free_coherent(dwc->ep0_trb);
  


--
2.34.1




[PATCH 3/3] usb: dwc3: invalidate dcache on buffer used in interrupt handling

2024-07-19 Thread Neil Armstrong
On Qualcomm systems, the setup buffer and even buffers are in
a bad state at interrupt handling, so invalidate the dcache lines
for the setup_buf and event buffer to make sure we read correct
data written by the hardware.

This fixes the following error:
dwc3-generic-peripheral usb@a60: UNKNOWN IRQ type -1
dwc3-generic-peripheral usb@a60: UNKNOWN IRQ type 4673109

and invalid situation in dwc3_gadget_giveback() because setup_buf content
is read at 0s and leads to fatal crash fixed by [1].

[1] 
https://lore.kernel.org/all/20240528-topic-sm8x50-dwc3-gadget-crash-fix-v1-1-58434ab4b...@linaro.org/

Signed-off-by: Neil Armstrong 
---
 drivers/usb/dwc3/ep0.c| 2 ++
 drivers/usb/dwc3/gadget.c | 2 ++
 drivers/usb/dwc3/io.h | 8 
 3 files changed, 12 insertions(+)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 0c7e0123368..fc1d5892106 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -743,6 +743,8 @@ static void dwc3_ep0_inspect_setup(struct dwc3 *dwc,
if (!dwc->gadget_driver)
goto out;
 
+   dwc3_invalidate_cache(ctrl, sizeof(*ctrl));
+
len = le16_to_cpu(ctrl->wLength);
if (!len) {
dwc->three_stage_setup = false;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index d41b590afb8..0bc9aee4daa 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2503,6 +2503,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 
*dwc, u32 buf)
while (left > 0) {
union dwc3_event event;
 
+   dwc3_invalidate_cache((uintptr_t)evt->buf, evt->length);
+
event.raw = *(u32 *) (evt->buf + evt->lpos);
 
dwc3_process_event_entry(dwc, &event);
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 1aaf5413c6d..7cf05203b0d 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -55,4 +55,12 @@ static inline void dwc3_flush_cache(uintptr_t addr, int 
length)
 
flush_dcache_range(start_addr, end_addr);
 }
+
+static inline void dwc3_invalidate_cache(uintptr_t addr, int length)
+{
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + length, ARCH_DMA_MINALIGN);
+
+   invalidate_dcache_range(start_addr, end_addr);
+}
 #endif /* __DRIVERS_USB_DWC3_IO_H */

-- 
2.34.1



[PATCH 2/3] usb: dwc3: fix dcache flush range calculation

2024-07-19 Thread Neil Armstrong
The current flush operation will omit doing a flush/invalidate on
the first and last bytes if the base address and size are not aligned
with DMA_MINALIGN.

This causes operation failures Qualcomm platforms.

Take in account the alignment and size of the buffer and also
flush the previous and last cacheline.

Signed-off-by: Neil Armstrong 
---
 drivers/usb/dwc3/io.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 04791d4c9be..1aaf5413c6d 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -50,6 +50,9 @@ static inline void dwc3_writel(void __iomem *base, u32 
offset, u32 value)
 
 static inline void dwc3_flush_cache(uintptr_t addr, int length)
 {
-   flush_dcache_range(addr, addr + ROUND(length, CACHELINE_SIZE));
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + length, ARCH_DMA_MINALIGN);
+
+   flush_dcache_range(start_addr, end_addr);
 }
 #endif /* __DRIVERS_USB_DWC3_IO_H */

-- 
2.34.1



[PATCH 1/3] usb: dwc3: allocate setup_buf with dma_alloc_coherent()

2024-07-19 Thread Neil Armstrong
Also allocate the setup_buf with dma_alloc_coherent() since it's
also consumed by the hardware DMA.

Signed-off-by: Neil Armstrong 
---
 drivers/usb/dwc3/core.h   | 2 ++
 drivers/usb/dwc3/ep0.c| 4 ++--
 drivers/usb/dwc3/gadget.c | 8 
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 7374ce950da..ce35460c405 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -670,6 +670,7 @@ struct dwc3_scratchpad_array {
  * @ep0_trb: dma address of ep0_trb
  * @ep0_usb_req: dummy req used while handling STD USB requests
  * @ep0_bounce_addr: dma address of ep0_bounce
+ * @setup_buf_addr: dma address if setup_buf
  * @scratch_addr: dma address of scratchbuf
  * @lock: for synchronizing
  * @dev: pointer to our struct device
@@ -757,6 +758,7 @@ struct dwc3 {
dma_addr_t  ep0_trb_addr;
dma_addr_t  ep0_bounce_addr;
dma_addr_t  scratch_addr;
+   dma_addr_t  setup_buf_addr;
struct dwc3_request ep0_usb_req;
 
/* device lock */
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 16b11ce3d9f..0c7e0123368 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -381,7 +381,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
-   dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+   dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
 
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@@ -663,7 +663,7 @@ static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct 
usb_ctrlrequest *ctrl)
dep = dwc->eps[0];
dwc->ep0_usb_req.dep = dep;
dwc->ep0_usb_req.request.length = dep->endpoint.maxpacket;
-   dwc->ep0_usb_req.request.buf = dwc->setup_buf;
+   dwc->ep0_usb_req.request.buf = (void *)dwc->setup_buf_addr;
dwc->ep0_usb_req.request.complete = dwc3_ep0_set_sel_cmpl;
 
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 7d6bcc2627f..d41b590afb8 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2622,8 +2622,8 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err1;
}
 
-   dwc->setup_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
- DWC3_EP0_BOUNCE_SIZE);
+   dwc->setup_buf = dma_alloc_coherent(DWC3_EP0_BOUNCE_SIZE,
+   (unsigned long *)&dwc->setup_buf_addr);
if (!dwc->setup_buf) {
ret = -ENOMEM;
goto err2;
@@ -2670,7 +2670,7 @@ err4:
dma_free_coherent(dwc->ep0_bounce);
 
 err3:
-   kfree(dwc->setup_buf);
+   dma_free_coherent(dwc->setup_buf);
 
 err2:
dma_free_coherent(dwc->ep0_trb);
@@ -2692,7 +2692,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
dma_free_coherent(dwc->ep0_bounce);
 
-   kfree(dwc->setup_buf);
+   dma_free_coherent(dwc->setup_buf);
 
dma_free_coherent(dwc->ep0_trb);
 

-- 
2.34.1



[PATCH 0/3] dwc3: gadget: properly fix cache operations

2024-07-19 Thread Neil Armstrong
We experience huge problems with cache handling on Qualcomm
systems, and it appears the dcache handling in the DWC3 gadget
code is quite wrong and causes operational issues.

This serie fixes the dcache operations on unaligned data,
and properly invalidate buffers when reading back data from
hardware.

Signed-off-by: Neil Armstrong 
---
Neil Armstrong (3):
  usb: dwc3: allocate setup_buf with dma_alloc_coherent()
  usb: dwc3: fix dcache flush range calculation
  usb: dwc3: invalidate dcache on buffer used in interrupt handling

 drivers/usb/dwc3/core.h   |  2 ++
 drivers/usb/dwc3/ep0.c|  6 --
 drivers/usb/dwc3/gadget.c | 10 ++
 drivers/usb/dwc3/io.h | 13 -
 4 files changed, 24 insertions(+), 7 deletions(-)
---
base-commit: 3f772959501c99fbe5aa0b22a36efe3478d1ae1c
change-id: 20240719-u-boot-dwc3-gadget-dcache-fixup-ea1e92758663

Best regards,
-- 
Neil Armstrong 



[PATCH 3/4] ufs: split flush and invalidate to only invalidate when required

2024-07-19 Thread Neil Armstrong
There is no need to flush and invalidate all data updated by the
driver, mainly because on ARM platforms flush also invalidates
the cachelines.

Split the function in two and add the appropriate cacheline
invalidates after the UFS DMA operation finishes to make sure
we read from memory.

Flushing then invalidating cacheline unaligned data causes data
corruption issues on Qualcomm platforms, and is largely unnecessary
anyway, so let's cleanup the cache operations.

Signed-off-by: Neil Armstrong 
---
 drivers/ufs/ufs.c | 45 ++---
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index db487d1ff9a..76cda83ce81 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -697,17 +697,28 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
 }
 
 /**
- * ufshcd_cache_flush_and_invalidate - Flush and invalidate cache
+ * ufshcd_cache_flush - Flush cache
  *
- * Flush and invalidate cache in aligned address..address+size range.
- * The invalidation is in place to avoid stale data in cache.
+ * Flush cache in aligned address..address+size range.
  */
-static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size)
+static void ufshcd_cache_flush(void *addr, unsigned long size)
 {
uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
 
flush_dcache_range(start_addr, end_addr);
+}
+
+/**
+ * ufshcd_cache_invalidate - Invalidate cache
+ *
+ * Invalidate cache in aligned address..address+size range.
+ */
+static void ufshcd_cache_invalidate(void *addr, unsigned long size)
+{
+   uintptr_t start_addr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
+   uintptr_t end_addr = ALIGN((uintptr_t)addr + size, ARCH_DMA_MINALIGN);
+
invalidate_dcache_range(start_addr, end_addr);
 }
 
@@ -755,7 +766,7 @@ static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba,
 
req_desc->prd_table_length = 0;
 
-   ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc));
+   ufshcd_cache_flush(req_desc, sizeof(*req_desc));
 }
 
 static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
@@ -786,13 +797,13 @@ static void ufshcd_prepare_utp_query_req_upiu(struct 
ufs_hba *hba,
/* Copy the Descriptor */
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) {
memcpy(ucd_req_ptr + 1, query->descriptor, len);
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 2 * 
sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, 2 * sizeof(*ucd_req_ptr));
} else {
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 
sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
}
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba)
@@ -810,8 +821,8 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct 
ufs_hba *hba)
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 /**
@@ -878,6 +889,8 @@ static int ufshcd_send_command(struct ufs_hba *hba, 
unsigned int task_tag)
  */
 static inline int ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr)
 {
+   ufshcd_cache_invalidate(ucd_rsp_ptr, sizeof(*ucd_rsp_ptr));
+
return be32_to_cpu(ucd_rsp_ptr->header.dword_0) >> 24;
 }
 
@@ -889,6 +902,8 @@ static inline int ufshcd_get_tr_ocs(struct ufs_hba *hba)
 {
struct utp_transfer_req_desc *req_desc = hba->utrdl;
 
+   ufshcd_cache_invalidate(req_desc, sizeof(*req_desc));
+
return le32_to_cpu(req_desc->header.dword_2) & MASK_OCS;
 }
 
@@ -1438,8 +1453,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufs_hba *hba,
memcpy(ucd_req_ptr->sc.cdb, pccb->cmd, cdb_len);
 
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
-   ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
-   ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, 
sizeof(*hba->ucd_rsp_ptr));
+   ufshcd_cache_flush(ucd_req_ptr, sizeof(*ucd_req_ptr));
+   ufshcd_cache_flush(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr));
 }
 
 static inline void prepare_prdt_desc(struct ufshcd_sg_entry *entry,
@@ -1462,7 +1477,7 @@ static void prepare_prdt_table(struct ufs_hba *hba, 
str

  1   2   3   4   5   6   7   8   9   10   >