xref: /rk3399_rockchip-uboot/drivers/ufs/ufs-rockchip.c (revision c5e0273071c3d3d3f8c19e55bb3779046715e1cc)
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) > 100) {
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 #endif
80 		if (hba->ops->phy_initialization) {
81 			err = hba->ops->phy_initialization(hba);
82 			if (err) {
83 				dev_err(hba->dev, "Phy setup failed (%d)\n", err);
84 			}
85 		}
86 	}
87 
88 	return err;
89 }
90 
91 static const unsigned char rk3576_phy_value[15][4] = {
92 	{0x03, 0x38, 0x50, 0x80},
93 	{0x03, 0x14, 0x58, 0x80},
94 	{0x03, 0x26, 0x58, 0x80},
95 	{0x03, 0x49, 0x58, 0x80},
96 	{0x03, 0x5A, 0x58, 0x80},
97 	{0xC3, 0x38, 0x50, 0xC0},
98 	{0xC3, 0x14, 0x58, 0xC0},
99 	{0xC3, 0x26, 0x58, 0xC0},
100 	{0xC3, 0x49, 0x58, 0xC0},
101 	{0xC3, 0x5A, 0x58, 0xC0},
102 	{0x43, 0x38, 0x50, 0xC0},
103 	{0x43, 0x14, 0x58, 0xC0},
104 	{0x43, 0x26, 0x58, 0xC0},
105 	{0x43, 0x49, 0x58, 0xC0},
106 	{0x43, 0x5A, 0x58, 0xC0}
107 };
108 
109 static int ufs_rockchip_rk3576_phy_init(struct ufs_hba *hba)
110 {
111 	struct ufs_rockchip_host *host = dev_get_priv(hba->dev);
112 	int try_case = host->phy_config_mode, value;
113 
114 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(PA_LOCAL_TX_LCC_ENABLE, 0x0), 0x0);
115 	/* enable the mphy DME_SET cfg */
116 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x40);
117 	for (int i = 0; i < 2; i++) {
118 		/* Configuration M-TX */
119 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xaa, SEL_TX_LANE0 + i), 0x06);
120 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xa9, SEL_TX_LANE0 + i), 0x02);
121 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xad, SEL_TX_LANE0 + i), 0x44);
122 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xac, SEL_TX_LANE0 + i), 0xe6);
123 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0xab, SEL_TX_LANE0 + i), 0x07);
124 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x94, SEL_TX_LANE0 + i), 0x93);
125 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x93, SEL_TX_LANE0 + i), 0xc9);
126 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x7f, SEL_TX_LANE0 + i), 0x00);
127 		/* Configuration M-RX */
128 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x12, SEL_RX_LANE0 + i), 0x06);
129 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x11, SEL_RX_LANE0 + i), 0x00);
130 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1d, SEL_RX_LANE0 + i), 0x58);
131 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1c, SEL_RX_LANE0 + i), 0x8c);
132 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x1b, SEL_RX_LANE0 + i), 0x02);
133 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x25, SEL_RX_LANE0 + i), 0xf6);
134 		ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x2f, SEL_RX_LANE0 + i), 0x69);
135 	}
136 	/* disable the mphy DME_SET cfg */
137 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(0x200, 0x0), 0x00);
138 
139 	ufs_sys_writel(host->mphy_base, 0x80, 0x08C);
140 	ufs_sys_writel(host->mphy_base, 0xB5, 0x110);
141 	ufs_sys_writel(host->mphy_base, 0xB5, 0x250);
142 
143 	value = rk3576_phy_value[try_case][0];
144 	ufs_sys_writel(host->mphy_base, value, 0x134);
145 	ufs_sys_writel(host->mphy_base, value, 0x274);
146 
147 	value = rk3576_phy_value[try_case][1];
148 	ufs_sys_writel(host->mphy_base, value, 0x0E0);
149 	ufs_sys_writel(host->mphy_base, value, 0x220);
150 
151 	value = rk3576_phy_value[try_case][2];
152 	ufs_sys_writel(host->mphy_base, value, 0x164);
153 	ufs_sys_writel(host->mphy_base, value, 0x2A4);
154 
155 	value = rk3576_phy_value[try_case][3];
156 	ufs_sys_writel(host->mphy_base, value, 0x178);
157 	ufs_sys_writel(host->mphy_base, value, 0x2B8);
158 
159 	ufs_sys_writel(host->mphy_base, 0x18, 0x1B0);
160 	ufs_sys_writel(host->mphy_base, 0x18, 0x2F0);
161 
162 	ufs_sys_writel(host->mphy_base, 0xC0, 0x120);
163 	ufs_sys_writel(host->mphy_base, 0xC0, 0x260);
164 
165 	ufs_sys_writel(host->mphy_base, 0x03, 0x094);
166 
167 	ufs_sys_writel(host->mphy_base, 0x03, 0x1B4);
168 	ufs_sys_writel(host->mphy_base, 0x03, 0x2F4);
169 
170 	ufs_sys_writel(host->mphy_base, 0xC0, 0x08C);
171 	udelay(1);
172 	ufs_sys_writel(host->mphy_base, 0x00, 0x08C);
173 
174 	udelay(200);
175 
176 	/* start link up */
177 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_TX_ENDIAN, 0), 0x0);
178 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(MIB_T_DBG_CPORT_RX_ENDIAN, 0), 0x0);
179 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID, 0), 0x0);
180 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(N_DEVICEID_VALID, 0), 0x1);
181 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_PEERDEVICEID, 0), 0x1);
182 	ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(T_CONNECTIONSTATE, 0), 0x1);
183 
184 	return 0;
185 }
186 
187 static int ufs_rockchip_common_init(struct ufs_hba *hba)
188 {
189 	struct udevice *dev = hba->dev;
190 	struct ufs_rockchip_host *host = dev_get_priv(dev);
191 	struct resource res;
192 	int err = 0;
193 
194 	/* system control register for hci */
195 	err = dev_read_resource_byname(dev, "hci_grf", &res);
196 	if (err) {
197 		dev_err(dev, "cannot ioremap for hci system control register\n");
198 		return -ENODEV;
199 	}
200 	host->ufs_sys_ctrl = (void *)(res.start);
201 
202 	/* system control register for mphy */
203 	err = dev_read_resource_byname(dev, "mphy_grf", &res);
204 	if (err) {
205 		dev_err(dev, "cannot ioremap for mphy system control register\n");
206 		return -ENODEV;
207 	}
208 	host->ufs_phy_ctrl = (void *)(res.start);
209 
210 	/* mphy base register */
211 	err = dev_read_resource_byname(dev, "mphy", &res);
212 	if (err) {
213 		dev_err(dev, "cannot ioremap for mphy base register\n");
214 		return -ENODEV;
215 	}
216 	host->mphy_base = (void *)(res.start);
217 
218 	host->phy_config_mode = dev_read_u32_default(dev, "ufs-phy-config-mode", 0);
219 
220 	err = reset_get_bulk(dev, &host->rsts);
221 	if (err) {
222 		dev_err(dev, "Can't get reset: %d\n", err);
223 		return err;
224 	}
225 
226 	host->hba = hba;
227 
228 	return 0;
229 }
230 
231 static int ufs_rockchip_rk3576_init(struct ufs_hba *hba)
232 {
233 	struct udevice *dev = hba->dev;
234 	struct ufs_rockchip_host *host = dev_get_priv(dev);
235 	int ret = 0;
236 
237 	ret = ufs_rockchip_common_init(hba);
238 	if (ret) {
239 		dev_err(hba->dev, "%s: ufs common init fail\n", __func__);
240 		return ret;
241 	}
242 
243 	/* UFS PHY select 26M from ppll */
244 	writel(0x00030002, 0x2722030C);
245 	/* Set UFS_REFCLK, UFS_RSTN */
246 	writel(0x00FF0011, 0x2604B398);
247 
248 	/* Reset ufs controller and device */
249 	reset_assert_bulk(&host->rsts);
250 	writel(0x00100000, 0x2604B400);
251 
252 	udelay(20);
253 
254 	writel(0x00100010, 0x2604B400);
255 	reset_deassert_bulk(&host->rsts);
256 
257 	udelay(20);
258 
259 	return 0;
260 }
261 
262 static struct ufs_hba_ops ufs_hba_rk3576_vops = {
263 	.init = ufs_rockchip_rk3576_init,
264 	.phy_initialization = ufs_rockchip_rk3576_phy_init,
265 	.hce_enable_notify = ufs_rockchip_hce_enable_notify,
266 };
267 
268 static const struct udevice_id ufs_rockchip_of_match[] = {
269 	{ .compatible = "rockchip,rk3576-ufs", .data = (ulong)&ufs_hba_rk3576_vops},
270 	{},
271 };
272 
273 static int ufs_rockchip_probe(struct udevice *dev)
274 {
275 	struct ufs_hba_ops *ops = (struct ufs_hba_ops *)dev_get_driver_data(dev);
276 	int err;
277 
278 	err = ufshcd_probe(dev, ops);
279 	if (err)
280 		dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err);
281 
282 	return err;
283 }
284 
285 static int ufs_rockchip_bind(struct udevice *dev)
286 {
287 	struct udevice *scsi_dev;
288 
289 	return ufs_scsi_bind(dev, &scsi_dev);
290 }
291 
292 U_BOOT_DRIVER(ti_j721e_ufs) = {
293 	.name		= "ufshcd-rockchip",
294 	.id		= UCLASS_UFS,
295 	.of_match	= ufs_rockchip_of_match,
296 	.probe		= ufs_rockchip_probe,
297 	.bind		= ufs_rockchip_bind,
298 	.priv_auto_alloc_size = sizeof(struct ufs_rockchip_host),
299 };
300