Skip to content

Commit d76afd8

Browse files
Merge patch series "Simplify MCQ resource mapping"
Nitin Rawat <nitin.rawat@oss.qualcomm.com> says: The patch series simplifies the UFS MCQ (Multi Circular Queue) resource mapping in the Qualcomm UFS host controller driver by replacing the complex multi-resource approach with a streamlined single-resource implementation. The current MCQ implementation uses multiple separate resource mappings (RES_UFS, RES_MCQ, RES_MCQ_SQD, RES_MCQ_VS) with dynamic resource allocation, which increases code complexity and potential for resource mapping errors. This approach also doesn't align with the device tree binding specification that defines a single 'mcq' memory region. Replace the multi-resource mapping with a single "mcq" resource that encompasses the entire MCQ configuration space. The doorbell registers (SQD, CQD, SQIS, CQIS) are accessed using predefined offsets relative to the MCQ base address, providing clearer memory layout organization. Tested on Qualcomm platforms SM8650 and SM8750 with UFS MCQ enabled. Changes from v3: 1. Addressed Krzysztof comment to separate device tree and driver patch independently in different patch series. This series caters driver changes. 2. Addressed Manivannan's change to update commit text and remove redundant null check in mcq code. 3. Addressed Manivannan's to Update few offsets as fixed definition instead of enum. Changes from v2: 1. Removed dt-bindings patch as existing binding supports required reg-names format. 2. Added patch to refactor MCQ register dump logic for new resource mapping. 3. Added patch to remove unused ufshcd_res_info structure from UFS core. 4. Changed reg-names from "ufs_mem" to "std" in device tree patches. 5. Reordered patches with driver changes first, then device tree changes. 6. Updated SM8750 MCQ region size from 0x2000 to 0x15000 Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2 parents 7dc0d13 + bc5dbf7 commit d76afd8

3 files changed

Lines changed: 85 additions & 140 deletions

File tree

drivers/ufs/host/ufs-qcom.c

Lines changed: 63 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,7 +1763,7 @@ static void ufs_qcom_dump_testbus(struct ufs_hba *hba)
17631763
}
17641764

