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