mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-04 12:21:03 +02:00
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
This commit is contained in:
commit
dba21bf0b6
@ -1890,6 +1890,7 @@ M: Neil Armstrong <neil.armstrong@linaro.org>
|
||||
M: Bhupesh Sharma <bhupesh.linux@gmail.com>
|
||||
M: Neha Malcom Francis <n-francis@ti.com>
|
||||
S: Maintained
|
||||
F: common/spl/spl_ufs.c
|
||||
F: drivers/ufs/
|
||||
|
||||
UPL
|
||||
|
||||
@ -30,6 +30,7 @@ enum {
|
||||
BOOT_DEVICE_XIP,
|
||||
BOOT_DEVICE_BOOTROM,
|
||||
BOOT_DEVICE_SMH,
|
||||
BOOT_DEVICE_UFS,
|
||||
BOOT_DEVICE_NONE
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -1613,6 +1613,36 @@ config SPL_THERMAL
|
||||
automatic power-off when the temperature gets too high or low. Other
|
||||
devices may be discrete but connected on a suitable bus.
|
||||
|
||||
config SPL_UFS_SUPPORT
|
||||
bool "Support loading from UFS"
|
||||
depends on UFS
|
||||
select SPL_LOAD_BLOCK
|
||||
help
|
||||
Enable support for UFS in SPL. This allows
|
||||
use of UFS devices such as hard drives and flash drivers for
|
||||
loading U-Boot.
|
||||
|
||||
config SPL_UFS_RAW_U_BOOT_DEVNUM
|
||||
int "SCSI device number of the UFS device to load U-Boot from"
|
||||
depends on SPL_UFS_SUPPORT
|
||||
default 0
|
||||
help
|
||||
UFS devices are usually configured with multiple LUNs, which present
|
||||
themselves as sequentially numbered SCSI devices. Usually one would
|
||||
get a default LUN 0 taking up most of the space on the device, with
|
||||
a number of smaller LUNs following it. This option controls which of
|
||||
them the SPL will attempt to load U-Boot from. Note that this is the
|
||||
SCSI device number, which might differ from the UFS LUN if you have
|
||||
multiple SCSI devices attached and recognized by the SPL.
|
||||
|
||||
config SPL_UFS_RAW_U_BOOT_SECTOR
|
||||
hex "Address on the UFS to load U-Boot from"
|
||||
depends on SPL_UFS_SUPPORT
|
||||
default 0x800 if ARCH_ROCKCHIP
|
||||
help
|
||||
Address on the block device to load U-Boot from.
|
||||
Units: UFS sectors (1 sector = 4096 bytes).
|
||||
|
||||
config SPL_WATCHDOG
|
||||
bool "Support watchdog drivers"
|
||||
imply SPL_WDT if !HW_WATCHDOG
|
||||
|
||||
@ -37,6 +37,7 @@ obj-$(CONFIG_$(PHASE_)DFU) += spl_dfu.o
|
||||
obj-$(CONFIG_$(PHASE_)SPI_LOAD) += spl_spi.o
|
||||
obj-$(CONFIG_$(PHASE_)RAM_SUPPORT) += spl_ram.o
|
||||
obj-$(CONFIG_$(PHASE_)USB_SDP_SUPPORT) += spl_sdp.o
|
||||
obj-$(CONFIG_$(PHASE_)UFS_SUPPORT) += spl_ufs.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_$(PHASE_)UPL) += spl_upl.o
|
||||
|
||||
49
common/spl/spl_ufs.c
Normal file
49
common/spl/spl_ufs.c
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2025 Alexey Charkov <alchark@gmail.com>
|
||||
*/
|
||||
|
||||
#include <spl.h>
|
||||
#include <spl_load.h>
|
||||
#include <scsi.h>
|
||||
#include <errno.h>
|
||||
#include <image.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <log.h>
|
||||
|
||||
static ulong spl_ufs_load_read(struct spl_load_info *load, ulong off, ulong size, void *buf)
|
||||
{
|
||||
struct blk_desc *bd = load->priv;
|
||||
lbaint_t sector = off >> bd->log2blksz;
|
||||
lbaint_t count = size >> bd->log2blksz;
|
||||
|
||||
return blk_dread(bd, sector, count, buf) << bd->log2blksz;
|
||||
}
|
||||
|
||||
static int spl_ufs_load_image(struct spl_image_info *spl_image,
|
||||
struct spl_boot_device *bootdev)
|
||||
{
|
||||
unsigned long sector = CONFIG_SPL_UFS_RAW_U_BOOT_SECTOR;
|
||||
int devnum = CONFIG_SPL_UFS_RAW_U_BOOT_DEVNUM;
|
||||
struct spl_load_info load;
|
||||
struct blk_desc *bd;
|
||||
int err;
|
||||
|
||||
/* try to recognize storage devices immediately */
|
||||
scsi_scan(false);
|
||||
bd = blk_get_devnum_by_uclass_id(UCLASS_SCSI, devnum);
|
||||
if (!bd)
|
||||
return -ENODEV;
|
||||
|
||||
spl_load_init(&load, spl_ufs_load_read, bd, bd->blksz);
|
||||
err = spl_load(spl_image, bootdev, &load, 0, sector << bd->log2blksz);
|
||||
if (err) {
|
||||
puts("spl_ufs_load_image: ufs block read error\n");
|
||||
log_debug("(error=%d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPL_LOAD_IMAGE_METHOD("UFS", 0, BOOT_DEVICE_UFS, spl_ufs_load_image);
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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[] = {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -147,6 +147,7 @@ else
|
||||
obj-$(CONFIG_$(PHASE_)SPRINTF) += vsprintf.o
|
||||
endif
|
||||
obj-$(CONFIG_$(PHASE_)STRTO) += strto.o
|
||||
obj-$(CONFIG_$(PHASE_)UFS_SUPPORT) += charset.o
|
||||
else
|
||||
# Main U-Boot always uses the full printf support
|
||||
obj-y += vsprintf.o strto.o
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user