xref: /linux/drivers/phy/sunplus/phy-sunplus-usb2.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Sunplus SP7021 USB 2.0 phy driver
5  *
6  * Copyright (C) 2022 Sunplus Technology Inc., All rights reserved.
7  *
8  * Note 1 : non-posted write command for the registers accesses of
9  * Sunplus SP7021.
10  *
11  */
12 
13 #include <linux/bitfield.h>
14 #include <linux/clk.h>
15 #include <linux/delay.h>
16 #include <linux/io.h>
17 #include <linux/module.h>
18 #include <linux/nvmem-consumer.h>
19 #include <linux/of.h>
20 #include <linux/phy/phy.h>
21 #include <linux/platform_device.h>
22 #include <linux/reset.h>
23 
24 #define HIGH_MASK_BITS				GENMASK(31, 16)
25 #define LOW_MASK_BITS				GENMASK(15, 0)
26 #define OTP_DISC_LEVEL_DEFAULT			0xd
27 
28 /* GROUP UPHY */
29 #define CONFIG1					0x4
30 #define J_HS_TX_PWRSAV				BIT(5)
31 #define CONFIG3					0xc
32 #define J_FORCE_DISC_ON				BIT(5)
33 #define J_DEBUG_CTRL_ADDR_MACRO			BIT(0)
34 #define CONFIG7					0x1c
35 #define J_DISC					0X1f
36 #define CONFIG9					0x24
37 #define J_ECO_PATH				BIT(6)
38 #define CONFIG16				0x40
39 #define J_TBCWAIT_MASK				GENMASK(6, 5)
40 #define J_TBCWAIT_1P1_MS			FIELD_PREP(J_TBCWAIT_MASK, 0)
41 #define J_TVDM_SRC_DIS_MASK			GENMASK(4, 3)
42 #define J_TVDM_SRC_DIS_8P2_MS			FIELD_PREP(J_TVDM_SRC_DIS_MASK, 3)
43 #define J_TVDM_SRC_EN_MASK			GENMASK(2, 1)
44 #define J_TVDM_SRC_EN_1P6_MS			FIELD_PREP(J_TVDM_SRC_EN_MASK, 0)
45 #define J_BC_EN					BIT(0)
46 #define CONFIG17				0x44
47 #define IBG_TRIM0_MASK				GENMASK(7, 5)
48 #define IBG_TRIM0_SSLVHT			FIELD_PREP(IBG_TRIM0_MASK, 4)
49 #define J_VDATREE_TRIM_MASK			GENMASK(4, 1)
50 #define J_VDATREE_TRIM_DEFAULT			FIELD_PREP(J_VDATREE_TRIM_MASK, 9)
51 #define CONFIG23				0x5c
52 #define PROB_MASK				GENMASK(5, 3)
53 #define PROB					FIELD_PREP(PROB_MASK, 7)
54 
55 /* GROUP MOON4 */
56 #define UPHY_CONTROL0				0x0
57 #define UPHY_CONTROL1				0x4
58 #define UPHY_CONTROL2				0x8
59 #define MO1_UPHY_RX_CLK_SEL			BIT(6)
60 #define MASK_MO1_UPHY_RX_CLK_SEL		BIT(6 + 16)
61 #define UPHY_CONTROL3				0xc
62 #define MO1_UPHY_PLL_POWER_OFF_SEL		BIT(7)
63 #define MASK_MO1_UPHY_PLL_POWER_OFF_SEL		BIT(7 + 16)
64 #define MO1_UPHY_PLL_POWER_OFF			BIT(3)
65 #define MASK_UPHY_PLL_POWER_OFF			BIT(3 + 16)
66 
67 struct sp_usbphy {
68 	struct device *dev;
69 	struct resource *phy_res_mem;
70 	struct resource *moon4_res_mem;
71 	struct reset_control *rstc;
72 	struct clk *phy_clk;
73 	void __iomem *phy_regs;
74 	void __iomem *moon4_regs;
75 	u32 disc_vol_addr_off;
76 };
77 
78 static int update_disc_vol(struct sp_usbphy *usbphy)
79 {
80 	struct nvmem_cell *cell;
81 	char *disc_name = "disc_vol";
82 	ssize_t otp_l = 0;
83 	char *otp_v;
84 	u32 val, set;
85 
86 	cell = nvmem_cell_get(usbphy->dev, disc_name);
87 	if (IS_ERR_OR_NULL(cell)) {
88 		if (PTR_ERR(cell) == -EPROBE_DEFER)
89 			return -EPROBE_DEFER;
90 	}
91 
92 	otp_v = nvmem_cell_read(cell, &otp_l);
93 	nvmem_cell_put(cell);
94 
95 	if (!IS_ERR(otp_v)) {
96 		set = *(otp_v + 1);
97 		set = (set << (sizeof(char) * 8)) | *otp_v;
98 		set = (set >> usbphy->disc_vol_addr_off) & J_DISC;
99 	}
100 
101 	if (IS_ERR(otp_v) || set == 0)
102 		set = OTP_DISC_LEVEL_DEFAULT;
103 
104 	val = readl(usbphy->phy_regs + CONFIG7);
105 	val = (val & ~J_DISC) | set;
106 	writel(val, usbphy->phy_regs + CONFIG7);
107 
108 	return 0;
109 }
110 
111 static int sp_uphy_init(struct phy *phy)
112 {
113 	struct sp_usbphy *usbphy = phy_get_drvdata(phy);
114 	u32 val;
115 	int ret;
116 
117 	ret = clk_prepare_enable(usbphy->phy_clk);
118 	if (ret)
119 		goto err_clk;
120 
121 	ret = reset_control_deassert(usbphy->rstc);
122 	if (ret)
123 		goto err_reset;
124 
125 	/* Default value modification */
126 	writel(HIGH_MASK_BITS | 0x4002, usbphy->moon4_regs + UPHY_CONTROL0);
127 	writel(HIGH_MASK_BITS | 0x8747, usbphy->moon4_regs + UPHY_CONTROL1);
128 
129 	/* disconnect voltage */
130 	ret = update_disc_vol(usbphy);
131 	if (ret < 0)
132 		return ret;
133 
134 	/* board uphy 0 internal register modification for tid certification */
135 	val = readl(usbphy->phy_regs + CONFIG9);
136 	val &= ~(J_ECO_PATH);
137 	writel(val, usbphy->phy_regs + CONFIG9);
138 
139 	val = readl(usbphy->phy_regs + CONFIG1);
140 	val &= ~(J_HS_TX_PWRSAV);
141 	writel(val, usbphy->phy_regs + CONFIG1);
142 
143 	val = readl(usbphy->phy_regs + CONFIG23);
144 	val = (val & ~PROB) | PROB;
145 	writel(val, usbphy->phy_regs + CONFIG23);
146 
147 	/* port 0 uphy clk fix */
148 	writel(MASK_MO1_UPHY_RX_CLK_SEL | MO1_UPHY_RX_CLK_SEL,
149 	       usbphy->moon4_regs + UPHY_CONTROL2);
150 
151 	/* battery charger */
152 	writel(J_TBCWAIT_1P1_MS | J_TVDM_SRC_DIS_8P2_MS | J_TVDM_SRC_EN_1P6_MS | J_BC_EN,
153 	       usbphy->phy_regs + CONFIG16);
154 	writel(IBG_TRIM0_SSLVHT | J_VDATREE_TRIM_DEFAULT, usbphy->phy_regs + CONFIG17);
155 
156 	/* chirp mode */
157 	writel(J_FORCE_DISC_ON | J_DEBUG_CTRL_ADDR_MACRO, usbphy->phy_regs + CONFIG3);
158 
159 	return 0;
160 
161 err_reset:
162 	reset_control_assert(usbphy->rstc);
163 err_clk:
164 	clk_disable_unprepare(usbphy->phy_clk);
165 
166 	return ret;
167 }
168 
169 static int sp_uphy_power_on(struct phy *phy)
170 {
171 	struct sp_usbphy *usbphy = phy_get_drvdata(phy);
172 	u32 pll_pwr_on, pll_pwr_off;
173 
174 	/* PLL power off/on twice */
175 	pll_pwr_off = (readl(usbphy->moon4_regs + UPHY_CONTROL3) & ~LOW_MASK_BITS)
176 			| MO1_UPHY_PLL_POWER_OFF_SEL | MO1_UPHY_PLL_POWER_OFF;
177 	pll_pwr_on = (readl(usbphy->moon4_regs + UPHY_CONTROL3) & ~LOW_MASK_BITS)
178 			| MO1_UPHY_PLL_POWER_OFF_SEL;
179 
180 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_off,
181 	       usbphy->moon4_regs + UPHY_CONTROL3);
182 	mdelay(1);
183 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_on,
184 	       usbphy->moon4_regs + UPHY_CONTROL3);
185 	mdelay(1);
186 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_off,
187 	       usbphy->moon4_regs + UPHY_CONTROL3);
188 	mdelay(1);
189 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_on,
190 	       usbphy->moon4_regs + UPHY_CONTROL3);
191 	mdelay(1);
192 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | 0x0,
193 	       usbphy->moon4_regs + UPHY_CONTROL3);
194 
195 	return 0;
196 }
197 
198 static int sp_uphy_power_off(struct phy *phy)
199 {
200 	struct sp_usbphy *usbphy = phy_get_drvdata(phy);
201 	u32 pll_pwr_off;
202 
203 	pll_pwr_off = (readl(usbphy->moon4_regs + UPHY_CONTROL3) & ~LOW_MASK_BITS)
204 			| MO1_UPHY_PLL_POWER_OFF_SEL | MO1_UPHY_PLL_POWER_OFF;
205 
206 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | pll_pwr_off,
207 	       usbphy->moon4_regs + UPHY_CONTROL3);
208 	mdelay(1);
209 	writel(MASK_MO1_UPHY_PLL_POWER_OFF_SEL | MASK_UPHY_PLL_POWER_OFF | 0x0,
210 	       usbphy->moon4_regs + UPHY_CONTROL3);
211 
212 	return 0;
213 }
214 
215 static int sp_uphy_exit(struct phy *phy)
216 {
217 	struct sp_usbphy *usbphy = phy_get_drvdata(phy);
218 
219 	reset_control_assert(usbphy->rstc);
220 	clk_disable_unprepare(usbphy->phy_clk);
221 
222 	return 0;
223 }
224 
225 static const struct phy_ops sp_uphy_ops = {
226 	.init		= sp_uphy_init,
227 	.power_on	= sp_uphy_power_on,
228 	.power_off	= sp_uphy_power_off,
229 	.exit		= sp_uphy_exit,
230 };
231 
232 static const struct of_device_id sp_uphy_dt_ids[] = {
233 	{.compatible = "sunplus,sp7021-usb2-phy", },
234 	{ }
235 };
236 MODULE_DEVICE_TABLE(of, sp_uphy_dt_ids);
237 
238 static int sp_usb_phy_probe(struct platform_device *pdev)
239 {
240 	struct sp_usbphy *usbphy;
241 	struct phy_provider *phy_provider;
242 	struct phy *phy;
243 	int ret;
244 
245 	usbphy = devm_kzalloc(&pdev->dev, sizeof(*usbphy), GFP_KERNEL);
246 	if (!usbphy)
247 		return -ENOMEM;
248 
249 	usbphy->dev = &pdev->dev;
250 
251 	usbphy->phy_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
252 	usbphy->phy_regs = devm_ioremap_resource(&pdev->dev, usbphy->phy_res_mem);
253 	if (IS_ERR(usbphy->phy_regs))
254 		return PTR_ERR(usbphy->phy_regs);
255 
256 	usbphy->moon4_res_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "moon4");
257 	if (!usbphy->moon4_res_mem)
258 		return -EINVAL;
259 
260 	usbphy->moon4_regs = devm_ioremap(&pdev->dev, usbphy->moon4_res_mem->start,
261 					  resource_size(usbphy->moon4_res_mem));
262 	if (!usbphy->moon4_regs)
263 		return -ENOMEM;
264 
265 	usbphy->phy_clk = devm_clk_get(&pdev->dev, NULL);
266 	if (IS_ERR(usbphy->phy_clk))
267 		return PTR_ERR(usbphy->phy_clk);
268 
269 	usbphy->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
270 	if (IS_ERR(usbphy->rstc))
271 		return PTR_ERR(usbphy->rstc);
272 
273 	of_property_read_u32(pdev->dev.of_node, "sunplus,disc-vol-addr-off",
274 			     &usbphy->disc_vol_addr_off);
275 
276 	phy = devm_phy_create(&pdev->dev, NULL, &sp_uphy_ops);
277 	if (IS_ERR(phy)) {
278 		ret = PTR_ERR(phy);
279 		return ret;
280 	}
281 
282 	phy_set_drvdata(phy, usbphy);
283 	phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
284 
285 	return PTR_ERR_OR_ZERO(phy_provider);
286 }
287 
288 static struct platform_driver sunplus_usb_phy_driver = {
289 	.probe		= sp_usb_phy_probe,
290 	.driver		= {
291 		.name	= "sunplus-usb2-phy",
292 		.of_match_table = sp_uphy_dt_ids,
293 	},
294 };
295 module_platform_driver(sunplus_usb_phy_driver);
296 
297 MODULE_AUTHOR("Vincent Shih <vincent.shih@sunplus.com>");
298 MODULE_DESCRIPTION("Sunplus USB 2.0 phy driver");
299 MODULE_LICENSE("GPL");
300