xref: /openbsd-src/sys/dev/fdt/imxsrc.c (revision 37c734d33dee3fea3589b7f939107ac40734e75e)
1*37c734d3Snaddy /* $OpenBSD: imxsrc.c,v 1.6 2022/06/28 23:43:12 naddy Exp $ */
2b61f5f14Spatrick /*
3b61f5f14Spatrick  * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se>
4b61f5f14Spatrick  *
5b61f5f14Spatrick  * Permission to use, copy, modify, and distribute this software for any
6b61f5f14Spatrick  * purpose with or without fee is hereby granted, provided that the above
7b61f5f14Spatrick  * copyright notice and this permission notice appear in all copies.
8b61f5f14Spatrick  *
9b61f5f14Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10b61f5f14Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11b61f5f14Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12b61f5f14Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13b61f5f14Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14b61f5f14Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15b61f5f14Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16b61f5f14Spatrick  */
17b61f5f14Spatrick 
18b61f5f14Spatrick #include <sys/types.h>
19b61f5f14Spatrick #include <sys/systm.h>
20b61f5f14Spatrick #include <sys/device.h>
21b61f5f14Spatrick #include <sys/malloc.h>
22b61f5f14Spatrick 
23a3745ba7Skettenis #include <machine/bus.h>
24b61f5f14Spatrick #include <machine/fdt.h>
25b61f5f14Spatrick 
26b61f5f14Spatrick #include <dev/ofw/openfirm.h>
27b61f5f14Spatrick #include <dev/ofw/ofw_clock.h>
28b61f5f14Spatrick #include <dev/ofw/fdt.h>
29b61f5f14Spatrick 
30a3745ba7Skettenis #define IMX51_RESET_GPU				0
31a3745ba7Skettenis #define IMX51_RESET_VPU				1
32a3745ba7Skettenis #define IMX51_RESET_IPU1			2
33a3745ba7Skettenis #define IMX51_RESET_OPEN_VG			3
34a3745ba7Skettenis #define IMX51_RESET_IPU2			4
35a3745ba7Skettenis 
36a3745ba7Skettenis #define SRC_SCR					0x00
37a3745ba7Skettenis #define  SRC_SCR_SW_GPU_RST			(1 << 1)
38a3745ba7Skettenis #define  SRC_SCR_SW_VPU_RST			(1 << 2)
39a3745ba7Skettenis #define  SRC_SCR_SW_IPU1_RST			(1 << 3)
40a3745ba7Skettenis #define  SRC_SCR_SW_OPEN_VG_RST			(1 << 4)
41a3745ba7Skettenis #define  SRC_SCR_SW_IPU2_RST			(1 << 12)
42a3745ba7Skettenis 
43d5982ef3Spatrick #define IMX8M_RESET_PCIEPHY			26
44d5982ef3Spatrick #define IMX8M_RESET_PCIEPHY_PERST		27
45d5982ef3Spatrick #define IMX8M_RESET_PCIE_CTRL_APPS_EN		28
46d5982ef3Spatrick #define IMX8M_RESET_PCIE_CTRL_APPS_TURNOFF	29
47d5982ef3Spatrick #define IMX8M_RESET_PCIE2PHY			34
48d5982ef3Spatrick #define IMX8M_RESET_PCIE2PHY_PERST		35
49d5982ef3Spatrick #define IMX8M_RESET_PCIE2_CTRL_APPS_EN		36
50b61f5f14Spatrick #define IMX8M_RESET_PCIE2_CTRL_APPS_TURNOFF	37
51b61f5f14Spatrick 
52b61f5f14Spatrick #define SRC_PCIE1_RCR				0x2c
53b61f5f14Spatrick #define SRC_PCIE2_RCR				0x48
54b61f5f14Spatrick #define  SRC_PCIE_RCR_PCIEPHY_G_RST			(1 << 1)
55b61f5f14Spatrick #define  SRC_PCIE_RCR_PCIEPHY_BTN			(1 << 2)
56b61f5f14Spatrick #define  SRC_PCIE_RCR_PCIEPHY_PERST			(1 << 3)
57b61f5f14Spatrick #define  SRC_PCIE_RCR_PCIE_CTRL_APPS_EN			(1 << 6)
58b61f5f14Spatrick #define  SRC_PCIE_RCR_PCIE_CTRL_APPS_TURNOFF		(1 << 11)
59b61f5f14Spatrick 
60b61f5f14Spatrick struct imxsrc_reset {
61b61f5f14Spatrick 	uint32_t	reg;
62b61f5f14Spatrick 	uint32_t	bit;
63b61f5f14Spatrick };
64b61f5f14Spatrick 
65*37c734d3Snaddy const struct imxsrc_reset imx51_resets[] = {
66a3745ba7Skettenis 	[IMX51_RESET_GPU] = { SRC_SCR, SRC_SCR_SW_GPU_RST },
67a3745ba7Skettenis 	[IMX51_RESET_VPU] = { SRC_SCR, SRC_SCR_SW_VPU_RST },
68a3745ba7Skettenis 	[IMX51_RESET_IPU1] = { SRC_SCR, SRC_SCR_SW_IPU1_RST },
69a3745ba7Skettenis 	[IMX51_RESET_OPEN_VG] = { SRC_SCR, SRC_SCR_SW_OPEN_VG_RST },
70a3745ba7Skettenis 	[IMX51_RESET_IPU2] = { SRC_SCR, SRC_SCR_SW_IPU2_RST },
71a3745ba7Skettenis };
72a3745ba7Skettenis 
73*37c734d3Snaddy const struct imxsrc_reset imx8m_resets[] = {
74a3745ba7Skettenis 	[IMX8M_RESET_PCIEPHY] = { SRC_PCIE1_RCR,
75a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIEPHY_G_RST | SRC_PCIE_RCR_PCIEPHY_BTN },
76a3745ba7Skettenis 	[IMX8M_RESET_PCIEPHY_PERST] = { SRC_PCIE1_RCR,
77a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIEPHY_PERST },
78a3745ba7Skettenis 	[IMX8M_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIE1_RCR,
79a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIE_CTRL_APPS_EN },
80a3745ba7Skettenis 	[IMX8M_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIE1_RCR,
81a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIE_CTRL_APPS_TURNOFF },
82a3745ba7Skettenis 	[IMX8M_RESET_PCIE2PHY] = { SRC_PCIE2_RCR,
83a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIEPHY_G_RST | SRC_PCIE_RCR_PCIEPHY_BTN },
84a3745ba7Skettenis 	[IMX8M_RESET_PCIE2PHY_PERST] = { SRC_PCIE2_RCR,
85a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIEPHY_PERST },
86a3745ba7Skettenis 	[IMX8M_RESET_PCIE2_CTRL_APPS_EN] = { SRC_PCIE2_RCR,
87a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIE_CTRL_APPS_EN },
88a3745ba7Skettenis 	[IMX8M_RESET_PCIE2_CTRL_APPS_TURNOFF] = { SRC_PCIE2_RCR,
89a3745ba7Skettenis 	    SRC_PCIE_RCR_PCIE_CTRL_APPS_TURNOFF },
90b61f5f14Spatrick };
91b61f5f14Spatrick 
92b61f5f14Spatrick #define HREAD4(sc, reg)							\
93b61f5f14Spatrick 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
94b61f5f14Spatrick #define HWRITE4(sc, reg, val)						\
95b61f5f14Spatrick 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
96b61f5f14Spatrick #define HSET4(sc, reg, bits)						\
97b61f5f14Spatrick 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
98b61f5f14Spatrick #define HCLR4(sc, reg, bits)						\
99b61f5f14Spatrick 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
100b61f5f14Spatrick 
101b61f5f14Spatrick struct imxsrc_softc {
102b61f5f14Spatrick 	struct device		 sc_dev;
103b61f5f14Spatrick 	bus_space_tag_t		 sc_iot;
104b61f5f14Spatrick 	bus_space_handle_t	 sc_ioh;
105b61f5f14Spatrick 	struct reset_device	 sc_rd;
106*37c734d3Snaddy 	const struct imxsrc_reset *sc_resets;
107b61f5f14Spatrick 	int			 sc_nresets;
108b61f5f14Spatrick };
109b61f5f14Spatrick 
110b61f5f14Spatrick int imxsrc_match(struct device *, void *, void *);
111b61f5f14Spatrick void imxsrc_attach(struct device *, struct device *, void *);
112b61f5f14Spatrick void imxsrc_reset(void *, uint32_t *, int);
113b61f5f14Spatrick 
1149fdf0c62Smpi const struct cfattach	imxsrc_ca = {
115b61f5f14Spatrick 	sizeof (struct imxsrc_softc), imxsrc_match, imxsrc_attach
116b61f5f14Spatrick };
117b61f5f14Spatrick 
118b61f5f14Spatrick struct cfdriver imxsrc_cd = {
119b61f5f14Spatrick 	NULL, "imxsrc", DV_DULL
120b61f5f14Spatrick };
121b61f5f14Spatrick 
122b61f5f14Spatrick int
imxsrc_match(struct device * parent,void * match,void * aux)123b61f5f14Spatrick imxsrc_match(struct device *parent, void *match, void *aux)
124b61f5f14Spatrick {
125b61f5f14Spatrick 	struct fdt_attach_args *faa = aux;
126b61f5f14Spatrick 
127a3745ba7Skettenis 	if (OF_is_compatible(faa->fa_node, "fsl,imx51-src") ||
128a3745ba7Skettenis 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-src"))
1298d9412beSpatrick 		return 10;	/* Must beat syscon(4). */
1308d9412beSpatrick 
1318d9412beSpatrick 	return 0;
132b61f5f14Spatrick }
133b61f5f14Spatrick 
134b61f5f14Spatrick void
imxsrc_attach(struct device * parent,struct device * self,void * aux)135b61f5f14Spatrick imxsrc_attach(struct device *parent, struct device *self, void *aux)
136b61f5f14Spatrick {
137b61f5f14Spatrick 	struct imxsrc_softc *sc = (struct imxsrc_softc *)self;
138b61f5f14Spatrick 	struct fdt_attach_args *faa = aux;
139b61f5f14Spatrick 
140b61f5f14Spatrick 	KASSERT(faa->fa_nreg >= 1);
141b61f5f14Spatrick 
142b61f5f14Spatrick 	sc->sc_iot = faa->fa_iot;
143b61f5f14Spatrick 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
144b61f5f14Spatrick 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
145b61f5f14Spatrick 		panic("%s: bus_space_map failed!", __func__);
146b61f5f14Spatrick 
147a3745ba7Skettenis 	if (OF_is_compatible(faa->fa_node, "fsl,imx51-src")) {
148a3745ba7Skettenis 		sc->sc_resets = imx51_resets;
149a3745ba7Skettenis 		sc->sc_nresets = nitems(imx51_resets);
150a3745ba7Skettenis 	} else {
151b61f5f14Spatrick 		sc->sc_resets = imx8m_resets;
152b61f5f14Spatrick 		sc->sc_nresets = nitems(imx8m_resets);
153a3745ba7Skettenis 	}
154b61f5f14Spatrick 
155b61f5f14Spatrick 	sc->sc_rd.rd_node = faa->fa_node;
156b61f5f14Spatrick 	sc->sc_rd.rd_cookie = sc;
157b61f5f14Spatrick 	sc->sc_rd.rd_reset = imxsrc_reset;
158b61f5f14Spatrick 	reset_register(&sc->sc_rd);
159b61f5f14Spatrick 
160b61f5f14Spatrick 	printf("\n");
161b61f5f14Spatrick }
162b61f5f14Spatrick 
163b61f5f14Spatrick void
imxsrc_reset(void * cookie,uint32_t * cells,int assert)164b61f5f14Spatrick imxsrc_reset(void *cookie, uint32_t *cells, int assert)
165b61f5f14Spatrick {
166b61f5f14Spatrick 	struct imxsrc_softc *sc = cookie;
167b61f5f14Spatrick 	int idx = cells[0];
168b61f5f14Spatrick 	uint32_t reg;
169b61f5f14Spatrick 
170b61f5f14Spatrick 	if (idx >= sc->sc_nresets || sc->sc_resets[idx].bit == 0) {
171b61f5f14Spatrick 		printf("%s: 0x%08x\n", __func__, idx);
172b61f5f14Spatrick 		return;
173b61f5f14Spatrick 	}
174b61f5f14Spatrick 
175b61f5f14Spatrick 	switch (idx) {
176b61f5f14Spatrick 	case IMX8M_RESET_PCIEPHY:
177b61f5f14Spatrick 	case IMX8M_RESET_PCIE2PHY:
178b61f5f14Spatrick 		if (!assert)
179b61f5f14Spatrick 			delay(10);
180b61f5f14Spatrick 		break;
181b61f5f14Spatrick 	case IMX8M_RESET_PCIE_CTRL_APPS_EN:
182b61f5f14Spatrick 	case IMX8M_RESET_PCIE2_CTRL_APPS_EN:
183b61f5f14Spatrick 		assert = !assert;
184b61f5f14Spatrick 		break;
185b61f5f14Spatrick 	}
186b61f5f14Spatrick 
187b61f5f14Spatrick 	reg = HREAD4(sc, sc->sc_resets[idx].reg);
188b61f5f14Spatrick 	if (assert)
189b61f5f14Spatrick 		reg |= sc->sc_resets[idx].bit;
190b61f5f14Spatrick 	else
191b61f5f14Spatrick 		reg &= ~sc->sc_resets[idx].bit;
192b61f5f14Spatrick 	HWRITE4(sc, sc->sc_resets[idx].reg, reg);
193b61f5f14Spatrick }
194