1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021, 2022 Soren Schmidt <sos@deepcore.dk>
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 *    without modification, immediately at the beginning of the file.
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 ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/endian.h>
32#include <sys/kernel.h>
33#include <sys/module.h>
34#include <sys/bus.h>
35#include <sys/proc.h>
36#include <sys/rman.h>
37#include <sys/intr.h>
38#include <sys/mutex.h>
39#include <sys/gpio.h>
40
41#include <dev/gpio/gpiobusvar.h>
42#include <dev/ofw/ofw_bus.h>
43#include <dev/ofw/ofw_bus_subr.h>
44#include <dev/ofw/ofw_pci.h>
45#include <dev/ofw/ofwpci.h>
46
47#include <dev/pci/pcivar.h>
48#include <dev/pci/pcireg.h>
49#include <dev/pci/pcib_private.h>
50#include <dev/pci/pci_dw.h>
51
52#include <dev/clk/clk.h>
53#include <dev/phy/phy.h>
54#include <dev/regulator/regulator.h>
55#include <dev/hwreset/hwreset.h>
56
57#include <machine/bus.h>
58#include <machine/intr.h>
59
60#include <vm/vm.h>
61#include <vm/vm_extern.h>
62#include <vm/vm_kern.h>
63#include <vm/pmap.h>
64
65#include "pcib_if.h"
66
67/* APB Registers */
68#define	PCIE_CLIENT_GENERAL_CON		0x0000
69#define	 DEVICE_TYPE_MASK		0x00f0
70#define	 DEVICE_TYPE_RC			(1<<6)
71#define	 LINK_REQ_RST_GRT		(1<<3)
72#define	 LTSSM_ENABLE			(1<<2)
73#define	PCIE_CLIENT_INTR_MASK_MSG_RX	0x0018
74#define	PCIE_CLIENT_INTR_MASK_LEGACY	0x001c
75#define	PCIE_CLIENT_INTR_MASK_ERR	0x0020
76#define	PCIE_CLIENT_INTR_MASK_MISC	0x0024
77#define	PCIE_CLIENT_INTR_MASK_PMC	0x0028
78#define	PCIE_CLIENT_GENERAL_DEBUG_INFO	0x0104
79#define	PCIE_CLIENT_HOT_RESET_CTRL	0x0180
80#define	 APP_LSSTM_ENABLE_ENHANCE	(1<<4)
81#define	PCIE_CLIENT_LTSSM_STATUS	0x0300
82#define	 RDLH_LINK_UP			(1<<17)
83#define	 SMLH_LINK_UP			(1<<16)
84#define	 SMLH_LTSSM_STATE_MASK		0x003f
85#define	 SMLH_LTSSM_STATE_LINK_UP	((1<<4) | (1<<0))
86
87struct rk3568_pcie_softc {
88	struct pci_dw_softc		dw_sc;  /* Must be first */
89	device_t			dev;
90	int				apb_rid;
91	struct resource			*apb_res;
92	int				dbi_rid;
93	struct resource			*dbi_res;
94	int				irq_rid;
95	struct resource			*irq_res;
96	void				*irq_handle;
97	phandle_t			node;
98	struct gpiobus_pin		*reset_gpio;
99	clk_t				aclk_mst, aclk_slv, aclk_dbi, pclk, aux;
100	regulator_t			regulator;
101	hwreset_t			hwreset;
102	phy_t				phy;
103};
104
105static struct ofw_compat_data compat_data[] = {
106	{"rockchip,rk3568-pcie",	1},
107	{NULL,				0}
108};
109
110
111static void
112rk3568_intr(void *data)
113{
114	struct rk3568_pcie_softc *sc = data;
115
116	device_printf(sc->dev, "INTERRUPT!!\n");
117}
118
119static int
120rk3568_pcie_get_link(device_t dev, bool *status)
121{
122	struct rk3568_pcie_softc *sc = device_get_softc(dev);
123	uint32_t val;
124
125	val = bus_read_4(sc->apb_res, PCIE_CLIENT_LTSSM_STATUS);
126	if (((val & (RDLH_LINK_UP | SMLH_LINK_UP)) ==
127	    (RDLH_LINK_UP | SMLH_LINK_UP)) &&
128	    ((val & SMLH_LTSSM_STATE_MASK) == SMLH_LTSSM_STATE_LINK_UP))
129		*status = true;
130	else
131		*status = false;
132	return (0);
133}
134
135static int
136rk3568_pcie_init_soc(device_t dev)
137{
138	struct rk3568_pcie_softc *sc = device_get_softc(dev);
139	int err, count;
140	bool status;
141
142	/* Assert reset */
143	if (hwreset_assert(sc->hwreset))
144		device_printf(dev, "Could not assert reset\n");
145
146	/* Powerup PCIe */
147	if (regulator_enable(sc->regulator))
148		device_printf(dev, "Cannot enable regulator\n");
149
150	/* Enable PHY */
151	if (phy_enable(sc->phy))
152		device_printf(dev, "Cannot enable phy\n");
153
154	/* Deassert reset */
155	if (hwreset_deassert(sc->hwreset))
156		device_printf(dev, "Could not deassert reset\n");
157
158	/* Enable clocks */
159	if ((err = clk_enable(sc->aclk_mst))) {
160		device_printf(dev, "Could not enable aclk_mst clk\n");
161		return (ENXIO);
162	}
163	if ((err = clk_enable(sc->aclk_slv))) {
164		device_printf(dev, "Could not enable aclk_slv clk\n");
165		return (ENXIO);
166	}
167	if ((err = clk_enable(sc->aclk_dbi))) {
168		device_printf(dev, "Could not enable aclk_dbi clk\n");
169		return (ENXIO);
170	}
171	if ((err = clk_enable(sc->pclk))) {
172		device_printf(dev, "Could not enable pclk clk\n");
173		return (ENXIO);
174	}
175	if ((err = clk_enable(sc->aux))) {
176		device_printf(dev, "Could not enable aux clk\n");
177		return (ENXIO);
178	}
179
180	/* Set Root Complex (RC) mode */
181	bus_write_4(sc->apb_res, PCIE_CLIENT_HOT_RESET_CTRL,
182	    (APP_LSSTM_ENABLE_ENHANCE << 16) | APP_LSSTM_ENABLE_ENHANCE);
183	bus_write_4(sc->apb_res, PCIE_CLIENT_GENERAL_CON,
184	    (DEVICE_TYPE_MASK << 16) | DEVICE_TYPE_RC);
185
186	/* Assert reset PCIe */
187	if ((err = gpio_pin_set_active(sc->reset_gpio, false)))
188		device_printf(dev, "reset_gpio set failed\n");
189
190	/* Start Link Training and Status State Machine (LTSSM) */
191	bus_write_4(sc->apb_res, PCIE_CLIENT_GENERAL_CON,
192	    (LINK_REQ_RST_GRT | LTSSM_ENABLE) << 16 |
193	    (LINK_REQ_RST_GRT | LTSSM_ENABLE));
194	DELAY(100000);
195
196	/* Release reset */
197	if ((err = gpio_pin_set_active(sc->reset_gpio, true)))
198		device_printf(dev, "reset_gpio release failed\n");
199
200	/* Wait for link up/stable */
201	for (count = 20; count; count--) {
202		rk3568_pcie_get_link(dev, &status);
203		if (status)
204			break;
205		DELAY(100000);
206		if (count == 0) {
207			device_printf(dev, "Link up timeout!\n");
208			return (ENXIO);
209		}
210	}
211
212	if ((err = pci_dw_init(dev)))
213		return (ENXIO);
214
215	/* Delay to have things settle */
216	DELAY(100000);
217
218	/* Enable all MSG interrupts */
219	bus_write_4(sc->apb_res, PCIE_CLIENT_INTR_MASK_MSG_RX, 0x7fff0000);
220
221	/* Enable all Legacy interrupts */
222	bus_write_4(sc->apb_res, PCIE_CLIENT_INTR_MASK_LEGACY, 0x00ff0000);
223
224	/* Enable all Error interrupts */
225	bus_write_4(sc->apb_res, PCIE_CLIENT_INTR_MASK_ERR, 0x0fff0000);
226
227	return (0);
228}
229
230static int
231rk3568_pcie_detach(device_t dev)
232{
233	struct rk3568_pcie_softc *sc = device_get_softc(dev);
234
235	/* Release allocated resources */
236	if (sc->irq_handle)
237		bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
238	if (sc->phy)
239		phy_release(sc->phy);
240	if (sc->aux)
241		clk_release(sc->aux);
242	if (sc->pclk)
243		clk_release(sc->pclk);
244	if (sc->aclk_dbi)
245		clk_release(sc->aclk_dbi);
246	if (sc->aclk_slv)
247		clk_release(sc->aclk_slv);
248	if (sc->aclk_mst)
249		clk_release(sc->aclk_mst);
250	if (sc->hwreset)
251		hwreset_release(sc->hwreset);
252	if (sc->regulator)
253		regulator_release(sc->regulator);
254	if (sc->irq_res)
255		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
256		    sc->irq_res);
257	if (sc->dbi_res)
258		bus_release_resource(dev, SYS_RES_MEMORY, sc->dbi_rid,
259		    sc->dbi_res);
260	if (sc->apb_res)
261		bus_release_resource(dev, SYS_RES_MEMORY, sc->apb_rid,
262		    sc->apb_res);
263	return (0);
264}
265
266static int
267rk3568_pcie_attach(device_t dev)
268{
269	struct rk3568_pcie_softc *sc = device_get_softc(dev);
270	int error;
271
272	sc->dev = dev;
273	sc->node = ofw_bus_get_node(dev);
274
275	/* Setup resources */
276	if ((error = ofw_bus_find_string_index(sc->node, "reg-names", "apb",
277	    &sc->apb_rid))) {
278		device_printf(dev, "Cannot get APB memory: %d\n", error);
279		goto fail;
280	}
281	if (!(sc->apb_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
282	    &sc->apb_rid, RF_ACTIVE))) {
283		device_printf(dev, "Cannot allocate APB resource\n");
284		goto fail;
285	}
286	if ((error = ofw_bus_find_string_index(sc->node, "reg-names", "dbi",
287	    &sc->dbi_rid))) {
288		device_printf(dev, "Cannot get DBI memory: %d\n", error);
289		goto fail;
290	}
291	if (!(sc->dw_sc.dbi_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
292	    &sc->dbi_rid, RF_ACTIVE))) {
293		device_printf(dev, "Cannot allocate DBI resource\n");
294		goto fail;
295	}
296
297	if (!(sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
298	    &sc->irq_rid, RF_ACTIVE | RF_SHAREABLE))) {
299		device_printf(dev, "Cannot allocate IRQ resource\n");
300		goto fail;
301	}
302
303	/* Get regulator if present */
304	if (regulator_get_by_ofw_property(dev, 0, "vpcie3v3-supply",
305	    &sc->regulator)) {
306		device_printf(dev, "Cannot get regulator\n");
307		goto fail;
308	}
309
310	/* Get reset */
311	if (hwreset_get_by_ofw_name(dev, 0, "pipe", &sc->hwreset)) {
312		device_printf(dev, "Can not get reset\n");
313		goto fail;
314	}
315
316	/* Get GPIO reset */
317	if (OF_hasprop(sc->node, "reset-gpios")) {
318		if (gpio_pin_get_by_ofw_property(dev, sc->node, "reset-gpios",
319		    &sc->reset_gpio)) {
320			device_printf(dev, "Cannot get reset-gpios\n");
321			goto fail;
322		}
323		gpio_pin_setflags(sc->reset_gpio, GPIO_PIN_OUTPUT);
324		gpio_pin_set_active(sc->reset_gpio, true);
325	}
326
327	/* Get clocks */
328	if (clk_get_by_ofw_name(dev, 0, "aclk_mst", &sc->aclk_mst)) {
329		device_printf(dev, "Can not get aclk_mst clk\n");
330		goto fail;
331	}
332	if (clk_get_by_ofw_name(dev, 0, "aclk_slv", &sc->aclk_slv)) {
333		device_printf(dev, "Can not get aclk_slv clk\n");
334		goto fail;
335	}
336	if (clk_get_by_ofw_name(dev, 0, "aclk_dbi", &sc->aclk_dbi)) {
337		device_printf(dev, "Can not get aclk_dbi clk\n");
338		goto fail;
339	}
340	if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->pclk)) {
341		device_printf(dev, "Can not get pclk clk\n");
342		goto fail;
343	}
344	if (clk_get_by_ofw_name(dev, 0, "aux", &sc->aux)) {
345		device_printf(dev, "Can not get aux clk\n");
346		goto fail;
347	}
348
349	/* Get PHY */
350	if (phy_get_by_ofw_name(dev, 0, "pcie-phy", &sc->phy)) {
351		device_printf(dev, "Cannot get 'pcie-phy'\n");
352		goto fail;
353	}
354
355	if ((error = rk3568_pcie_init_soc(dev)))
356		goto fail;
357
358	/* Enable interrupt */
359	if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
360	    NULL, rk3568_intr, sc, &sc->irq_handle))) {
361		device_printf(dev, "unable to setup interrupt\n");
362		goto fail;
363	}
364
365	return (bus_generic_attach(dev));
366fail:
367	rk3568_pcie_detach(dev);
368	return (ENXIO);
369}
370
371static int
372rk3568_pcie_probe(device_t dev)
373{
374
375	if (!ofw_bus_status_okay(dev))
376		return (ENXIO);
377	if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
378		return (ENXIO);
379	device_set_desc(dev, "RockChip RK3568 PCI-express controller");
380	return (BUS_PROBE_DEFAULT);
381}
382
383static device_method_t rk3568_pcie_methods[] = {
384	/* Device interface */
385	DEVMETHOD(device_probe,		rk3568_pcie_probe),
386	DEVMETHOD(device_attach,	rk3568_pcie_attach),
387	DEVMETHOD(device_detach,	rk3568_pcie_detach),
388
389	/* PCI DW interface */
390	DEVMETHOD(pci_dw_get_link,	rk3568_pcie_get_link),
391
392	DEVMETHOD_END
393};
394
395DEFINE_CLASS_1(pcib, rk3568_pcie_driver, rk3568_pcie_methods,
396    sizeof(struct rk3568_pcie_softc), pci_dw_driver);
397DRIVER_MODULE(rk3568_pcie, simplebus, rk3568_pcie_driver, NULL, NULL);
398