xref: /linux/drivers/firmware/xilinx/zynqmp-ufs.c (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Firmware Layer for UFS APIs
4  *
5  * Copyright (C) 2025 Advanced Micro Devices, Inc.
6  */
7 
8 #include <linux/firmware/xlnx-zynqmp.h>
9 #include <linux/module.h>
10 
11 /* Register Node IDs */
12 #define PM_REGNODE_PMC_IOU_SLCR		0x30000002 /* PMC IOU SLCR */
13 #define PM_REGNODE_EFUSE_CACHE		0x30000003 /* EFUSE Cache */
14 
15 /* Register Offsets for PMC IOU SLCR */
16 #define SRAM_CSR_OFFSET			0x104C /* SRAM Control and Status */
17 #define TXRX_CFGRDY_OFFSET		0x1054 /* M-PHY TX-RX Config ready */
18 
19 /* Masks for SRAM Control and Status Register */
20 #define SRAM_CSR_INIT_DONE_MASK		BIT(0) /* SRAM initialization done */
21 #define SRAM_CSR_EXT_LD_DONE_MASK	BIT(1) /* SRAM External load done */
22 #define SRAM_CSR_BYPASS_MASK		BIT(2) /* Bypass SRAM interface */
23 
24 /* Mask to check M-PHY TX-RX configuration readiness */
25 #define TX_RX_CFG_RDY_MASK		GENMASK(3, 0)
26 
27 /* Register Offsets for EFUSE Cache */
28 #define UFS_CAL_1_OFFSET		0xBE8 /* UFS Calibration Value */
29 
30 /**
31  * zynqmp_pm_is_mphy_tx_rx_config_ready - check M-PHY TX-RX config readiness
32  * @is_ready:	Store output status (true/false)
33  *
34  * Return:	Returns 0 on success or error value on failure.
35  */
36 int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
37 {
38 	u32 regval;
39 	int ret;
40 
41 	if (!is_ready)
42 		return -EINVAL;
43 
44 	ret = zynqmp_pm_sec_read_reg(PM_REGNODE_PMC_IOU_SLCR, TXRX_CFGRDY_OFFSET, &regval);
45 	if (ret)
46 		return ret;
47 
48 	regval &= TX_RX_CFG_RDY_MASK;
49 	if (regval)
50 		*is_ready = true;
51 	else
52 		*is_ready = false;
53 
54 	return ret;
55 }
56 EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready);
57 
58 /**
59  * zynqmp_pm_is_sram_init_done - check SRAM initialization
60  * @is_done:	Store output status (true/false)
61  *
62  * Return:	Returns 0 on success or error value on failure.
63  */
64 int zynqmp_pm_is_sram_init_done(bool *is_done)
65 {
66 	u32 regval;
67 	int ret;
68 
69 	if (!is_done)
70 		return -EINVAL;
71 
72 	ret = zynqmp_pm_sec_read_reg(PM_REGNODE_PMC_IOU_SLCR, SRAM_CSR_OFFSET, &regval);
73 	if (ret)
74 		return ret;
75 
76 	regval &= SRAM_CSR_INIT_DONE_MASK;
77 	if (regval)
78 		*is_done = true;
79 	else
80 		*is_done = false;
81 
82 	return ret;
83 }
84 EXPORT_SYMBOL_GPL(zynqmp_pm_is_sram_init_done);
85 
86 /**
87  * zynqmp_pm_set_sram_bypass - Set SRAM bypass Control
88  *
89  * Return:	Returns 0 on success or error value on failure.
90  */
91 int zynqmp_pm_set_sram_bypass(void)
92 {
93 	u32 sram_csr;
94 	int ret;
95 
96 	ret = zynqmp_pm_sec_read_reg(PM_REGNODE_PMC_IOU_SLCR, SRAM_CSR_OFFSET, &sram_csr);
97 	if (ret)
98 		return ret;
99 
100 	sram_csr &= ~SRAM_CSR_EXT_LD_DONE_MASK;
101 	sram_csr |= SRAM_CSR_BYPASS_MASK;
102 
103 	return zynqmp_pm_sec_mask_write_reg(PM_REGNODE_PMC_IOU_SLCR, SRAM_CSR_OFFSET,
104 					    GENMASK(2, 1), sram_csr);
105 }
106 EXPORT_SYMBOL_GPL(zynqmp_pm_set_sram_bypass);
107 
108 /**
109  * zynqmp_pm_get_ufs_calibration_values - Read UFS calibration values
110  * @val:	Store the calibration value
111  *
112  * Return:	Returns 0 on success or error value on failure.
113  */
114 int zynqmp_pm_get_ufs_calibration_values(u32 *val)
115 {
116 	return zynqmp_pm_sec_read_reg(PM_REGNODE_EFUSE_CACHE, UFS_CAL_1_OFFSET, val);
117 }
118 EXPORT_SYMBOL_GPL(zynqmp_pm_get_ufs_calibration_values);
119