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