1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Renesas RCar Gen2 USB PHY driver
4  *
5  * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com>
6  */
7 
8 #include <common.h>
9 #include <clk.h>
10 #include <div64.h>
11 #include <dm.h>
12 #include <fdtdec.h>
13 #include <generic-phy.h>
14 #include <malloc.h>
15 #include <reset.h>
16 #include <syscon.h>
17 #include <usb.h>
18 #include <asm/io.h>
19 #include <dm/device_compat.h>
20 #include <linux/bitops.h>
21 #include <linux/delay.h>
22 #include <power/regulator.h>
23 
24 #define USBHS_LPSTS			0x02
25 #define USBHS_UGCTRL			0x80
26 #define USBHS_UGCTRL2			0x84
27 #define USBHS_UGSTS			0x88	/* From technical update */
28 
29 /* Low Power Status register (LPSTS) */
30 #define USBHS_LPSTS_SUSPM		0x4000
31 
32 /* USB General control register (UGCTRL) */
33 #define USBHS_UGCTRL_CONNECT		BIT(2)
34 #define USBHS_UGCTRL_PLLRESET		BIT(0)
35 
36 /* USB General control register 2 (UGCTRL2) */
37 #define USBHS_UGCTRL2_USB2SEL		0x80000000
38 #define USBHS_UGCTRL2_USB2SEL_PCI	0x00000000
39 #define USBHS_UGCTRL2_USB2SEL_USB30	0x80000000
40 #define USBHS_UGCTRL2_USB0SEL		0x00000030
41 #define USBHS_UGCTRL2_USB0SEL_PCI	0x00000010
42 #define USBHS_UGCTRL2_USB0SEL_HS_USB	0x00000030
43 
44 /* USB General status register (UGSTS) */
45 #define USBHS_UGSTS_LOCK		0x00000100 /* From technical update */
46 
47 #define PHYS_PER_CHANNEL	2
48 
49 struct rcar_gen2_phy {
50 	fdt_addr_t	regs;
51 	struct clk	clk;
52 };
53 
rcar_gen2_phy_phy_init(struct phy * phy)54 static int rcar_gen2_phy_phy_init(struct phy *phy)
55 {
56 	struct rcar_gen2_phy *priv = dev_get_priv(phy->dev);
57 	u16 chan = phy->id & 0xffff;
58 	u16 mode = (phy->id >> 16) & 0xffff;
59 	u32 clrmask, setmask;
60 
61 	if (chan == 0) {
62 		clrmask = USBHS_UGCTRL2_USB0SEL;
63 		setmask = mode ? USBHS_UGCTRL2_USB0SEL_HS_USB :
64 				 USBHS_UGCTRL2_USB0SEL_PCI;
65 	} else {
66 		clrmask = USBHS_UGCTRL2_USB2SEL;
67 		setmask = mode ? USBHS_UGCTRL2_USB2SEL_USB30 :
68 				 USBHS_UGCTRL2_USB2SEL_PCI;
69 	}
70 	clrsetbits_le32(priv->regs + USBHS_UGCTRL2, clrmask, setmask);
71 
72 	return 0;
73 }
74 
rcar_gen2_phy_phy_power_on(struct phy * phy)75 static int rcar_gen2_phy_phy_power_on(struct phy *phy)
76 {
77 	struct rcar_gen2_phy *priv = dev_get_priv(phy->dev);
78 	int i;
79 	u32 value;
80 
81 	/* Power on USBHS PHY */
82 	clrbits_le32(priv->regs + USBHS_UGCTRL, USBHS_UGCTRL_PLLRESET);
83 
84 	setbits_le16(priv->regs + USBHS_LPSTS, USBHS_LPSTS_SUSPM);
85 
86 	for (i = 0; i < 20; i++) {
87 		value = readl(priv->regs + USBHS_UGSTS);
88 		if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) {
89 			setbits_le32(priv->regs + USBHS_UGCTRL,
90 				     USBHS_UGCTRL_CONNECT);
91 			return 0;
92 		}
93 		udelay(1);
94 	}
95 
96 	return -ETIMEDOUT;
97 }
98 
rcar_gen2_phy_phy_power_off(struct phy * phy)99 static int rcar_gen2_phy_phy_power_off(struct phy *phy)
100 {
101 	struct rcar_gen2_phy *priv = dev_get_priv(phy->dev);
102 
103 	/* Power off USBHS PHY */
104 	clrbits_le32(priv->regs + USBHS_UGCTRL, USBHS_UGCTRL_CONNECT);
105 
106 	clrbits_le16(priv->regs + USBHS_LPSTS, USBHS_LPSTS_SUSPM);
107 
108 	setbits_le32(priv->regs + USBHS_UGCTRL, USBHS_UGCTRL_PLLRESET);
109 
110 	return 0;
111 }
112 
rcar_gen2_phy_of_xlate(struct phy * phy,struct ofnode_phandle_args * args)113 static int rcar_gen2_phy_of_xlate(struct phy *phy,
114 				  struct ofnode_phandle_args *args)
115 {
116 	if (args->args_count != 2) {
117 		dev_err(phy->dev, "Invalid DT PHY argument count: %d\n",
118 			args->args_count);
119 		return -EINVAL;
120 	}
121 
122 	if (args->args[0] != 0 && args->args[0] != 2) {
123 		dev_err(phy->dev, "Invalid DT PHY channel: %d\n",
124 			args->args[0]);
125 		return -EINVAL;
126 	}
127 
128 	if (args->args[1] != 0 && args->args[1] != 1) {
129 		dev_err(phy->dev, "Invalid DT PHY mode: %d\n",
130 			args->args[1]);
131 		return -EINVAL;
132 	}
133 
134 	if (args->args_count)
135 		phy->id = args->args[0] | (args->args[1] << 16);
136 	else
137 		phy->id = 0;
138 
139 	return 0;
140 }
141 
142 static const struct phy_ops rcar_gen2_phy_phy_ops = {
143 	.init		= rcar_gen2_phy_phy_init,
144 	.power_on	= rcar_gen2_phy_phy_power_on,
145 	.power_off	= rcar_gen2_phy_phy_power_off,
146 	.of_xlate	= rcar_gen2_phy_of_xlate,
147 };
148 
rcar_gen2_phy_probe(struct udevice * dev)149 static int rcar_gen2_phy_probe(struct udevice *dev)
150 {
151 	struct rcar_gen2_phy *priv = dev_get_priv(dev);
152 	int ret;
153 
154 	priv->regs = dev_read_addr(dev);
155 	if (priv->regs == FDT_ADDR_T_NONE)
156 		return -EINVAL;
157 
158 	/* Enable clock */
159 	ret = clk_get_by_index(dev, 0, &priv->clk);
160 	if (ret)
161 		return ret;
162 
163 	ret = clk_enable(&priv->clk);
164 	if (ret)
165 		return ret;
166 
167 	return 0;
168 }
169 
rcar_gen2_phy_remove(struct udevice * dev)170 static int rcar_gen2_phy_remove(struct udevice *dev)
171 {
172 	struct rcar_gen2_phy *priv = dev_get_priv(dev);
173 
174 	clk_disable(&priv->clk);
175 	clk_free(&priv->clk);
176 
177 	return 0;
178 }
179 
180 static const struct udevice_id rcar_gen2_phy_of_match[] = {
181 	{ .compatible = "renesas,rcar-gen2-usb-phy", },
182 	{ },
183 };
184 
185 U_BOOT_DRIVER(rcar_gen2_phy) = {
186 	.name		= "rcar-gen2-phy",
187 	.id		= UCLASS_PHY,
188 	.of_match	= rcar_gen2_phy_of_match,
189 	.ops		= &rcar_gen2_phy_phy_ops,
190 	.probe		= rcar_gen2_phy_probe,
191 	.remove		= rcar_gen2_phy_remove,
192 	.priv_auto	= sizeof(struct rcar_gen2_phy),
193 };
194