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