17651765
static int ufs_qcom_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
1766-
const char *prefix, enum ufshcd_res id)
1766+
const char *prefix, void __iomem *base)
17671767
{
17681768
u32 *regs __free(kfree) = NULL;
17691769
size_t pos;
@@ -1776,7 +1776,7 @@ static int ufs_qcom_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
17761776
return -ENOMEM;
17771777

17781778
for (pos = 0; pos < len; pos += 4)
1779-
regs[pos / 4] = readl(hba->res[id].base + offset + pos);
1779+
regs[pos / 4] = readl(base + offset + pos);
17801780

17811781
print_hex_dump(KERN_ERR, prefix,
17821782
len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
@@ -1787,30 +1787,34 @@ static int ufs_qcom_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
17871787

17881788
static void ufs_qcom_dump_mcq_hci_regs(struct ufs_hba *hba)
17891789
{
1790+
struct ufshcd_mcq_opr_info_t *opr = &hba->mcq_opr[0];
1791+
void __iomem *mcq_vs_base = hba->mcq_base + UFS_MEM_VS_BASE;
1792+
17901793
struct dump_info {
1794+
void __iomem *base;
17911795
size_t offset;
17921796
size_t len;
17931797
const char *prefix;
1794-
enum ufshcd_res id;
17951798
};
17961799

17971800
struct dump_info mcq_dumps[] = {
1798-
{0x0, 256 * 4, "MCQ HCI-0 ", RES_MCQ},
1799-
{0x400, 256 * 4, "MCQ HCI-1 ", RES_MCQ},
1800-
{0x0, 5 * 4, "MCQ VS-0 ", RES_MCQ_VS},
1801-
{0x0, 256 * 4, "MCQ SQD-0 ", RES_MCQ_SQD},
1802-
{0x400, 256 * 4, "MCQ SQD-1 ", RES_MCQ_SQD},
1803-
{0x800, 256 * 4, "MCQ SQD-2 ", RES_MCQ_SQD},
1804-
{0xc00, 256 * 4, "MCQ SQD-3 ", RES_MCQ_SQD},
1805-
{0x1000, 256 * 4, "MCQ SQD-4 ", RES_MCQ_SQD},
1806-
{0x1400, 256 * 4, "MCQ SQD-5 ", RES_MCQ_SQD},
1807-
{0x1800, 256 * 4, "MCQ SQD-6 ", RES_MCQ_SQD},
1808-
{0x1c00, 256 * 4, "MCQ SQD-7 ", RES_MCQ_SQD},
1801+
{hba->mcq_base, 0x0, 256 * 4, "MCQ HCI-0 "},
1802+
{hba->mcq_base, 0x400, 256 * 4, "MCQ HCI-1 "},
1803+
{mcq_vs_base, 0x0, 5 * 4, "MCQ VS-0 "},
1804+
{opr->base, 0x0, 256 * 4, "MCQ SQD-0 "},
1805+
{opr->base, 0x400, 256 * 4, "MCQ SQD-1 "},
1806+
{opr->base, 0x800, 256 * 4, "MCQ SQD-2 "},
1807+
{opr->base, 0xc00, 256 * 4, "MCQ SQD-3 "},
1808+
{opr->base, 0x1000, 256 * 4, "MCQ SQD-4 "},
1809+
{opr->base, 0x1400, 256 * 4, "MCQ SQD-5 "},
1810+
{opr->base, 0x1800, 256 * 4, "MCQ SQD-6 "},
1811+
{opr->base, 0x1c00, 256 * 4, "MCQ SQD-7 "},
1812+
18091813
};
18101814

18111815
for (int i = 0; i < ARRAY_SIZE(mcq_dumps); i++) {
18121816
ufs_qcom_dump_regs(hba, mcq_dumps[i].offset, mcq_dumps[i].len,
1813-
mcq_dumps[i].prefix, mcq_dumps[i].id);
1817+
mcq_dumps[i].prefix, mcq_dumps[i].base);
18141818
cond_resched();
18151819
}
18161820
}
@@ -1931,116 +1935,68 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
19311935
hba->clk_scaling.suspend_on_no_request = true;
19321936
}
19331937

