Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Nitin Rawat and committed by
Martin K. Petersen
2b9887b1 8f5ae30d

+66 -100
+44 -96
drivers/ufs/host/ufs-qcom.c
··· 1910 1910 hba->clk_scaling.suspend_on_no_request = true; 1911 1911 } 1912 1912 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 - 1929 1913 static int ufs_qcom_mcq_config_resource(struct ufs_hba *hba) 1930 1914 { 1931 1915 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; 1916 + struct resource *res; 1935 1917 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 - } 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; 1962 1923 } 1963 1924 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; 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); 1986 1930 } 1987 1931 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; 1994 - } 1995 - 1996 - out: 1997 - hba->mcq_base = res->base; 1998 1932 return 0; 1999 - ioremap_err: 2000 - res->base = NULL; 2001 - remove_resource(res_mcq); 2002 - return ret; 2003 1933 } 2004 1934 2005 1935 static int ufs_qcom_op_runtime_config(struct ufs_hba *hba) 2006 1936 { 2007 - struct ufshcd_res_info *mem_res, *sqdao_res; 2008 1937 struct ufshcd_mcq_opr_info_t *opr; 2009 1938 int i; 1939 + u32 doorbell_offsets[OPR_MAX]; 2010 1940 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 + */ 2013 1952 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; 2016 1957 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 + */ 2017 1965 for (i = 0; i < OPR_MAX; i++) { 2018 1966 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); 2023 1975 } 2024 1976 2025 1977 return 0; ··· 1986 2034 static int ufs_qcom_get_outstanding_cqs(struct ufs_hba *hba, 1987 2035 unsigned long *ocqs) 1988 2036 { 1989 - struct ufshcd_res_info *mcq_vs_res = &hba->res[RES_MCQ_VS]; 1990 - 1991 - if (!mcq_vs_res->base) 1992 - return -EINVAL; 1993 - 1994 - *ocqs = readl(mcq_vs_res->base + UFS_MEM_CQIS_VS); 2037 + /* Read from MCQ vendor-specific register in MCQ region */ 2038 + *ocqs = readl(hba->mcq_base + UFS_MEM_CQIS_VS); 1995 2039 1996 2040 return 0; 1997 2041 }
+22 -4
drivers/ufs/host/ufs-qcom.h
··· 33 33 #define DL_VS_CLK_CFG_MASK GENMASK(9, 0) 34 34 #define DME_VS_CORE_CLK_CTRL_DME_HW_CGC_EN BIT(9) 35 35 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 + 36 58 /* QCOM UFS host controller vendor specific registers */ 37 59 enum { 38 60 REG_UFS_SYS1CLK_1US = 0xC0, ··· 115 93 REG_UFS_SW_AFTER_HW_H8_ENTER_CNT = 0x2708, 116 94 REG_UFS_HW_H8_EXIT_CNT = 0x270C, 117 95 REG_UFS_SW_H8_EXIT_CNT = 0x2710, 118 - }; 119 - 120 - enum { 121 - UFS_MEM_CQIS_VS = 0x8, 122 96 }; 123 97 124 98 #define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x)