xref: /openbsd-src/sys/dev/fdt/imxgpc.c (revision 9fdf0c627b1fec102f212f847a6f7676c1829e65)
1*9fdf0c62Smpi /*	$OpenBSD: imxgpc.c,v 1.10 2021/10/24 17:52:26 mpi Exp $	*/
2242dcb92Spatrick /*
3242dcb92Spatrick  * Copyright (c) 2016 Mark Kettenis
4242dcb92Spatrick  *
5242dcb92Spatrick  * Permission to use, copy, modify, and distribute this software for any
6242dcb92Spatrick  * purpose with or without fee is hereby granted, provided that the above
7242dcb92Spatrick  * copyright notice and this permission notice appear in all copies.
8242dcb92Spatrick  *
9242dcb92Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10242dcb92Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11242dcb92Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12242dcb92Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13242dcb92Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14242dcb92Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15242dcb92Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16242dcb92Spatrick  */
17242dcb92Spatrick 
18242dcb92Spatrick #include <sys/param.h>
19242dcb92Spatrick #include <sys/systm.h>
20242dcb92Spatrick #include <sys/device.h>
214abb65b9Spatrick #include <sys/malloc.h>
22242dcb92Spatrick 
234abb65b9Spatrick #if defined(__arm64__)
244abb65b9Spatrick #include <machine/cpufunc.h>
254abb65b9Spatrick #endif
26242dcb92Spatrick #include <machine/fdt.h>
27242dcb92Spatrick 
28242dcb92Spatrick #include <dev/ofw/openfirm.h>
294abb65b9Spatrick #include <dev/ofw/ofw_power.h>
304abb65b9Spatrick 
314abb65b9Spatrick #define FSL_SIP_GPC			0xc2000000
324abb65b9Spatrick #define  FSL_SIP_CONFIG_GPC_PM_DOMAIN		0x03
33242dcb92Spatrick 
34242dcb92Spatrick struct imxgpc_softc {
35242dcb92Spatrick 	struct device	sc_dev;
36242dcb92Spatrick 	struct interrupt_controller sc_ic;
374abb65b9Spatrick 
384abb65b9Spatrick 	int		sc_npd;
394abb65b9Spatrick 	struct power_domain_device *sc_pd;
40242dcb92Spatrick };
41242dcb92Spatrick 
42242dcb92Spatrick int	imxgpc_match(struct device *, void *, void *);
43242dcb92Spatrick void	imxgpc_attach(struct device *, struct device *, void *);
444abb65b9Spatrick void	imxgpc_enable(void *, uint32_t *, int);
45242dcb92Spatrick 
46*9fdf0c62Smpi const struct cfattach imxgpc_ca = {
47242dcb92Spatrick 	sizeof(struct imxgpc_softc), imxgpc_match, imxgpc_attach
48242dcb92Spatrick };
49242dcb92Spatrick 
50242dcb92Spatrick struct cfdriver imxgpc_cd = {
51242dcb92Spatrick 	NULL, "imxgpc", DV_DULL
52242dcb92Spatrick };
53242dcb92Spatrick 
54242dcb92Spatrick int
imxgpc_match(struct device * parent,void * match,void * aux)55242dcb92Spatrick imxgpc_match(struct device *parent, void *match, void *aux)
56242dcb92Spatrick {
57242dcb92Spatrick 	struct fdt_attach_args *faa = aux;
58242dcb92Spatrick 
592c00674cSpatrick 	return (OF_is_compatible(faa->fa_node, "fsl,imx6q-gpc") ||
60db133697Skettenis 	    OF_is_compatible(faa->fa_node, "fsl,imx7d-gpc") ||
61529b42b2Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mm-gpc") ||
62dcf7f918Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mp-gpc") ||
632c00674cSpatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-gpc"));
64242dcb92Spatrick }
65242dcb92Spatrick 
66242dcb92Spatrick void
imxgpc_attach(struct device * parent,struct device * self,void * aux)67242dcb92Spatrick imxgpc_attach(struct device *parent, struct device *self, void *aux)
68242dcb92Spatrick {
69242dcb92Spatrick 	struct fdt_attach_args *faa = aux;
70242dcb92Spatrick 	struct imxgpc_softc *sc = (struct imxgpc_softc *)self;
714abb65b9Spatrick 	int i, node, list;
72242dcb92Spatrick 
73242dcb92Spatrick 	sc->sc_ic.ic_node = faa->fa_node;
74242dcb92Spatrick 	sc->sc_ic.ic_cookie = &sc->sc_ic;
7570e69ae2Spatrick 	sc->sc_ic.ic_establish = fdt_intr_parent_establish;
7670e69ae2Spatrick 	sc->sc_ic.ic_disestablish = fdt_intr_parent_disestablish;
77452daaedSpatrick 	sc->sc_ic.ic_barrier = intr_barrier;
7870e69ae2Spatrick 	fdt_intr_register(&sc->sc_ic);
79242dcb92Spatrick 
80242dcb92Spatrick 	printf("\n");
814abb65b9Spatrick 
82529b42b2Spatrick 	if (OF_is_compatible(faa->fa_node, "fsl,imx8mm-gpc") ||
83dcf7f918Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mp-gpc") ||
84529b42b2Spatrick 	    OF_is_compatible(faa->fa_node, "fsl,imx8mq-gpc")) {
854abb65b9Spatrick 		list = OF_child(faa->fa_node);
864abb65b9Spatrick 		if (!list)
874abb65b9Spatrick 			return;
884abb65b9Spatrick 		for (node = OF_child(list); node; node = OF_peer(node))
894abb65b9Spatrick 			sc->sc_npd++;
904abb65b9Spatrick 		if (!sc->sc_npd)
914abb65b9Spatrick 			return;
924abb65b9Spatrick 		sc->sc_pd = mallocarray(sc->sc_npd, sizeof(*sc->sc_pd),
934abb65b9Spatrick 		    M_DEVBUF, M_WAITOK);
944abb65b9Spatrick 		for (node = OF_child(list), i = 0; node;
954abb65b9Spatrick 		    node = OF_peer(node), i++){
964abb65b9Spatrick 			sc->sc_pd[i].pd_node = node;
974abb65b9Spatrick 			sc->sc_pd[i].pd_cookie = &sc->sc_pd[i];
984abb65b9Spatrick 			sc->sc_pd[i].pd_enable = imxgpc_enable;
994abb65b9Spatrick 			power_domain_register(&sc->sc_pd[i]);
1004abb65b9Spatrick 		}
1014abb65b9Spatrick 	}
1024abb65b9Spatrick }
1034abb65b9Spatrick 
1044abb65b9Spatrick void
imxgpc_enable(void * cookie,uint32_t * cells,int on)1054abb65b9Spatrick imxgpc_enable(void *cookie, uint32_t *cells, int on)
1064abb65b9Spatrick {
1074abb65b9Spatrick #if defined(__arm64__)
1084abb65b9Spatrick 	struct power_domain_device *pd = cookie;
1094abb65b9Spatrick 	int domain;
1104abb65b9Spatrick 
1113cc1f9efSpatrick 	power_domain_enable(pd->pd_node);
1123cc1f9efSpatrick 
1134abb65b9Spatrick 	domain = OF_getpropint(pd->pd_node, "reg", 0);
1144abb65b9Spatrick 
1154abb65b9Spatrick 	/* Set up power domain */
1164abb65b9Spatrick 	smc_call(FSL_SIP_GPC, FSL_SIP_CONFIG_GPC_PM_DOMAIN,
1174abb65b9Spatrick 	    domain, on);
1184abb65b9Spatrick #endif
119242dcb92Spatrick }
120