Skip to content

Commit 2b9887b

Browse files
Nitin Rawatmartinkpetersen
authored andcommitted
scsi: ufs: ufs-qcom: Streamline UFS MCQ resource mapping
The current MCQ resource configuration involves multiple resource mappings and dynamic resource allocation. Simplify the resource mapping by directly mapping the single "mcq" resource from device tree to hba->mcq_base instead of mapping multiple separate resources (RES_UFS, RES_MCQ, RES_MCQ_SQD, RES_MCQ_VS). It also uses predefined offsets for MCQ doorbell registers (SQD, CQD, SQIS, CQIS) relative to the MCQ base,providing clearer memory layout clarity. Additionally update vendor-specific register offset UFS_MEM_CQIS_VS offset from 0x8 to 0x4008 to align with the hardware programming guide. The new approach assumes the device tree provides a single "mcq" resource that encompasses the entire MCQ configuration space, making the driver more maintainable and less prone to resource mapping errors. The change aligns the driver implementation with the device tree binding specification, which defines a single 'mcq' memory region rather than multiple separate regions. Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com> Reviewed-by: Manivannan Sadhasivam <mani@kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 8f5ae30 commit 2b9887b

2 files changed

Lines changed: 66 additions & 100 deletions

File tree

drivers/ufs/host/ufs-qcom.c

Lines changed: 44 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,116 +1910,68 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
19101910
hba->clk_scaling.suspend_on_no_request = true;
19111911
}
19121912

