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/clk/clk.h>
48#include <dev/phy/phy.h>
49#include <dev/phy/phy_internal.h>
50#include <dev/syscon/syscon.h>
51#include <dev/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
75static struct ofw_compat_data compat_data[] = {
76	{"rockchip,rk3399-pcie-phy",	1},
77	{NULL,				0}
78};
79
80struct 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
103static void
104cfg_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
121static uint32_t
122cfg_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
133static int
134rk_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
204static int
205rk_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
231static int
232rk_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. */
252static phynode_method_t rk_pcie_phy_phynode_methods[] = {
253	PHYNODEMETHOD(phynode_enable,		 rk_pcie_phy_enable),
254
255	PHYNODEMETHOD_END
256};
257
258DEFINE_CLASS_1( rk_pcie_phy_phynode, rk_pcie_phy_phynode_class,
259    rk_pcie_phy_phynode_methods, 0, phynode_class);
260
261static 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
275static 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
349fail:
350	return (rv);
351}
352
353static 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
361DEFINE_CLASS_0(rk_pcie_phy, rk_pcie_phy_driver, rk_pcie_phy_methods,
362    sizeof(struct rk_pcie_phy_softc));
363
364EARLY_DRIVER_MODULE(rk_pcie_phy, simplebus, rk_pcie_phy_driver, NULL, NULL,
365    BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE);
366