xref: /openbsd-src/sys/dev/fdt/imxgpc.c (revision 4b70baf6e17fc8b27fc1f7fa7929335753fa94c3)
1 /*	$OpenBSD: imxgpc.c,v 1.5 2019/04/01 08:40:37 patrick Exp $	*/
2 /*
3  * Copyright (c) 2016 Mark Kettenis
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #if defined(__arm64__)
24 #include <machine/cpufunc.h>
25 #endif
26 #include <machine/fdt.h>
27 
28 #include <dev/ofw/openfirm.h>
29 #include <dev/ofw/ofw_power.h>
30 
31 #define FSL_SIP_GPC			0xc2000000
32 #define  FSL_SIP_CONFIG_GPC_PM_DOMAIN		0x03
33 
34 struct imxgpc_softc {
35 	struct device	sc_dev;
36 	struct interrupt_controller sc_ic;
37 
38 	int		sc_npd;
39 	struct power_domain_device *sc_pd;
40 };
41 
42 int	imxgpc_match(struct device *, void *, void *);
43 void	imxgpc_attach(struct device *, struct device *, void *);
44 void	imxgpc_enable(void *, uint32_t *, int);
45 
46 struct cfattach imxgpc_ca = {
47 	sizeof(struct imxgpc_softc), imxgpc_match, imxgpc_attach
48 };
49 
50 struct cfdriver imxgpc_cd = {
51 	NULL, "imxgpc", DV_DULL
52 };
53 
54 int
55 imxgpc_match(struct device *parent, void *match, void *aux)
56 {
57 	struct fdt_attach_args *faa = aux;
58 
59 	return (OF_is_compatible(faa->fa_node, "fsl,imx6q-gpc") ||
60 	    OF_is_compatible(faa->fa_node, "fsl,imx7d-gpc") ||
61 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-gpc"));
62 }
63 
64 void
65 imxgpc_attach(struct device *parent, struct device *self, void *aux)
66 {
67 	struct fdt_attach_args *faa = aux;
68 	struct imxgpc_softc *sc = (struct imxgpc_softc *)self;
69 	int i, node, list;
70 
71 	sc->sc_ic.ic_node = faa->fa_node;
72 	sc->sc_ic.ic_cookie = &sc->sc_ic;
73 	sc->sc_ic.ic_establish = fdt_intr_parent_establish;
74 	sc->sc_ic.ic_disestablish = fdt_intr_parent_disestablish;
75 	fdt_intr_register(&sc->sc_ic);
76 
77 	printf("\n");
78 
79 	if (OF_is_compatible(faa->fa_node, "fsl,imx8mq-gpc")) {
80 		list = OF_child(faa->fa_node);
81 		if (!list)
82 			return;
83 		for (node = OF_child(list); node; node = OF_peer(node))
84 			sc->sc_npd++;
85 		if (!sc->sc_npd)
86 			return;
87 		sc->sc_pd = mallocarray(sc->sc_npd, sizeof(*sc->sc_pd),
88 		    M_DEVBUF, M_WAITOK);
89 		for (node = OF_child(list), i = 0; node;
90 		    node = OF_peer(node), i++){
91 			sc->sc_pd[i].pd_node = node;
92 			sc->sc_pd[i].pd_cookie = &sc->sc_pd[i];
93 			sc->sc_pd[i].pd_enable = imxgpc_enable;
94 			power_domain_register(&sc->sc_pd[i]);
95 		}
96 	}
97 }
98 
99 void
100 imxgpc_enable(void *cookie, uint32_t *cells, int on)
101 {
102 #if defined(__arm64__)
103 	struct power_domain_device *pd = cookie;
104 	int domain;
105 
106 	domain = OF_getpropint(pd->pd_node, "reg", 0);
107 
108 	/* Set up power domain */
109 	smc_call(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN,
110 	    domain, on);
111 #endif
112 }
113