diff options
| author | Tom Rini <[email protected]> | 2026-03-13 09:01:53 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-03-13 10:52:03 -0600 |
| commit | dba21bf0b6ececa4bbc15ac93b3cdf4b09286ed7 (patch) | |
| tree | dd57833421f4b24cdbee47249405df46d7a49e96 /drivers | |
| parent | 2f52473884723751316388af30a95419905b1cd3 (diff) | |
| parent | 67d8731d4aad25be00e27eeef3602c519619405e (diff) | |
Merge tag 'u-boot-ufs-20260313' of https://source.denx.de/u-boot/custodians/u-boot-ufs into next
- ufs_hba_ops callbacks cleanup
- Rockchip UFS reset support
- UFS support in SPL
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/Makefile | 1 | ||||
| -rw-r--r-- | drivers/scsi/Makefile | 3 | ||||
| -rw-r--r-- | drivers/ufs/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/ufs/ufs-rockchip.c | 31 | ||||
| -rw-r--r-- | drivers/ufs/ufs-rockchip.h | 1 | ||||
| -rw-r--r-- | drivers/ufs/ufs-uclass.c | 36 | ||||
| -rw-r--r-- | drivers/ufs/ufs.h | 10 |
7 files changed, 69 insertions, 17 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index de993ae42ac..43d0ba33281 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_SPL_USB_HOST) += usb/host/ obj-$(CONFIG_SPL_SATA) += ata/ scsi/ obj-$(CONFIG_SPL_LEGACY_BLOCK) += block/ obj-$(CONFIG_SPL_THERMAL) += thermal/ +obj-$(CONFIG_SPL_UFS_SUPPORT) += scsi/ ufs/ endif endif diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b76de1b22a8..c9af60d5d03 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -16,4 +16,7 @@ ifdef CONFIG_XPL_BUILD ifdef CONFIG_SPL_SATA obj-$(CONFIG_SCSI) += scsi.o scsi-uclass.o endif +ifdef CONFIG_SPL_UFS_SUPPORT +obj-$(CONFIG_SCSI) += scsi.o scsi-uclass.o +endif endif diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig index 6c75bb2a079..49472933de3 100644 --- a/drivers/ufs/Kconfig +++ b/drivers/ufs/Kconfig @@ -76,6 +76,10 @@ config UFS_RENESAS_GEN5 config UFS_ROCKCHIP bool "Rockchip specific hooks to UFS controller platform driver" depends on UFS + depends on DM_GPIO + depends on RESET_ROCKCHIP + depends on SPL_DM_GPIO || !SPL_UFS_SUPPORT + depends on SPL_RESET_ROCKCHIP || !SPL_UFS_SUPPORT help This selects the Rockchip specific additions to UFSHCD platform driver. diff --git a/drivers/ufs/ufs-rockchip.c b/drivers/ufs/ufs-rockchip.c index 643a6ffb9bc..a13236c7f76 100644 --- a/drivers/ufs/ufs-rockchip.c +++ b/drivers/ufs/ufs-rockchip.c @@ -5,6 +5,7 @@ * Copyright (C) 2025 Rockchip Electronics Co.Ltd. */ +#include <asm/gpio.h> #include <asm/io.h> #include <clk.h> #include <dm.h> @@ -29,12 +30,9 @@ static int ufs_rockchip_hce_enable_notify(struct ufs_hba *hba, ufshcd_dme_reset(hba); ufshcd_dme_enable(hba); - if (hba->ops->phy_initialization) { - err = hba->ops->phy_initialization(hba); - if (err) - dev_err(hba->dev, - "Phy init failed (%d)\n", err); - } + err = ufshcd_ops_phy_initialization(hba); + if (err) + dev_err(hba->dev, "Phy init failed (%d)\n", err); return err; } @@ -152,11 +150,31 @@ static int ufs_rockchip_common_init(struct ufs_hba *hba) return err; } + err = gpio_request_by_name(dev, "reset-gpios", 0, &host->device_reset, + GPIOD_IS_OUT | GPIOD_ACTIVE_LOW); + if (err) { + dev_err(dev, "Cannot get reset GPIO\n"); + return err; + } + host->hba = hba; return 0; } +static int ufs_rockchip_device_reset(struct ufs_hba *hba) +{ + struct ufs_rockchip_host *host = dev_get_priv(hba->dev); + + dm_gpio_set_value(&host->device_reset, true); + udelay(20); + + dm_gpio_set_value(&host->device_reset, false); + udelay(20); + + return 0; +} + static int ufs_rockchip_rk3576_init(struct ufs_hba *hba) { int ret = 0; @@ -174,6 +192,7 @@ static struct ufs_hba_ops ufs_hba_rk3576_vops = { .init = ufs_rockchip_rk3576_init, .phy_initialization = ufs_rockchip_rk3576_phy_init, .hce_enable_notify = ufs_rockchip_hce_enable_notify, + .device_reset = ufs_rockchip_device_reset, }; static const struct udevice_id ufs_rockchip_of_match[] = { diff --git a/drivers/ufs/ufs-rockchip.h b/drivers/ufs/ufs-rockchip.h index 3dcb80f5702..50c2539da78 100644 --- a/drivers/ufs/ufs-rockchip.h +++ b/drivers/ufs/ufs-rockchip.h @@ -72,6 +72,7 @@ struct ufs_rockchip_host { void __iomem *ufs_sys_ctrl; void __iomem *mphy_base; struct reset_ctl_bulk rsts; + struct gpio_desc device_reset; struct clk ref_out_clk; uint64_t caps; uint32_t phy_config_mode; diff --git a/drivers/ufs/ufs-uclass.c b/drivers/ufs/ufs-uclass.c index 7a80a9d5664..bb997aace8f 100644 --- a/drivers/ufs/ufs-uclass.c +++ b/drivers/ufs/ufs-uclass.c @@ -127,11 +127,6 @@ 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 @@ -512,7 +507,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba) int retries = DME_LINKSTARTUP_RETRIES; do { - ufshcd_ops_link_startup_notify(hba, PRE_CHANGE); + ret = ufshcd_ops_link_startup_notify(hba, PRE_CHANGE); + if (ret) + goto out; ret = ufshcd_dme_link_startup(hba); @@ -598,12 +595,18 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba) static int ufshcd_hba_enable(struct ufs_hba *hba) { int retry; + int ret; if (!ufshcd_is_hba_active(hba)) /* change controller state to "reset state" */ ufshcd_hba_stop(hba); - ufshcd_ops_hce_enable_notify(hba, PRE_CHANGE); + ret = ufshcd_ops_hce_enable_notify(hba, PRE_CHANGE); + if (ret) { + dev_err(hba->dev, "Controller enable notify PRE_CHANGE failed: %i\n", + ret); + return ret; + } /* start controller initialization sequence */ ufshcd_hba_start(hba); @@ -635,7 +638,12 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) /* enable UIC related interrupts */ ufshcd_enable_intr(hba, UFSHCD_UIC_MASK); - ufshcd_ops_hce_enable_notify(hba, POST_CHANGE); + ret = ufshcd_ops_hce_enable_notify(hba, POST_CHANGE); + if (ret) { + dev_err(hba->dev, "Controller enable notify POST_CHANGE failed: %i\n", + ret); + return ret; + } return 0; } @@ -2184,7 +2192,11 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) /* Set descriptor lengths to specification defaults */ ufshcd_def_desc_sizes(hba); - ufshcd_ops_init(hba); + err = ufshcd_ops_init(hba); + if (err) { + dev_err(hba->dev, "Host controller init failed: %i\n", err); + return err; + } /* Read capabilities registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES); @@ -2228,7 +2240,11 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) mb(); /* flush previous writes */ /* Reset the attached device */ - ufshcd_device_reset(hba); + err = ufshcd_vops_device_reset(hba); + if (err) { + dev_err(hba->dev, "Failed to reset attached device: %i\n", err); + return err; + } err = ufshcd_hba_enable(hba); if (err) { diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index bc839a43704..0f6c93fbce7 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -509,7 +509,7 @@ struct ufs_query { }; /** - * struct ufs_dev_cmd - all assosiated fields with device management commands + * struct ufs_dev_cmd - all associated fields with device management commands * @type: device management command type - Query, NOP OUT * @tag_wq: wait queue until free command slot is available */ @@ -756,6 +756,14 @@ static inline int ufshcd_ops_link_startup_notify(struct ufs_hba *hba, return 0; } +static inline int ufshcd_ops_phy_initialization(struct ufs_hba *hba) +{ + if (hba->ops && hba->ops->phy_initialization) + return hba->ops->phy_initialization(hba); + + return 0; +} + static inline int ufshcd_vops_device_reset(struct ufs_hba *hba) { if (hba->ops && hba->ops->device_reset) |