1934-
/* Resources */
1935-
static const struct ufshcd_res_info ufs_res_info[RES_MAX] = {
1936-
{.name = "ufs_mem",},
1937-
{.name = "mcq",},
1938-
/* Submission Queue DAO */
1939-
{.name = "mcq_sqd",},
1940-
/* Submission Queue Interrupt Status */
1941-
{.name = "mcq_sqis",},
1942-
/* Completion Queue DAO */
1943-
{.name = "mcq_cqd",},
1944-
/* Completion Queue Interrupt Status */
1945-
{.name = "mcq_cqis",},
1946-
/* MCQ vendor specific */
1947-
{.name = "mcq_vs",},
1948-
};
1949-
19501938
static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba)
19511939
{
19521940
struct platform_device *pdev = to_platform_device(hba->dev);
1953-
struct ufshcd_res_info *res;
1954-
struct resource *res_mem, *res_mcq;
1955-
int i, ret;
1956-
1957-
memcpy(hba->res, ufs_res_info, sizeof(ufs_res_info));
1958-
1959-
for (i = 0; i < RES_MAX; i++) {
1960-
res = &hba->res[i];
1961-
res->resource = platform_get_resource_byname(pdev,
1962-
IORESOURCE_MEM,
1963-
res->name);
1964-
if (!res->resource) {
1965-
dev_info(hba->dev, "Resource %s not provided\n", res->name);
1966-
if (i == RES_UFS)
1967-
return -ENODEV;
1968-
continue;
1969-
} else if (i == RES_UFS) {
1970-
res_mem = res->resource;
1971-
res->base = hba->mmio_base;
1972-
continue;
1973-
}
1941+
struct resource *res;
19741942

1975-
res->base = devm_ioremap_resource(hba->dev, res->resource);
1976-
if (IS_ERR(res->base)) {
1977-
dev_err(hba->dev, "Failed to map res %s, err=%d\n",
1978-
res->name, (int)PTR_ERR(res->base));
1979-
ret = PTR_ERR(res->base);
1980-
res->base = NULL;
1981-
return ret;
1982-
}
1943+
/* Map the MCQ configuration region */
1944+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mcq");
1945+
if (!res) {
1946+
dev_err(hba->dev, "MCQ resource not found in device tree\n");
1947+
return -ENODEV;
19831948
}
19841949

1985-
/* MCQ resource provided in DT */
1986-
res = &hba->res[RES_MCQ];
1987-
/* Bail if MCQ resource is provided */
1988-
if (res->base)
1989-
goto out;
1990-
1991-
/* Explicitly allocate MCQ resource from ufs_mem */
1992-
res_mcq = devm_kzalloc(hba->dev, sizeof(*res_mcq), GFP_KERNEL);
1993-
if (!res_mcq)
1994-
return -ENOMEM;
1995-
1996-
res_mcq->start = res_mem->start +
1997-
MCQ_SQATTR_OFFSET(hba->mcq_capabilities);
1998-
res_mcq->end = res_mcq->start + hba->nr_hw_queues * MCQ_QCFG_SIZE - 1;
1999-
res_mcq->flags = res_mem->flags;
2000-
res_mcq->name = "mcq";
2001-
2002-
ret = insert_resource(&iomem_resource, res_mcq);
2003-
if (ret) {
2004-
dev_err(hba->dev, "Failed to insert MCQ resource, err=%d\n",
2005-
ret);
2006-
return ret;
1950+
hba->mcq_base = devm_ioremap_resource(hba->dev, res);
1951+
if (IS_ERR(hba->mcq_base)) {
1952+
dev_err(hba->dev, "Failed to map MCQ region: %ld\n",
1953+
PTR_ERR(hba->mcq_base));
1954+
return PTR_ERR(hba->mcq_base);
20071955
}
20081956

2009-
res->base = devm_ioremap_resource(hba->dev, res_mcq);
2010-
if (IS_ERR(res->base)) {
2011-
dev_err(hba->dev, "MCQ registers mapping failed, err=%d\n",
2012-
(int)PTR_ERR(res->base));
2013-
ret = PTR_ERR(res->base);
2014-
goto ioremap_err;
2015-
}
2016-
2017-
out:
2018-
hba->mcq_base = res->base;
20191957
return 0;
2020-
ioremap_err:
2021-
res->base = NULL;
2022-
remove_resource(res_mcq);
2023-
return ret;
20241958
}
20251959

20261960
static int ufs_qcom_op_runtime_config(struct ufs_hba *hba)
20271961
{
2028-
struct ufshcd_res_info *mem_res, *sqdao_res;
20291962
struct ufshcd_mcq_opr_info_t *opr;
20301963
int i;
1964+
u32 doorbell_offsets[OPR_MAX];
20311965

2032-
mem_res = &hba->res[RES_UFS];
2033-
sqdao_res = &hba->res[RES_MCQ_SQD];
1966+
/*
1967+
* Configure doorbell address offsets in MCQ configuration registers.
1968+
* These values are offsets relative to mmio_base (UFS_HCI_BASE).
1969+
*
1970+
* Memory Layout:
1971+
* - mmio_base = UFS_HCI_BASE
1972+
* - mcq_base = MCQ_CONFIG_BASE = mmio_base + (UFS_QCOM_MCQCAP_QCFGPTR * 0x200)
1973+
* - Doorbell registers are at: mmio_base + (UFS_QCOM_MCQCAP_QCFGPTR * 0x200) +
1974+
* - UFS_QCOM_MCQ_SQD_OFFSET
1975+
* - Which is also: mcq_base + UFS_QCOM_MCQ_SQD_OFFSET
1976+
*/
20341977

2035-
if (!mem_res->base || !sqdao_res->base)
2036-
return -EINVAL;
1978+
doorbell_offsets[OPR_SQD] = UFS_QCOM_SQD_ADDR_OFFSET;
1979+
doorbell_offsets[OPR_SQIS] = UFS_QCOM_SQIS_ADDR_OFFSET;
1980+
doorbell_offsets[OPR_CQD] = UFS_QCOM_CQD_ADDR_OFFSET;
1981+
doorbell_offsets[OPR_CQIS] = UFS_QCOM_CQIS_ADDR_OFFSET;
20371982

1983+
/*
1984+
* Configure MCQ operation registers.
1985+
*
1986+
* The doorbell registers are physically located within the MCQ region:
1987+
* - doorbell_physical_addr = mmio_base + doorbell_offset
1988+
* - doorbell_physical_addr = mcq_base + (doorbell_offset - MCQ_CONFIG_OFFSET)
1989+
*/
20381990
for (i = 0; i < OPR_MAX; i++) {
20391991
opr = &hba->mcq_opr[i];
2040-
opr->offset = sqdao_res->resource->start -
2041-
mem_res->resource->start + 0x40 * i;
2042-
opr->stride = 0x100;
2043-
opr->base = sqdao_res->base + 0x40 * i;
1992+
opr->offset = doorbell_offsets[i]; /* Offset relative to mmio_base */
1993+
opr->stride = UFS_QCOM_MCQ_STRIDE; /* 256 bytes between queues */
1994+
1995+
/*
1996+
* Calculate the actual doorbell base address within MCQ region:
1997+
* base = mcq_base + (doorbell_offset - MCQ_CONFIG_OFFSET)
1998+
*/
1999+
opr->base = hba->mcq_base + (opr->offset - UFS_QCOM_MCQ_CONFIG_OFFSET);
20442000
}
20452001

20462002
return 0;
@@ -2055,12 +2011,8 @@ static int ufs_qcom_get_hba_mac(struct ufs_hba *hba)
20552011
static int ufs_qcom_get_outstanding_cqs(struct ufs_hba *hba,
20562012
unsigned long *ocqs)
20572013
{
2058-
struct ufshcd_res_info *mcq_vs_res = &hba->res[RES_MCQ_VS];
2059-
2060-
if (!mcq_vs_res->base)
2061-
return -EINVAL;
2062-
2063-
*ocqs = readl(mcq_vs_res->base + UFS_MEM_CQIS_VS);
2014+
/* Read from MCQ vendor-specific register in MCQ region */
2015+
*ocqs = readl(hba->mcq_base + UFS_MEM_CQIS_VS);
20642016

20652017
return 0;
20662018
}

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

include/ufs/ufshcd.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -793,30 +793,6 @@ struct ufs_hba_monitor {
793793
bool enabled;
794794
};
795795

796-
/**
797-
* struct ufshcd_res_info_t - MCQ related resource regions
798-
*
799-
* @name: resource name
800-
* @resource: pointer to resource region
801-
* @base: register base address
802-
*/
803-
struct ufshcd_res_info {
804-
const char *name;
805-
struct resource *resource;
806-
void __iomem *base;
807-
};
808-
809-
enum ufshcd_res {
810-
RES_UFS,
811-
RES_MCQ,
812-
RES_MCQ_SQD,
813-
RES_MCQ_SQIS,
814-
RES_MCQ_CQD,
815-
RES_MCQ_CQIS,
816-
RES_MCQ_VS,
817-
RES_MAX,
818-
};
819-
820796
/**
821797
* struct ufshcd_mcq_opr_info_t - Operation and Runtime registers
822798
*
@@ -1126,7 +1102,6 @@ struct ufs_hba {
11261102
bool lsdb_sup;
11271103
bool mcq_enabled;
11281104
bool mcq_esi_enabled;
1129-
struct ufshcd_res_info res[RES_MAX];
11301105
void __iomem *mcq_base;
11311106
struct ufs_hw_queue *uhq;
11321107
struct ufs_hw_queue *dev_cmd_queue;

0 commit comments

Comments
 (0)