mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-16 01:44:34 +00:00
Merge patch series "ufs: Add a PCI UFS controller support"
To quote the author: This adds a PCI UFS controller support and enables the support on QEMU RISC-V for testing. Requiring QEMU v8.2+.
This commit is contained in:
commit
d6e052c615
11 changed files with 97 additions and 15 deletions
|
@ -81,5 +81,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
|
|||
imply USB_XHCI_PCI
|
||||
imply USB_KEYBOARD
|
||||
imply CMD_USB
|
||||
imply UFS
|
||||
imply UFS_PCI
|
||||
|
||||
endif
|
||||
|
|
|
@ -1520,7 +1520,7 @@ config CMD_TSI148
|
|||
Turndra tsi148 device. See the command help for full details.
|
||||
|
||||
config CMD_UFS
|
||||
bool "Enable UFS - Universal Flash Subsystem commands"
|
||||
bool "ufs - Universal Flash Storage commands"
|
||||
depends on UFS
|
||||
help
|
||||
"This provides commands to initialise and configure universal flash
|
||||
|
|
|
@ -32,6 +32,6 @@ static int do_ufs(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
|||
}
|
||||
|
||||
U_BOOT_CMD(ufs, 3, 1, do_ufs,
|
||||
"UFS sub system",
|
||||
"UFS sub-system",
|
||||
"init [dev] - init UFS subsystem\n"
|
||||
);
|
||||
|
|
|
@ -131,7 +131,13 @@ An attached disk can be emulated in RISC-V virt machine by adding::
|
|||
-drive if=none,file=riscv64.img,format=raw,id=mydisk \
|
||||
-device ide-hd,drive=mydisk,bus=ahci.0
|
||||
|
||||
You will have to run 'scsi scan' to use it.
|
||||
or alternatively attach an emulated UFS::
|
||||
|
||||
-device ufs,id=ufs0 \
|
||||
-drive if=none,file=test.img,format=raw,id=lun0 \
|
||||
-device ufs-lu,drive=lun0,bus=ufs0
|
||||
|
||||
You will have to run 'scsi scan' to use them.
|
||||
|
||||
A video console can be emulated in RISC-V virt machine by removing "-nographic"
|
||||
and adding::
|
||||
|
|
|
@ -15,6 +15,17 @@ config CADENCE_UFS
|
|||
This selects the platform driver for the Cadence UFS host
|
||||
controller present on present TI's J721e devices.
|
||||
|
||||
config UFS_PCI
|
||||
bool "PCI bus based UFS Controller support"
|
||||
depends on PCI && UFS
|
||||
help
|
||||
This selects the PCI UFS Host Controller Interface. Select this if
|
||||
you have UFS Host Controller with PCI Interface.
|
||||
|
||||
If you have a controller with this interface, say Y here.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config TI_J721E_UFS
|
||||
bool "Glue Layer driver for UFS on TI J721E devices"
|
||||
help
|
||||
|
|
|
@ -6,4 +6,5 @@
|
|||
obj-$(CONFIG_UFS) += ufs.o ufs-uclass.o
|
||||
obj-$(CONFIG_CADENCE_UFS) += cdns-platform.o
|
||||
obj-$(CONFIG_TI_J721E_UFS) += ti-j721e-ufs.o
|
||||
obj-$(CONFIG_UFS_PCI) += ufs-pci.o
|
||||
obj-$(CONFIG_UFS_RENESAS) += ufs-renesas.o
|
||||
|
|
45
drivers/ufs/ufs-pci.c
Normal file
45
drivers/ufs/ufs-pci.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2023 tinylab.org
|
||||
* Author: Bin Meng <bmeng@tinylab.org>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <pci.h>
|
||||
#include <ufs.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include "ufs.h"
|
||||
|
||||
static int ufs_pci_bind(struct udevice *dev)
|
||||
{
|
||||
struct udevice *scsi_dev;
|
||||
|
||||
return ufs_scsi_bind(dev, &scsi_dev);
|
||||
}
|
||||
|
||||
static int ufs_pci_probe(struct udevice *dev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ufshcd_probe(dev, NULL);
|
||||
if (err)
|
||||
dev_err(dev, "%s failed (ret=%d)\n", __func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(ufs_pci) = {
|
||||
.name = "ufs_pci",
|
||||
.id = UCLASS_UFS,
|
||||
.bind = ufs_pci_bind,
|
||||
.probe = ufs_pci_probe,
|
||||
};
|
||||
|
||||
static struct pci_device_id ufs_supported[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_UFS) },
|
||||
{},
|
||||
};
|
||||
|
||||
U_BOOT_PCI_DEVICE(ufs_pci, ufs_supported);
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/**
|
||||
* ufs-uclass.c - Universal Flash Subsystem (UFS) Uclass driver
|
||||
* ufs-uclass.c - Universal Flash Storage (UFS) Uclass driver
|
||||
*
|
||||
* Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/**
|
||||
* ufs.c - Universal Flash Subsystem (UFS) driver
|
||||
* ufs.c - Universal Flash Storage (UFS) driver
|
||||
*
|
||||
* Taken from Linux Kernel v5.2 (drivers/scsi/ufs/ufshcd.c) and ported
|
||||
* to u-boot.
|
||||
|
@ -320,7 +320,7 @@ static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer)
|
|||
UIC_ARG_MPHY_TX_GEN_SEL_INDEX(i)),
|
||||
0);
|
||||
if (err) {
|
||||
dev_err(hba->dev, "%s: TX LCC Disable failed, peer = %d, lane = %d, err = %d",
|
||||
dev_err(hba->dev, "%s: TX LCC Disable failed, peer = %d, lane = %d, err = %d\n",
|
||||
__func__, peer, i, err);
|
||||
break;
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba)
|
|||
ufshcd_enable_run_stop_reg(hba);
|
||||
} else {
|
||||
dev_err(hba->dev,
|
||||
"Host controller not ready to process requests");
|
||||
"Host controller not ready to process requests\n");
|
||||
err = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ static int ufshcd_copy_query_response(struct ufs_hba *hba)
|
|||
memcpy(hba->dev_cmd.query.descriptor, descp, resp_len);
|
||||
} else {
|
||||
dev_warn(hba->dev,
|
||||
"%s: Response size is bigger than buffer",
|
||||
"%s: Response size is bigger than buffer\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1179,11 +1179,11 @@ static int ufshcd_read_desc_length(struct ufs_hba *hba, enum desc_idn desc_id,
|
|||
&header_len);
|
||||
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "%s: Failed to get descriptor header id %d",
|
||||
dev_err(hba->dev, "%s: Failed to get descriptor header id %d\n",
|
||||
__func__, desc_id);
|
||||
return ret;
|
||||
} else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) {
|
||||
dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch",
|
||||
dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch\n",
|
||||
__func__, header[QUERY_DESC_DESC_TYPE_OFFSET],
|
||||
desc_id);
|
||||
ret = -EINVAL;
|
||||
|
@ -1302,7 +1302,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id,
|
|||
|
||||
/* Sanity checks */
|
||||
if (ret || !buff_len) {
|
||||
dev_err(hba->dev, "%s: Failed to get full descriptor length",
|
||||
dev_err(hba->dev, "%s: Failed to get full descriptor length\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1323,14 +1323,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id,
|
|||
&buff_len);
|
||||
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d",
|
||||
dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
|
||||
__func__, desc_id, desc_index, param_offset, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
|
||||
dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header",
|
||||
dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n",
|
||||
__func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
@ -1914,6 +1914,7 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops)
|
|||
struct ufs_hba *hba = dev_get_uclass_priv(ufs_dev);
|
||||
struct scsi_plat *scsi_plat;
|
||||
struct udevice *scsi_dev;
|
||||
void __iomem *mmio_base;
|
||||
int err;
|
||||
|
||||
device_find_first_child(ufs_dev, &scsi_dev);
|
||||
|
@ -1927,7 +1928,14 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops)
|
|||
|
||||
hba->dev = ufs_dev;
|
||||
hba->ops = hba_ops;
|
||||
hba->mmio_base = dev_read_addr_ptr(ufs_dev);
|
||||
|
||||
if (device_is_on_pci_bus(ufs_dev)) {
|
||||
mmio_base = dm_pci_map_bar(ufs_dev, PCI_BASE_ADDRESS_0, 0, 0,
|
||||
PCI_REGION_TYPE, PCI_REGION_MEM);
|
||||
} else {
|
||||
mmio_base = dev_read_addr_ptr(ufs_dev);
|
||||
}
|
||||
hba->mmio_base = mmio_base;
|
||||
|
||||
/* Set descriptor lengths to specification defaults */
|
||||
ufshcd_def_desc_sizes(hba);
|
||||
|
@ -1945,7 +1953,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops)
|
|||
hba->version != UFSHCI_VERSION_11 &&
|
||||
hba->version != UFSHCI_VERSION_20 &&
|
||||
hba->version != UFSHCI_VERSION_21 &&
|
||||
hba->version != UFSHCI_VERSION_30)
|
||||
hba->version != UFSHCI_VERSION_30 &&
|
||||
hba->version != UFSHCI_VERSION_31)
|
||||
dev_err(hba->dev, "invalid UFS version 0x%x\n",
|
||||
hba->version);
|
||||
|
||||
|
|
|
@ -782,6 +782,7 @@ enum {
|
|||
UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */
|
||||
UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
|
||||
UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */
|
||||
UFSHCI_VERSION_31 = 0x00000310, /* 3.1 */
|
||||
};
|
||||
|
||||
/* Interrupt disable masks */
|
||||
|
|
|
@ -1363,6 +1363,13 @@
|
|||
#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
|
||||
#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
|
||||
|
||||
/* Per https://www.qemu.org/docs/master/specs/pci-ids.html */
|
||||
#define PCI_VENDOR_ID_REDHAT 0x1b36
|
||||
#define PCI_DEVICE_ID_REDHAT_SDHCI 0x0007
|
||||
#define PCI_DEVICE_ID_REDHAT_XHCI 0x000d
|
||||
#define PCI_DEVICE_ID_REDHAT_NVME 0x0010
|
||||
#define PCI_DEVICE_ID_REDHAT_UFS 0x0013
|
||||
|
||||
#define PCI_VENDOR_ID_INIT 0x1101
|
||||
|
||||
#define PCI_VENDOR_ID_CREATIVE 0x1102 /* duplicate: ECTIVA */
|
||||
|
|
Loading…
Add table
Reference in a new issue