xref: /openbsd/sys/dev/fdt/rktcphy.c (revision 471aeecf)
1 /* $OpenBSD: rktcphy.c,v 1.2 2022/04/06 18:59:28 naddy Exp $ */
2 /*-
3  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4  *
5  * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.Org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * Rockchip PHY TYPEC
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 
37 #include <machine/intr.h>
38 #include <machine/bus.h>
39 #include <machine/fdt.h>
40 
41 #include <dev/ofw/openfirm.h>
42 #include <dev/ofw/ofw_clock.h>
43 #include <dev/ofw/ofw_misc.h>
44 #include <dev/ofw/fdt.h>
45 
46 #define	GRF_USB3OTG_BASE(x)	(0x2430 + (0x10 * x))
47 #define	GRF_USB3OTG_CON0(x)	(GRF_USB3OTG_BASE(x) + 0x0)
48 #define	GRF_USB3OTG_CON1(x)	(GRF_USB3OTG_BASE(x) + 0x4)
49 #define	 USB3OTG_CON1_U3_DIS	(1 << 0)
50 
51 #define	GRF_USB3PHY_BASE(x)	(0x0e580 + (0xc * (x)))
52 #define	GRF_USB3PHY_CON0(x)	(GRF_USB3PHY_BASE(x) + 0x0)
53 #define	 USB3PHY_CON0_USB2_ONLY	(1 << 3)
54 #define	GRF_USB3PHY_CON1(x)	(GRF_USB3PHY_BASE(x) + 0x4)
55 #define	GRF_USB3PHY_CON2(x)	(GRF_USB3PHY_BASE(x) + 0x8)
56 #define	GRF_USB3PHY_STATUS0	0x0e5c0
57 #define	GRF_USB3PHY_STATUS1	0x0e5c4
58 
59 #define	CMN_PLL0_VCOCAL_INIT		(0x84 << 2)
60 #define	CMN_PLL0_VCOCAL_ITER		(0x85 << 2)
61 #define	CMN_PLL0_INTDIV			(0x94 << 2)
62 #define	CMN_PLL0_FRACDIV		(0x95 << 2)
63 #define	CMN_PLL0_HIGH_THR		(0x96 << 2)
64 #define	CMN_PLL0_DSM_DIAG		(0x97 << 2)
65 #define	CMN_PLL0_SS_CTRL1		(0x98 << 2)
66 #define	CMN_PLL0_SS_CTRL2		(0x99 << 2)
67 #define	CMN_DIAG_PLL0_FBH_OVRD		(0x1c0 << 2)
68 #define	CMN_DIAG_PLL0_FBL_OVRD		(0x1c1 << 2)
69 #define	CMN_DIAG_PLL0_OVRD		(0x1c2 << 2)
70 #define	CMN_DIAG_PLL0_V2I_TUNE		(0x1c5 << 2)
71 #define	CMN_DIAG_PLL0_CP_TUNE		(0x1c6 << 2)
72 #define	CMN_DIAG_PLL0_LF_PROG		(0x1c7 << 2)
73 #define	CMN_DIAG_HSCLK_SEL		(0x1e0 << 2)
74 #define	 CMN_DIAG_HSCLK_SEL_PLL_CONFIG	0x30
75 #define	 CMN_DIAG_HSCLK_SEL_PLL_MASK	0x33
76 
77 #define	TX_TXCC_MGNFS_MULT_000(lane)	((0x4050 | ((lane) << 9)) << 2)
78 #define	XCVR_DIAG_BIDI_CTRL(lane)	((0x40e8 | ((lane) << 9)) << 2)
79 #define	XCVR_DIAG_LANE_FCM_EN_MGN(lane)	((0x40f2 | ((lane) << 9)) << 2)
80 #define	TX_PSC_A0(lane)			((0x4100 | ((lane) << 9)) << 2)
81 #define	TX_PSC_A1(lane)			((0x4101 | ((lane) << 9)) << 2)
82 #define	TX_PSC_A2(lane)			((0x4102 | ((lane) << 9)) << 2)
83 #define	TX_PSC_A3(lane)			((0x4103 | ((lane) << 9)) << 2)
84 #define	TX_RCVDET_EN_TMR(lane)		((0x4122 | ((lane) << 9)) << 2)
85 #define	TX_RCVDET_ST_TMR(lane)		((0x4123 | ((lane) << 9)) << 2)
86 
87 #define	RX_PSC_A0(lane)			((0x8000 | ((lane) << 9)) << 2)
88 #define	RX_PSC_A1(lane)			((0x8001 | ((lane) << 9)) << 2)
89 #define	RX_PSC_A2(lane)			((0x8002 | ((lane) << 9)) << 2)
90 #define	RX_PSC_A3(lane)			((0x8003 | ((lane) << 9)) << 2)
91 #define	RX_PSC_CAL(lane)		((0x8006 | ((lane) << 9)) << 2)
92 #define	RX_PSC_RDY(lane)		((0x8007 | ((lane) << 9)) << 2)
93 #define	RX_SIGDET_HL_FILT_TMR(lane)	((0x8090 | ((lane) << 9)) << 2)
94 #define	RX_REE_CTRL_DATA_MASK(lane)	((0x81bb | ((lane) << 9)) << 2)
95 #define	RX_DIAG_SIGDET_TUNE(lane)	((0x81dc | ((lane) << 9)) << 2)
96 
97 #define	PMA_LANE_CFG			(0xc000 << 2)
98 #define	PIN_ASSIGN_D_F			0x5100
99 #define	DP_MODE_CTL			(0xc008 << 2)
100 #define	DP_MODE_ENTER_A2		0xc104
101 #define	PMA_CMN_CTRL1			(0xc800 << 2)
102 #define	 PMA_CMN_CTRL1_READY		(1 << 0)
103 
104 #define HREAD4(sc, reg)							\
105 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
106 #define HWRITE4(sc, reg, val)						\
107 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
108 #define HSET4(sc, reg, bits)						\
109 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
110 #define HCLR4(sc, reg, bits)						\
111 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
112 
113 struct rktcphy_softc {
114 	struct device		sc_dev;
115 	bus_space_tag_t		sc_iot;
116 	bus_space_handle_t	sc_ioh;
117 	int			sc_node;
118 	struct regmap		*sc_grf;
119 
120 	struct phy_device	sc_pd;
121 	int			sc_mode;
122 	int			sc_phy_ctrl_id;
123 };
124 
125 int rktcphy_match(struct device *, void *, void *);
126 void rktcphy_attach(struct device *, struct device *, void *);
127 
128 void rktcphy_set_usb2_only(struct rktcphy_softc *, int);
129 int rktcphy_enable(void *, uint32_t *);
130 
131 const struct cfattach rktcphy_ca = {
132 	sizeof (struct rktcphy_softc), rktcphy_match, rktcphy_attach
133 };
134 
135 struct cfdriver rktcphy_cd = {
136 	NULL, "rktcphy", DV_DULL
137 };
138 
139 int
rktcphy_match(struct device * parent,void * match,void * aux)140 rktcphy_match(struct device *parent, void *match, void *aux)
141 {
142 	struct fdt_attach_args *faa = aux;
143 
144 	return OF_is_compatible(faa->fa_node, "rockchip,rk3399-typec-phy");
145 }
146 
147 void
rktcphy_attach(struct device * parent,struct device * self,void * aux)148 rktcphy_attach(struct device *parent, struct device *self, void *aux)
149 {
150 	struct rktcphy_softc *sc = (struct rktcphy_softc *)self;
151 	struct fdt_attach_args *faa = aux;
152 	uint32_t grf;
153 	int usb3;
154 
155 	if (faa->fa_nreg < 1) {
156 		printf(": no registers\n");
157 		return;
158 	}
159 
160 	sc->sc_node = faa->fa_node;
161 	sc->sc_iot = faa->fa_iot;
162 
163 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
164 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
165 		printf(": can't map registers\n");
166 		return;
167 	}
168 
169 	/*
170 	 * Find out which phy we are.  There is no property for this so we need
171 	 * to know the address to use the correct GRF registers.
172 	 */
173 	switch (faa->fa_reg[0].addr) {
174 	case 0xff7c0000:
175 		sc->sc_phy_ctrl_id = 0;
176 		break;
177 	case 0xff800000:
178 		sc->sc_phy_ctrl_id = 1;
179 		break;
180 	default:
181 		printf(": unknown address 0x%llx\n", faa->fa_reg[0].addr);
182 		return;
183 	}
184 
185 	grf = OF_getpropint(sc->sc_node, "rockchip,grf", 0);
186 	sc->sc_grf = regmap_byphandle(grf);
187 
188 	reset_assert(sc->sc_node, "uphy");
189 	reset_assert(sc->sc_node, "uphy-pipe");
190 	reset_assert(sc->sc_node, "uphy-tcphy");
191 
192 	clock_set_assigned(sc->sc_node);
193 
194 	/* Only usb3 port is supported right now */
195 	usb3 = OF_getnodebyname(sc->sc_node, "usb3-port");
196 	if (usb3 == 0) {
197 		printf(": no usb3-port child node\n");
198 		return;
199 	}
200 
201 	printf("\n");
202 
203 	sc->sc_pd.pd_node = usb3;
204 	sc->sc_pd.pd_cookie = sc;
205 	sc->sc_pd.pd_enable = rktcphy_enable;
206 	phy_register(&sc->sc_pd);
207 }
208 
209 void
rktcphy_set_usb2_only(struct rktcphy_softc * sc,int usb2only)210 rktcphy_set_usb2_only(struct rktcphy_softc *sc, int usb2only)
211 {
212 	uint32_t reg;
213 
214 	/* Disable usb3tousb2 only */
215 	reg = regmap_read_4(sc->sc_grf, GRF_USB3PHY_CON0(sc->sc_phy_ctrl_id));
216 	if (usb2only)
217 		reg |= USB3PHY_CON0_USB2_ONLY;
218 	else
219 		reg &= ~USB3PHY_CON0_USB2_ONLY;
220 	/* Write Mask */
221 	reg |= (USB3PHY_CON0_USB2_ONLY) << 16;
222 	regmap_write_4(sc->sc_grf, GRF_USB3PHY_CON0(sc->sc_phy_ctrl_id), reg);
223 
224 	/* Enable the USB3 Super Speed port */
225 	reg = regmap_read_4(sc->sc_grf, GRF_USB3OTG_CON1(sc->sc_phy_ctrl_id));
226 	if (usb2only)
227 		reg |= USB3OTG_CON1_U3_DIS;
228 	else
229 		reg &= ~USB3OTG_CON1_U3_DIS;
230 	/* Write Mask */
231 	reg |= (USB3OTG_CON1_U3_DIS) << 16;
232 	regmap_write_4(sc->sc_grf, GRF_USB3OTG_CON1(sc->sc_phy_ctrl_id), reg);
233 }
234 
235 int
rktcphy_enable(void * cookie,uint32_t * cells)236 rktcphy_enable(void *cookie, uint32_t *cells)
237 {
238 	struct rktcphy_softc *sc = cookie;
239 	uint32_t reg;
240 	int i;
241 
242 	rktcphy_set_usb2_only(sc, false);
243 
244 	clock_enable(sc->sc_node, "tcpdcore");
245 	clock_enable(sc->sc_node, "tcpdphy-ref");
246 
247 	reset_deassert(sc->sc_node, "uphy-tcphy");
248 
249 	/* 24M configuration, magic values from rockchip */
250 	HWRITE4(sc, PMA_CMN_CTRL1, 0x830);
251 	for (i = 0; i < 4; i++) {
252 		HWRITE4(sc, XCVR_DIAG_LANE_FCM_EN_MGN(i), 0x90);
253 		HWRITE4(sc, TX_RCVDET_EN_TMR(i), 0x960);
254 		HWRITE4(sc, TX_RCVDET_ST_TMR(i), 0x30);
255 	}
256 	reg = HREAD4(sc, CMN_DIAG_HSCLK_SEL);
257 	reg &= ~CMN_DIAG_HSCLK_SEL_PLL_MASK;
258 	reg |= CMN_DIAG_HSCLK_SEL_PLL_CONFIG;
259 	HWRITE4(sc, CMN_DIAG_HSCLK_SEL, reg);
260 
261 	/* PLL configuration, magic values from rockchip */
262 	HWRITE4(sc, CMN_PLL0_VCOCAL_INIT, 0xf0);
263 	HWRITE4(sc, CMN_PLL0_VCOCAL_ITER, 0x18);
264 	HWRITE4(sc, CMN_PLL0_INTDIV, 0xd0);
265 	HWRITE4(sc, CMN_PLL0_FRACDIV, 0x4a4a);
266 	HWRITE4(sc, CMN_PLL0_HIGH_THR, 0x34);
267 	HWRITE4(sc, CMN_PLL0_SS_CTRL1, 0x1ee);
268 	HWRITE4(sc, CMN_PLL0_SS_CTRL2, 0x7f03);
269 	HWRITE4(sc, CMN_PLL0_DSM_DIAG, 0x20);
270 	HWRITE4(sc, CMN_DIAG_PLL0_OVRD, 0);
271 	HWRITE4(sc, CMN_DIAG_PLL0_FBH_OVRD, 0);
272 	HWRITE4(sc, CMN_DIAG_PLL0_FBL_OVRD, 0);
273 	HWRITE4(sc, CMN_DIAG_PLL0_V2I_TUNE, 0x7);
274 	HWRITE4(sc, CMN_DIAG_PLL0_CP_TUNE, 0x45);
275 	HWRITE4(sc, CMN_DIAG_PLL0_LF_PROG, 0x8);
276 
277 	/* Configure the TX and RX line, magic values from rockchip */
278 	HWRITE4(sc, TX_PSC_A0(0), 0x7799);
279 	HWRITE4(sc, TX_PSC_A1(0), 0x7798);
280 	HWRITE4(sc, TX_PSC_A2(0), 0x5098);
281 	HWRITE4(sc, TX_PSC_A3(0), 0x5098);
282 	HWRITE4(sc, TX_TXCC_MGNFS_MULT_000(0), 0x0);
283 	HWRITE4(sc, XCVR_DIAG_BIDI_CTRL(0), 0xbf);
284 
285 	HWRITE4(sc, RX_PSC_A0(1), 0xa6fd);
286 	HWRITE4(sc, RX_PSC_A1(1), 0xa6fd);
287 	HWRITE4(sc, RX_PSC_A2(1), 0xa410);
288 	HWRITE4(sc, RX_PSC_A3(1), 0x2410);
289 	HWRITE4(sc, RX_PSC_CAL(1), 0x23ff);
290 	HWRITE4(sc, RX_SIGDET_HL_FILT_TMR(1), 0x13);
291 	HWRITE4(sc, RX_REE_CTRL_DATA_MASK(1), 0x03e7);
292 	HWRITE4(sc, RX_DIAG_SIGDET_TUNE(1), 0x1004);
293 	HWRITE4(sc, RX_PSC_RDY(1), 0x2010);
294 	HWRITE4(sc, XCVR_DIAG_BIDI_CTRL(1), 0xfb);
295 
296 	HWRITE4(sc, PMA_LANE_CFG, PIN_ASSIGN_D_F);
297 
298 	HWRITE4(sc, DP_MODE_CTL, DP_MODE_ENTER_A2);
299 
300 	reset_deassert(sc->sc_node, "uphy");
301 
302 	for (i = 10000; i > 0; i--) {
303 		reg = HREAD4(sc, PMA_CMN_CTRL1);
304 		if (reg & PMA_CMN_CTRL1_READY)
305 			break;
306 		delay(10);
307 	}
308 	if (i == 0) {
309 		printf("%s: timeout waiting for PMA\n", sc->sc_dev.dv_xname);
310 		return ENXIO;
311 	}
312 
313 	reset_deassert(sc->sc_node, "uphy-pipe");
314 	return 0;
315 }
316