xref: /freebsd/sys/arm64/rockchip/rk_pcie_phy.c (revision 1da7f3f6f72b2245e458fc7195733268ae4a1136)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * Rockchip PHY TYPEC
30  */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/rman.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/mutex.h>
39 #include <sys/gpio.h>
40 #include <machine/bus.h>
41 
42 #include <dev/fdt/fdt_common.h>
43 #include <dev/ofw/ofw_bus.h>
44 #include <dev/ofw/ofw_bus_subr.h>
45 #include <dev/ofw/ofw_subr.h>
46 
47 #include <dev/extres/clk/clk.h>
48 #include <dev/extres/phy/phy.h>
49 #include <dev/extres/phy/phy_internal.h>
50 #include <dev/extres/syscon/syscon.h>
51 #include <dev/extres/hwreset/hwreset.h>
52 
53 #include "syscon_if.h"
54 
55 #define GRF_HIWORD_SHIFT	16
56 #define	GRF_SOC_CON_5_PCIE	0xE214
57 #define	 CON_5_PCIE_IDLE_OFF(x)	(1 <<(((x) & 0x3) + 3))
58 #define	GRF_SOC_CON8		0xE220
59 #define	GRF_SOC_STATUS1 	0xE2A4
60 
61 /* PHY config registers  - write */
62 #define	PHY_CFG_CLK_TEST	0x10
63 #define	 CLK_TEST_SEPE_RATE		(1 << 3)
64 #define	PHY_CFG_CLK_SCC		0x12
65 #define	 CLK_SCC_PLL_100M		(1 << 3)
66 
67 /* PHY config registers  - read */
68 #define	PHY_CFG_PLL_LOCK	0x10
69 #define	 CLK_PLL_LOCKED			(1 << 1)
70 #define	PHY_CFG_SCC_LOCK	0x12
71 #define	 CLK_SCC_100M_GATE		(1 << 2)
72 
73 #define	 STATUS1_PLL_LOCKED		(1 << 9)
74 
75 static struct ofw_compat_data compat_data[] = {
76 	{"rockchip,rk3399-pcie-phy",	1},
77 	{NULL,				0}
78 };
79 
80 struct rk_pcie_phy_softc {
81 	device_t		dev;
82 	struct syscon		*syscon;
83 	struct mtx		mtx;
84 	clk_t			clk_ref;
85 	hwreset_t		hwreset_phy;
86 	int			enable_count;
87 };
88 
89 #define	PHY_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
90 #define	PHY_UNLOCK(_sc)		mtx_unlock(&(_sc)->mtx)
91 #define	PHY_LOCK_INIT(_sc)	mtx_init(&(_sc)->mtx, 			\
92 	    device_get_nameunit(_sc->dev), "rk_pcie_phyc", MTX_DEF)
93 #define	PHY_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->mtx);
94 #define	PHY_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->mtx, MA_OWNED);
95 #define	PHY_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
96 
97 #define	RD4(sc, reg)		SYSCON_READ_4((sc)->syscon, (reg))
98 #define	WR4(sc, reg, mask, val)						\
99     SYSCON_WRITE_4((sc)->syscon, (reg), ((mask) << GRF_HIWORD_SHIFT) | (val))
100 
101 #define	MAX_LANE	4
102 
103 static void
104 cfg_write(struct rk_pcie_phy_softc *sc, uint32_t reg, uint32_t data)
105 {
106 	/* setup register address and data first */
107 	WR4(sc, GRF_SOC_CON8, 0x7FF,
108 	    (reg & 0x3F) << 1 | (data & 0x0F) << 7);
109 	/* dummy readback for sync */
110 	RD4(sc, GRF_SOC_CON8);
111 
112 	/* Do write pulse */
113 	WR4(sc, GRF_SOC_CON8, 1, 1);
114 	RD4(sc, GRF_SOC_CON8);
115 	DELAY(10);
116 	WR4(sc, GRF_SOC_CON8, 1, 0);
117 	RD4(sc, GRF_SOC_CON8);
118 	DELAY(10);
119 }
120 
121 static uint32_t
122 cfg_read(struct rk_pcie_phy_softc *sc, uint32_t reg)
123 {
124 	uint32_t val;
125 
126 	WR4(sc, GRF_SOC_CON8, 0x3FF, reg << 1);
127 	RD4(sc, GRF_SOC_CON8);
128 	DELAY(10);
129 	val = RD4(sc, GRF_SOC_STATUS1);
130 	return ((val >> 8) & 0x0f);
131 }
132 
133 static int
134 rk_pcie_phy_up(struct rk_pcie_phy_softc *sc, int id)
135 {
136 	uint32_t val;
137 	int i, rv;
138 
139 	PHY_LOCK(sc);
140 
141 	sc->enable_count++;
142 	if (sc->enable_count != 1) {
143 		PHY_UNLOCK(sc);
144 		return (0);
145 	}
146 
147 	rv = hwreset_deassert(sc->hwreset_phy);
148 	if (rv != 0) {
149 		device_printf(sc->dev, "Cannot deassert 'phy' reset\n");
150 		PHY_UNLOCK(sc);
151 		return (rv);
152 	}
153 	/* Un-idle all lanes */
154 	for (i = 0; i < MAX_LANE; i++)
155 		WR4(sc, GRF_SOC_CON_5_PCIE, CON_5_PCIE_IDLE_OFF(i), 0);
156 
157 	/* Wait for PLL lock */
158 	for (i = 100; i > 0; i--) {
159 		val = cfg_read(sc, PHY_CFG_PLL_LOCK);
160 		if (val & CLK_PLL_LOCKED)
161 			break;
162 		DELAY(1000);
163 	}
164 	if (i <= 0) {
165 		device_printf(sc->dev, "PLL lock timeouted, 0x%02X\n", val);
166 		PHY_UNLOCK(sc);
167 		return (ETIMEDOUT);
168 	}
169 	/* Switch PLL to stable 5GHz, rate adjustment is done by divider */
170 	cfg_write(sc, PHY_CFG_CLK_TEST, CLK_TEST_SEPE_RATE);
171 	/* Enable 100MHz output for PCIe ref clock */
172 	cfg_write(sc, PHY_CFG_CLK_SCC, CLK_SCC_PLL_100M);
173 
174 	/* Wait for ungating of ref clock */
175 	for (i = 100; i > 0; i--) {
176 		val = cfg_read(sc, PHY_CFG_SCC_LOCK);
177 		if ((val & CLK_SCC_100M_GATE) == 0)
178 			break;
179 		DELAY(1000);
180 	}
181 	if (i <= 0) {
182 		device_printf(sc->dev, "PLL output enable timeouted\n");
183 		PHY_UNLOCK(sc);
184 		return (ETIMEDOUT);
185 	}
186 
187 	/* Wait for PLL relock (to 5GHz) */
188 	for (i = 100; i > 0; i--) {
189 		val = cfg_read(sc, PHY_CFG_PLL_LOCK);
190 		if (val & CLK_PLL_LOCKED)
191 			break;
192 		DELAY(1000);
193 	}
194 	if (i <= 0) {
195 		device_printf(sc->dev, "PLL relock timeouted\n");
196 		PHY_UNLOCK(sc);
197 		return (ETIMEDOUT);
198 	}
199 
200 	PHY_UNLOCK(sc);
201 	return (rv);
202 }
203 
204 static int
205 rk_pcie_phy_down(struct rk_pcie_phy_softc *sc, int id)
206 {
207 	int rv;
208 
209 	PHY_LOCK(sc);
210 
211 	rv = 0;
212 	if (sc->enable_count <= 0)
213 		panic("unpaired enable/disable");
214 
215 	sc->enable_count--;
216 
217 	/* Idle given lane */
218 	WR4(sc, GRF_SOC_CON_5_PCIE,
219 	    CON_5_PCIE_IDLE_OFF(id),
220 	    CON_5_PCIE_IDLE_OFF(id));
221 
222 	if (sc->enable_count == 0) {
223 		rv = hwreset_assert(sc->hwreset_phy);
224 		if (rv != 0)
225 			device_printf(sc->dev, "Cannot assert 'phy' reset\n");
226 	}
227 	PHY_UNLOCK(sc);
228 	return (rv);
229 }
230 
231 static int
232 rk_pcie_phy_enable(struct phynode *phynode, bool enable)
233 {
234 	struct rk_pcie_phy_softc *sc;
235 	device_t dev;
236 	intptr_t phy;
237 	int rv;
238 
239 	dev = phynode_get_device(phynode);
240 	phy = phynode_get_id(phynode);
241 	sc = device_get_softc(dev);
242 
243 	if (enable)
244 		rv = rk_pcie_phy_up(sc, (int)phy);
245 	 else
246 		rv = rk_pcie_phy_down(sc, (int) phy);
247 
248 	return (rv);
249 }
250 
251 /* Phy class and methods. */
252 static phynode_method_t rk_pcie_phy_phynode_methods[] = {
253 	PHYNODEMETHOD(phynode_enable,		 rk_pcie_phy_enable),
254 
255 	PHYNODEMETHOD_END
256 };
257 
258 DEFINE_CLASS_1( rk_pcie_phy_phynode, rk_pcie_phy_phynode_class,
259     rk_pcie_phy_phynode_methods, 0, phynode_class);
260 
261 static int
262  rk_pcie_phy_probe(device_t dev)
263 {
264 
265 	if (!ofw_bus_status_okay(dev))
266 		return (ENXIO);
267 
268 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
269 		return (ENXIO);
270 
271 	device_set_desc(dev, "Rockchip RK3399 PCIe PHY");
272 	return (BUS_PROBE_DEFAULT);
273 }
274 
275 static int
276  rk_pcie_phy_attach(device_t dev)
277 {
278 	struct rk_pcie_phy_softc *sc;
279 	struct phynode_init_def phy_init;
280 	struct phynode *phynode;
281 	phandle_t node;
282 	int i, rv;
283 
284 	sc = device_get_softc(dev);
285 	sc->dev = dev;
286 	node = ofw_bus_get_node(dev);
287 	PHY_LOCK_INIT(sc);
288 
289 	if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
290 	    sc->syscon == NULL) {
291 		device_printf(dev, "cannot get syscon for device\n");
292 		rv = ENXIO;
293 		goto fail;
294 	}
295 
296 	rv = clk_set_assigned(dev, ofw_bus_get_node(dev));
297 	if (rv != 0 && rv != ENOENT) {
298 		device_printf(dev, "clk_set_assigned failed: %d\n", rv);
299 		rv = ENXIO;
300 		goto fail;
301 	}
302 
303 	rv = clk_get_by_ofw_name(sc->dev, 0, "refclk", &sc->clk_ref);
304 	if (rv != 0) {
305 		device_printf(sc->dev, "Cannot get 'refclk' clock\n");
306 		rv = ENXIO;
307 		goto fail;
308 	}
309 	rv = hwreset_get_by_ofw_name(sc->dev, 0, "phy", &sc->hwreset_phy);
310 	if (rv != 0) {
311 		device_printf(sc->dev, "Cannot get 'phy' reset\n");
312 		rv = ENXIO;
313 		goto fail;
314 	}
315 
316 	rv = hwreset_assert(sc->hwreset_phy);
317 	if (rv != 0) {
318 		device_printf(sc->dev, "Cannot assert 'phy' reset\n");
319 		rv = ENXIO;
320 		goto fail;
321 	}
322 
323 	rv = clk_enable(sc->clk_ref);
324 	if (rv != 0) {
325 		device_printf(sc->dev, "Cannot enable 'ref' clock\n");
326 		rv = ENXIO;
327 		goto fail;
328 	}
329 
330 	for (i = 0; i < MAX_LANE; i++) {
331 		phy_init.id = i;
332 		phy_init.ofw_node = node;
333 		phynode = phynode_create(dev, &rk_pcie_phy_phynode_class,
334 		&phy_init);
335 		if (phynode == NULL) {
336 			device_printf(dev, "Cannot create phy[%d]\n", i);
337 			rv = ENXIO;
338 			goto fail;
339 		}
340 		if (phynode_register(phynode) == NULL) {
341 			device_printf(dev, "Cannot register phy[%d]\n", i);
342 			rv = ENXIO;
343 			goto fail;
344 		}
345 	}
346 
347 	return (0);
348 
349 fail:
350 	return (rv);
351 }
352 
353 static device_method_t rk_pcie_phy_methods[] = {
354 	/* Device interface */
355 	DEVMETHOD(device_probe,		 rk_pcie_phy_probe),
356 	DEVMETHOD(device_attach,	 rk_pcie_phy_attach),
357 
358 	DEVMETHOD_END
359 };
360 
361 DEFINE_CLASS_0(rk_pcie_phy, rk_pcie_phy_driver, rk_pcie_phy_methods,
362     sizeof(struct rk_pcie_phy_softc));
363 
364 EARLY_DRIVER_MODULE(rk_pcie_phy, simplebus, rk_pcie_phy_driver, NULL, NULL,
365     BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
366