xref: /rk3399_rockchip-uboot/drivers/ufs/ufs-rockchip.c (revision 3fbe7fd65f25e2e87fe1d6d867eeaec4d04c6753)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Rockchip UFS Host Controller driver
4  *
5  * Copyright (C) 2024 Rockchip Electronics Co.Ltd.
6  */
7 
8 #include <asm/io.h>
9 #include <clk.h>
10 #include <common.h>
11 #include <dm.h>
12 #include <linux/err.h>
13 #include <linux/ioport.h>
14 #include <reset.h>
15 #include <ufs.h>
16 
17 #include "ufs.h"
18 #include "unipro.h"
19 #include "ufs-rockchip.h"
20 
21 extern int ufshcd_dme_enable(struct ufs_hba *hba);
22 
23 static inline bool ufshcd_is_hba_active(struct ufs_hba *hba)
24 {
25 	return ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & CONTROLLER_ENABLE;
26 }
27 
28 #if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_ROCKCHIP_UFS_DISABLED_LINKUP_TEST)
29 static int ufs_rockchip_test_linkup(struct ufs_hba *hba)
30 {
31 	unsigned long start = 0;
32 	u32 intr_status;
33 	u32 enabled_intr_status;
34 
35 	/* Write Args */
36 	ufshcd_writel(hba, 0, REG_UIC_COMMAND_ARG_1);
37 	ufshcd_writel(hba, 0, REG_UIC_COMMAND_ARG_2);
38 	ufshcd_writel(hba, 0, REG_UIC_COMMAND_ARG_3);
39 	/* Write UIC Cmd */
40 	ufshcd_writel(hba, UIC_CMD_DME_LINK_STARTUP & COMMAND_OPCODE_MASK, REG_UIC_COMMAND);
41 
42 	start = get_timer(0);
43 	do {
44 		intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
45 		enabled_intr_status = intr_status & hba->intr_mask;
46 		ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
47 
48 		if (get_timer(start) > 50) {
49 			dev_err(hba->dev,
50 				"Timedout waiting for UIC response\n");
51 			return -ETIMEDOUT;
52 		}
53 
54 		if (enabled_intr_status & UFSHCD_ERROR_MASK) {
55 			dev_err(hba->dev, "Error in status:%08x\n",
56 				enabled_intr_status);
57 
58 			return -1;
59 		}
60 	} while (!(enabled_intr_status & UFSHCD_UIC_MASK));
61 
62 	return 0;
63 }
64 #endif
65 
66 static int ufs_rockchip_hce_enable_notify(struct ufs_hba *hba,
67 					  enum ufs_notify_change_status status)
68 {
69 	int err = 0;
70 
71 	if (status == POST_CHANGE) {
72 		ufshcd_dme_reset(hba);
73 		ufshcd_dme_enable(hba);
74 
75 #if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_ROCKCHIP_UFS_DISABLED_LINKUP_TEST)
76 		/* Try linkup to test if mphy has power supply */
77 		if (ufs_rockchip_test_linkup(hba)) {
78 			return -EIO;
79 		} else {
80 			ufshcd_dme_reset(hba);
81 			ufshcd_dme_enable(hba);
82 		}
83 #endif
84 		if (hba->ops->phy_initialization) {
85                        err = hba->ops->phy_initialization(hba);
86                        if (err) {
87                                dev_err(hba->dev, "Phy setup failed (%d)\n", err);
88                        }
89                }
90 	}
91 
92 	return err;
93 }
94 
95 static const unsigned char rk3576_phy_value[15][4] = {
96 	{0x03, 0x38, 0x50, 0x80},
97 	{0x03, 0x14, 0x58, 0x80},
98 	{0x03, 0x26, 0x58, 0x80},
99 	{0x03, 0x49, 0x58, 0x80},
100 	{0x03, 0x5A, 0x58, 0x80},
101 	{0xC3, 0x38, 0x50, 0xC0},
102 	{0xC3, 0x14, 0x58, 0xC0},
103 	{0xC3, 0x26, 0x58, 0xC0},
104 	{0xC3, 0x49, 0x58, 0xC0},
105 	{0xC3, 0x5A, 0x58, 0xC0},
106 	{0x43, 0x38, 0x50, 0xC0},
107 	{0x43, 0x14, 0x58, 0xC0},
108 	{0x43, 0x26, 0x58, 0xC0},
109 	{0x43, 0x49, 0x58, 0xC0},
110 	{0x43, 0x5A, 0x58, 0xC0}
111 };
112 
113 static int ufs_rockchip_rk3576_phy_init(struct ufs_hba *hba)
114 {
115 	struct ufs_rockchip_host *host = dev_get_priv(hba->dev);
116 	int try_case = host->phy_config_mode, value;
117 
118 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(PA_LOCAL_TX_LCC_ENABLE, 0x0), 0x0);
119 	/* enable the mphy DME_SET cfg */
120 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x40);
121 	for (int i = 0; i < 2; i++) {
122 		/* Configuration M-TX */
123 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xaa, SEL_TX_LANE0 + i), 0x06);
124 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xa9, SEL_TX_LANE0 + i), 0x02);
125 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xad, SEL_TX_LANE0 + i), 0x44);
126 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xac, SEL_TX_LANE0 + i), 0xe6);
127 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xab, SEL_TX_LANE0 + i), 0x07);
128 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x94, SEL_TX_LANE0 + i), 0x93);
129 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x93, SEL_TX_LANE0 + i), 0xc9);
130 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x7f, SEL_TX_LANE0 + i), 0x00);
131 		/* Configuration M-RX */
132 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x12, SEL_RX_LANE0 + i), 0x06);
133 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x11, SEL_RX_LANE0 + i), 0x00);
134 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1d, SEL_RX_LANE0 + i), 0x58);
135 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1c, SEL_RX_LANE0 + i), 0x8c);
136 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1b, SEL_RX_LANE0 + i), 0x02);
137 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x25, SEL_RX_LANE0 + i), 0xf6);
138 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x2f, SEL_RX_LANE0 + i), 0x69);
139 	}
140 	/* disable the mphy DME_SET cfg */
141 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x00);
142 
143 	ufs_sys_writel(host->mphy_base, 0x80, 0x08C);
144 	ufs_sys_writel(host->mphy_base, 0xB5, 0x110);
145 	ufs_sys_writel(host->mphy_base, 0xB5, 0x250);
146 
147 	value = rk3576_phy_value[try_case][0];
148 	ufs_sys_writel(host->mphy_base, value, 0x134);
149 	ufs_sys_writel(host->mphy_base, value, 0x274);
150 
151 	value = rk3576_phy_value[try_case][1];
152 	ufs_sys_writel(host->mphy_base, value, 0x0E0);
153 	ufs_sys_writel(host->mphy_base, value, 0x220);
154 
155 	value = rk3576_phy_value[try_case][2];
156 	ufs_sys_writel(host->mphy_base, value, 0x164);
157 	ufs_sys_writel(host->mphy_base, value, 0x2A4);
158 
159 	value = rk3576_phy_value[try_case][3];
160 	ufs_sys_writel(host->mphy_base, value, 0x178);
161 	ufs_sys_writel(host->mphy_base, value, 0x2B8);
162 
163 	ufs_sys_writel(host->mphy_base, 0x18, 0x1B0);
164 	ufs_sys_writel(host->mphy_base, 0x18, 0x2F0);
165 
166 	ufs_sys_writel(host->mphy_base, 0xC0, 0x120);
167 	ufs_sys_writel(host->mphy_base, 0xC0, 0x260);
168 
169 	ufs_sys_writel(host->mphy_base, 0x03, 0x094);
170 
171 	ufs_sys_writel(host->mphy_base, 0x03, 0x1B4);
172 	ufs_sys_writel(host->mphy_base, 0x03, 0x2F4);
173 
174 	ufs_sys_writel(host->mphy_base, 0xC0, 0x08C);
175 	udelay(1);
176 	ufs_sys_writel(host->mphy_base, 0x00, 0x08C);
177 
178 	udelay(200);
179 
180 	/* start link up */
181 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_TX_ENDIAN, 0), 0x0);
182 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_RX_ENDIAN, 0), 0x0);
183 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID, 0), 0x0);
184 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID_VALID, 0), 0x1);
185 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_PEERDEVICEID, 0), 0x1);
186 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_CONNECTIONSTATE, 0), 0x1);
187 
188 	return 0;
189 }
190 
191 static int ufs_rockchip_common_init(struct ufs_hba *hba)
192 {
193 	struct udevice *dev = hba->dev;
194 	struct ufs_rockchip_host *host = dev_get_priv(dev);
195 	struct resource res;
196 	int err = 0;
197 
198 	/* system control register for hci */
199 	err = dev_read_resource_byname(dev, "hci_grf", &res);
200 	if (err) {
201 		dev_err(dev, "cannot ioremap for hci system control register\n");
202 		return -ENODEV;
203 	}
204 	host->ufs_sys_ctrl = (void *)(res.start);
205 
206 	/* system control register for mphy */
207 	err = dev_read_resource_byname(dev, "mphy_grf", &res);
208 	if (err) {
209 		dev_err(dev, "cannot ioremap for mphy system control register\n");
210 		return -ENODEV;
211 	}
212 	host->ufs_phy_ctrl = (void *)(res.start);
213 
214 	/* mphy base register */
215 	err = dev_read_resource_byname(dev, "mphy", &res);
216 	if (err) {
217 		dev_err(dev, "cannot ioremap for mphy base register\n");
218 		return -ENODEV;
219 	}
220 	host->mphy_base = (void *)(res.start);
221 
222 	host->phy_config_mode = dev_read_u32_default(dev, "ufs-phy-config-mode", 0);
223 
224 	err = reset_get_bulk(dev, &host->rsts);
225 	if (err) {
226 		dev_err(dev, "Can't get reset: %d\n", err);
227 		return err;
228 	}
229 
230 	host->hba = hba;
231 
232 	return 0;
233 }
234 
235 static int ufs_rockchip_rk3576_init(struct ufs_hba *hba)
236 {
237 	struct udevice *dev = hba->dev;
238 	struct ufs_rockchip_host *host = dev_get_priv(dev);
239 	int ret = 0;
240 
241 	ret = ufs_rockchip_common_init(hba);
242 	if (ret) {
243 		dev_err(hba->dev, "%s: ufs common init fail\n", __func__);
244 		return ret;
245 	}
246 
247 	/* UFS PHY select 26M from ppll */
248 	writel(0x00030002, 0x2722030C);
249 	/* Set UFS_REFCLK, UFS_RSTN */
250 	writel(0x00FF0011, 0x2604B398);
251 
252 	/* Reset ufs controller and device */
253 	reset_assert_bulk(&host->rsts);
254 	writel(0x00100000, 0x2604B400);
255 
256 	udelay(20);
257 
258 	writel(0x00100010, 0x2604B400);
259 	reset_deassert_bulk(&host->rsts);
260 
261 	udelay(20);
262 
263 	return 0;
264 }
265 
266 static struct ufs_hba_ops ufs_hba_rk3576_vops = {
267 	.init = ufs_rockchip_rk3576_init,
268 	.phy_initialization = ufs_rockchip_rk3576_phy_init,
269 	.hce_enable_notify = ufs_rockchip_hce_enable_notify,
270 };
271 
272 static const struct udevice_id ufs_rockchip_of_match[] = {
273 	{ .compatible = "rockchip,rk3576-ufs", .data = (ulong)&ufs_hba_rk3576_vops},
274 	{},
275 };
276 
277 static int ufs_rockchip_probe(struct udevice *dev)
278 {
279 	struct ufs_hba_ops *ops = (struct ufs_hba_ops *)dev_get_driver_data(dev);
280 	int err;
281 
282 	err = ufshcd_probe(dev, ops);
283 	if (err)
284 		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
285 
286 	return err;
287 }
288 
289 static int ufs_rockchip_bind(struct udevice *dev)
290 {
291 	struct udevice *scsi_dev;
292 
293 	return ufs_scsi_bind(dev, &scsi_dev);
294 }
295 
296 U_BOOT_DRIVER(ti_j721e_ufs) = {
297 	.name		= "ufshcd-rockchip",
298 	.id		= UCLASS_UFS,
299 	.of_match	= ufs_rockchip_of_match,
300 	.probe		= ufs_rockchip_probe,
301 	.bind		= ufs_rockchip_bind,
302 	.priv_auto_alloc_size = sizeof(struct ufs_rockchip_host),
303 };
304