xref: /openbsd-src/sys/dev/fdt/sxirintc.c (revision cb45c7e573b2e95edf879d1c8cf99aff8fd144b5)
1 /*	$OpenBSD: sxirintc.c,v 1.1 2022/07/14 19:06:29 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
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 
22 #include <machine/bus.h>
23 #include <machine/fdt.h>
24 
25 #include <dev/ofw/openfirm.h>
26 #include <dev/ofw/fdt.h>
27 
28 #define RINTC_IRQ_PENDING	0x10
29 #define RINTC_IRQ_ENABLE	0x40
30 #define  RINTC_IRQ_ENABLE_NMI	(1 << 0)
31 
32 #define HREAD4(sc, reg)							\
33 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
34 #define HWRITE4(sc, reg, val)						\
35 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
36 #define HSET4(sc, reg, bits)						\
37 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
38 #define HCLR4(sc, reg, bits)						\
39 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
40 
41 struct sxirintc_softc {
42 	struct device		sc_dev;
43 	bus_space_tag_t		sc_iot;
44 	bus_space_handle_t	sc_ioh;
45 };
46 
47 int	sxirintc_match(struct device *, void *, void *);
48 void	sxirintc_attach(struct device *, struct device *, void *);
49 int	sxirintc_activate(struct device *, int);
50 
51 const struct cfattach sxirintc_ca = {
52 	sizeof(struct sxirintc_softc), sxirintc_match, sxirintc_attach,
53 	NULL, sxirintc_activate
54 };
55 
56 struct cfdriver sxirintc_cd = {
57 	NULL, "sxirintc", DV_DULL
58 };
59 
60 int
sxirintc_match(struct device * parent,void * match,void * aux)61 sxirintc_match(struct device *parent, void *match, void *aux)
62 {
63 	struct fdt_attach_args *faa = aux;
64 
65 	return OF_is_compatible(faa->fa_node, "allwinner,sun6i-a31-r-intc");
66 }
67 
68 void
sxirintc_attach(struct device * parent,struct device * self,void * aux)69 sxirintc_attach(struct device *parent, struct device *self, void *aux)
70 {
71 	struct sxirintc_softc *sc = (struct sxirintc_softc *)self;
72 	struct fdt_attach_args *faa = aux;
73 
74 	if (faa->fa_nreg < 1) {
75 		printf(": no registers\n");
76 		return;
77 	}
78 
79 	sc->sc_iot = faa->fa_iot;
80 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
81 	    faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
82 		printf(": can't map registers\n");
83 		return;
84 	}
85 
86 	printf("\n");
87 }
88 
89 int
sxirintc_activate(struct device * self,int act)90 sxirintc_activate(struct device *self, int act)
91 {
92 	struct sxirintc_softc *sc = (struct sxirintc_softc *)self;
93 
94 	/*
95 	 * Typically the "NMI" interrupt is controlled by the PMIC.
96 	 * This interrupt is routed in parallel to the GIC and the
97 	 * ARISC coprocessor.  Enable this interrupt when we suspend
98 	 * such that the firmware running on the ARISC coprocessor can
99 	 * wake up the SoC when the PMIC triggers this interrupt.
100 	 */
101 
102 	switch (act) {
103 	case DVACT_SUSPEND:
104 		HWRITE4(sc, RINTC_IRQ_PENDING, ~0);
105 		HSET4(sc, RINTC_IRQ_ENABLE, RINTC_IRQ_ENABLE_NMI);
106 		break;
107 	case DVACT_RESUME:
108 		HCLR4(sc, RINTC_IRQ_ENABLE, RINTC_IRQ_ENABLE_NMI);
109 		break;
110 	}
111 
112 	return 0;
113 }
114