1913-
/* Resources */
1914-
static const struct ufshcd_res_info ufs_res_info[RES_MAX] = {
1915-
{.name = "ufs_mem",},
1916-
{.name = "mcq",},
1917-
/* Submission Queue DAO */
1918-
{.name = "mcq_sqd",},
1919-
/* Submission Queue Interrupt Status */
1920-
{.name = "mcq_sqis",},
1921-
/* Completion Queue DAO */
1922-
{.name = "mcq_cqd",},
1923-
/* Completion Queue Interrupt Status */
1924-
{.name = "mcq_cqis",},
1925-
/* MCQ vendor specific */
1926-
{.name = "mcq_vs",},
1927-
};
1928-
19291913
static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba)
19301914
{
19311915
struct platform_device *pdev = to_platform_device(hba->dev);
1932-
struct ufshcd_res_info *res;
1933-
struct resource *res_mem, *res_mcq;
1934-
int i, ret;
1935-
1936-
memcpy(hba->res, ufs_res_info, sizeof(ufs_res_info));
1937-
1938-
for (i = 0; i < RES_MAX; i++) {
1939-
res = &hba->res[i];
1940-
res->resource = platform_get_resource_byname(pdev,
1941-
IORESOURCE_MEM,
1942-
res->name);
1943-
if (!res->resource) {
1944-
dev_info(hba->dev, "Resource %s not provided\n", res->name);
1945-
if (i == RES_UFS)
1946-
return -ENODEV;
1947-
continue;
1948-
} else if (i == RES_UFS) {
1949-
res_mem = res->resource;
1950-
res->base = hba->mmio_base;
1951-
continue;
1952-
}
1953-
1954-
res->base = devm_ioremap_resource(hba->dev, res->resource);
1955-
if (IS_ERR(res->base)) {
1956-
dev_err(hba->dev, "Failed to map res %s, err=%d\n",
1957-
res->name, (int)PTR_ERR(res->base));
1958-
ret = PTR_ERR(res->base);
1959-
res->base = NULL;
1960-
return ret;
1961-
}
1962-
}
1916+
struct resource *res;
19631917

1964-
/* MCQ resource provided in DT */
1965-
res = &hba->res[RES_MCQ];
1966-
/* Bail if MCQ resource is provided */
1967-
if (res->base)
1968-
goto out;
1969-
1970-
/* Explicitly allocate MCQ resource from ufs_mem */
1971-
res_mcq = devm_kzalloc(hba->dev, sizeof(*res_mcq), GFP_KERNEL);
1972-
if (!res_mcq)
1973-
return -ENOMEM;
1974-
1975-
res_mcq->start = res_mem->start +
1976-
MCQ_SQATTR_OFFSET(hba->mcq_capabilities);
1977-
res_mcq->end = res_mcq->start + hba->nr_hw_queues * MCQ_QCFG_SIZE - 1;
1978-
res_mcq->flags = res_mem->flags;
1979-
res_mcq->name = "mcq";
1980-
1981-
ret = insert_resource(&iomem_resource, res_mcq);
1982-
if (ret) {
1983-
dev_err(hba->dev, "Failed to insert MCQ resource, err=%d\n",
1984-
ret);
1985-
return ret;
1918+
/* Map the MCQ configuration region */
1919+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mcq");
1920+
if (!res) {
1921+
dev_err(hba->dev, "MCQ resource not found in device tree\n");
1922+
return -ENODEV;
19861923
}
19871924

1988-
res->base = devm_ioremap_resource(hba->dev, res_mcq);
1989-
if (IS_ERR(res->base)) {
1990-
dev_err(hba->dev, "MCQ registers mapping failed, err=%d\n",
1991-
(int)PTR_ERR(res->base));
1992-
ret = PTR_ERR(res->base);
1993-
goto ioremap_err;
1925+
hba->mcq_base = devm_ioremap_resource(hba->dev, res);
1926+
if (IS_ERR(hba->mcq_base)) {
1927+
dev_err(hba->dev, "Failed to map MCQ region: %ld\n",
1928+
PTR_ERR(hba->mcq_base));
1929+
return PTR_ERR(hba->mcq_base);
19941930
}
19951931

1996-
out:
1997-
hba->mcq_base = res->base;
19981932
return 0;
1999-
ioremap_err:
2000-
res->base = NULL;
2001-
remove_resource(res_mcq);
2002-
return ret;
20031933
}
20041934

20051935
static int ufs_qcom_op_runtime_config(struct ufs_hba *hba)
20061936
{
2007-
struct ufshcd_res_info *mem_res, *sqdao_res;
20081937
struct ufshcd_mcq_opr_info_t *opr;
20091938
int i;
1939+
u32 doorbell_offsets[OPR_MAX];
20101940

2011-
mem_res = &hba->res[RES_UFS];
2012-
sqdao_res = &hba->res[RES_MCQ_SQD];
1941+
/*
1942+
* Configure doorbell address offsets in MCQ configuration registers.
1943+
* These values are offsets relative to mmio_base (UFS_HCI_BASE).
1944+
*
1945+
* Memory Layout:
1946+
* - mmio_base = UFS_HCI_BASE
1947+
* - mcq_base = MCQ_CONFIG_BASE = mmio_base + (UFS_QCOM_MCQCAP_QCFGPTR * 0x200)
1948+
* - Doorbell registers are at: mmio_base + (UFS_QCOM_MCQCAP_QCFGPTR * 0x200) +
1949+
* - UFS_QCOM_MCQ_SQD_OFFSET
1950+
* - Which is also: mcq_base + UFS_QCOM_MCQ_SQD_OFFSET
1951+
*/
20131952

2014-
if (!mem_res->base || !sqdao_res->base)
2015-
return -EINVAL;
1953+
doorbell_offsets[OPR_SQD] = UFS_QCOM_SQD_ADDR_OFFSET;
1954+
doorbell_offsets[OPR_SQIS] = UFS_QCOM_SQIS_ADDR_OFFSET;
1955+
doorbell_offsets[OPR_CQD] = UFS_QCOM_CQD_ADDR_OFFSET;
1956+
doorbell_offsets[OPR_CQIS] = UFS_QCOM_CQIS_ADDR_OFFSET;
20161957

1958+
/*
1959+
* Configure MCQ operation registers.
1960+
*
1961+
* The doorbell registers are physically located within the MCQ region:
1962+
* - doorbell_physical_addr = mmio_base + doorbell_offset
1963+
* - doorbell_physical_addr = mcq_base + (doorbell_offset - MCQ_CONFIG_OFFSET)
1964+
*/
20171965
for (i = 0; i < OPR_MAX; i++) {
20181966
opr = &hba->mcq_opr[i];
2019-
opr->offset = sqdao_res->resource->start -
2020-
mem_res->resource->start + 0x40 * i;
2021-
opr->stride = 0x100;
2022-
opr->base = sqdao_res->base + 0x40 * i;
1967+
opr->offset = doorbell_offsets[i]; /* Offset relative to mmio_base */
1968+
opr->stride = UFS_QCOM_MCQ_STRIDE; /* 256 bytes between queues */
1969+
1970+
/*
1971+
* Calculate the actual doorbell base address within MCQ region:
1972+
* base = mcq_base + (doorbell_offset - MCQ_CONFIG_OFFSET)
1973+
*/
1974+
opr->base = hba->mcq_base + (opr->offset - UFS_QCOM_MCQ_CONFIG_OFFSET);
20231975
}
20241976

20251977
return 0;
@@ -2034,12 +1986,8 @@ static int ufs_qcom_get_hba_mac(struct ufs_hba *hba)
20341986
static int ufs_qcom_get_outstanding_cqs(struct ufs_hba *hba,
20351987
unsigned long *ocqs)
20361988
{
2037-
struct ufshcd_res_info *mcq_vs_res = &hba->res[RES_MCQ_VS];
2038-
2039-
if (!mcq_vs_res->base)
2040-
return -EINVAL;
2041-
2042-
*ocqs = readl(mcq_vs_res->base + UFS_MEM_CQIS_VS);
1989+
/* Read from MCQ vendor-specific register in MCQ region */
1990+
*ocqs = readl(hba->mcq_base + UFS_MEM_CQIS_VS);
20431991

20441992
return 0;
20451993
}

drivers/ufs/host/ufs-qcom.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,28 @@
3333
#define DL_VS_CLK_CFG_MASK GENMASK(9, 0)
3434
#define DME_VS_CORE_CLK_CTRL_DME_HW_CGC_EN BIT(9)
3535

36+
/* Qualcomm MCQ Configuration */
37+
#define UFS_QCOM_MCQCAP_QCFGPTR 224 /* 0xE0 in hex */
38+
#define UFS_QCOM_MCQ_CONFIG_OFFSET (UFS_QCOM_MCQCAP_QCFGPTR * 0x200) /* 0x1C000 */
39+
40+
/* Doorbell offsets within MCQ region (relative to MCQ_CONFIG_BASE) */
41+
#define UFS_QCOM_MCQ_SQD_OFFSET 0x5000
42+
#define UFS_QCOM_MCQ_CQD_OFFSET 0x5080
43+
#define UFS_QCOM_MCQ_SQIS_OFFSET 0x5040
44+
#define UFS_QCOM_MCQ_CQIS_OFFSET 0x50C0
45+
#define UFS_QCOM_MCQ_STRIDE 0x100
46+
47+
/* Calculated doorbell address offsets (relative to mmio_base) */
48+
#define UFS_QCOM_SQD_ADDR_OFFSET (UFS_QCOM_MCQ_CONFIG_OFFSET + UFS_QCOM_MCQ_SQD_OFFSET)
49+
#define UFS_QCOM_CQD_ADDR_OFFSET (UFS_QCOM_MCQ_CONFIG_OFFSET + UFS_QCOM_MCQ_CQD_OFFSET)
50+
#define UFS_QCOM_SQIS_ADDR_OFFSET (UFS_QCOM_MCQ_CONFIG_OFFSET + UFS_QCOM_MCQ_SQIS_OFFSET)
51+
#define UFS_QCOM_CQIS_ADDR_OFFSET (UFS_QCOM_MCQ_CONFIG_OFFSET + UFS_QCOM_MCQ_CQIS_OFFSET)
52+
#define REG_UFS_MCQ_STRIDE UFS_QCOM_MCQ_STRIDE
53+
54+
/* MCQ Vendor specific address offsets (relative to MCQ_CONFIG_BASE) */
55+
#define UFS_MEM_VS_BASE 0x4000
56+
#define UFS_MEM_CQIS_VS 0x4008
57+
3658
/* QCOM UFS host controller vendor specific registers */
3759
enum {
3860
REG_UFS_SYS1CLK_1US = 0xC0,
@@ -95,10 +117,6 @@ enum {
95117
REG_UFS_SW_H8_EXIT_CNT = 0x2710,
96118
};
97119

98-
enum {
99-
UFS_MEM_CQIS_VS = 0x8,
100-
};
101-
102120
#define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x)
103121
#define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x)
104122

0 commit comments

Comments
 (0)