xref: /openbsd-src/sys/arch/arm64/arm64/acpi_machdep.c (revision 28d09237077354eff565f9f3ef991865a249ce6c)
1 /*	$OpenBSD: acpi_machdep.c,v 1.22 2024/05/22 05:51:49 jsg Exp $	*/
2 /*
3  * Copyright (c) 2018 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/device.h>
20 #include <sys/malloc.h>
21 #include <sys/systm.h>
22 
23 #include <uvm/uvm_extern.h>
24 
25 #include <machine/apmvar.h>
26 #include <machine/bus.h>
27 #include <machine/fdt.h>
28 
29 #include <dev/ofw/openfirm.h>
30 #include <dev/ofw/fdt.h>
31 
32 #include <dev/acpi/acpivar.h>
33 #include <dev/acpi/dsdt.h>
34 
35 #include <arm64/dev/acpiiort.h>
36 
37 #include "apm.h"
38 
39 int	pwr_action = 1;
40 
41 int	acpi_fdt_match(struct device *, void *, void *);
42 void	acpi_fdt_attach(struct device *, struct device *, void *);
43 
44 const struct cfattach acpi_fdt_ca = {
45 	sizeof(struct acpi_softc), acpi_fdt_match, acpi_fdt_attach
46 };
47 
48 int
acpi_fdt_match(struct device * parent,void * match,void * aux)49 acpi_fdt_match(struct device *parent, void *match, void *aux)
50 {
51 	struct fdt_attach_args *faa = aux;
52 
53 	return OF_is_compatible(faa->fa_node, "openbsd,acpi-5.0");
54 }
55 
56 void
acpi_fdt_attach(struct device * parent,struct device * self,void * aux)57 acpi_fdt_attach(struct device *parent, struct device *self, void *aux)
58 {
59 	struct acpi_softc *sc = (struct acpi_softc *)self;
60 	struct fdt_attach_args *faa = aux;
61 	bus_dma_tag_t dmat;
62 
63 	sc->sc_memt = faa->fa_iot;
64 	sc->sc_ci_dmat = faa->fa_dmat;
65 
66 	/* Create coherent DMA tag. */
67 	dmat = malloc(sizeof(*sc->sc_cc_dmat), M_DEVBUF, M_WAITOK | M_ZERO);
68 	memcpy(dmat, faa->fa_dmat, sizeof(*dmat));
69 	dmat->_flags |= BUS_DMA_COHERENT;
70 	sc->sc_cc_dmat = dmat;
71 
72 	acpi_attach_common(sc, faa->fa_reg[0].addr);
73 }
74 
75 int
acpi_map(paddr_t pa,size_t len,struct acpi_mem_map * handle)76 acpi_map(paddr_t pa, size_t len, struct acpi_mem_map *handle)
77 {
78 	paddr_t pgpa = trunc_page(pa);
79 	paddr_t endpa = round_page(pa + len);
80 	vaddr_t va = (vaddr_t)km_alloc(endpa - pgpa, &kv_any, &kp_none,
81 	    &kd_nowait);
82 
83 	if (va == 0)
84 		return (ENOMEM);
85 
86 	handle->baseva = va;
87 	handle->va = (u_int8_t *)(va + (pa & PGOFSET));
88 	handle->vsize = endpa - pgpa;
89 	handle->pa = pa;
90 
91 	do {
92 		pmap_kenter_pa(va, pgpa, PROT_READ | PROT_WRITE);
93 		va += NBPG;
94 		pgpa += NBPG;
95 	} while (pgpa < endpa);
96 
97 	return 0;
98 }
99 
100 void
acpi_unmap(struct acpi_mem_map * handle)101 acpi_unmap(struct acpi_mem_map *handle)
102 {
103 	pmap_kremove(handle->baseva, handle->vsize);
104 	km_free((void *)handle->baseva, handle->vsize, &kv_any, &kp_none);
105 }
106 
107 int
acpi_bus_space_map(bus_space_tag_t t,bus_addr_t addr,bus_size_t size,int flags,bus_space_handle_t * bshp)108 acpi_bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
109     int flags, bus_space_handle_t *bshp)
110 {
111 	return bus_space_map(t, addr, size, flags, bshp);
112 }
113 
114 void
acpi_bus_space_unmap(bus_space_tag_t t,bus_space_handle_t bsh,bus_size_t size)115 acpi_bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
116     bus_size_t size)
117 {
118 	bus_space_unmap(t, bsh, size);
119 }
120 
121 int
acpi_acquire_glk(uint32_t * lock)122 acpi_acquire_glk(uint32_t *lock)
123 {
124 	/* No global lock. */
125 	return 1;
126 }
127 
128 int
acpi_release_glk(uint32_t * lock)129 acpi_release_glk(uint32_t *lock)
130 {
131 	/* No global lock. */
132 	return 0;
133 }
134 
135 void
acpi_attach_machdep(struct acpi_softc * sc)136 acpi_attach_machdep(struct acpi_softc *sc)
137 {
138 #if NAPM > 0
139 	apm_setinfohook(acpi_apminfo);
140 #endif
141 }
142 
143 void *
acpi_intr_establish(int irq,int flags,int level,int (* func)(void *),void * arg,const char * name)144 acpi_intr_establish(int irq, int flags, int level,
145     int (*func)(void *), void *arg, const char *name)
146 {
147 	struct interrupt_controller *ic;
148 	struct machine_intr_handle *aih;
149 	uint32_t interrupt[3];
150 	void *cookie;
151 
152 	extern LIST_HEAD(, interrupt_controller) interrupt_controllers;
153 	LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
154 		if (ic->ic_phandle == 1)
155 			break;
156 	}
157 	if (ic == NULL)
158 		return NULL;
159 
160 	interrupt[0] = 0;
161 	interrupt[1] = irq - 32;
162 	if (flags & LR_EXTIRQ_MODE) { /* edge */
163 		if (flags & LR_EXTIRQ_POLARITY)
164 			interrupt[2] = 0x2; /* falling */
165 		else
166 			interrupt[2] = 0x1; /* rising */
167 	} else { /* level */
168 		if (flags & LR_EXTIRQ_POLARITY)
169 			interrupt[2] = 0x8; /* low */
170 		else
171 			interrupt[2] = 0x4; /* high */
172 	}
173 
174 	cookie = ic->ic_establish(ic->ic_cookie, interrupt, level, NULL,
175 	    func, arg, (char *)name);
176 	if (cookie == NULL)
177 		return NULL;
178 
179 	aih = malloc(sizeof(*aih), M_DEVBUF, M_WAITOK);
180 	aih->ih_ic = ic;
181 	aih->ih_ih = cookie;
182 
183 	return aih;
184 }
185 
186 void
acpi_intr_disestablish(void * cookie)187 acpi_intr_disestablish(void *cookie)
188 {
189 	struct machine_intr_handle *aih = cookie;
190 	struct interrupt_controller *ic = aih->ih_ic;
191 
192 	ic->ic_disestablish(aih->ih_ih);
193 	free(aih, M_DEVBUF, sizeof(*aih));
194 }
195 
196 bus_dma_tag_t
acpi_iommu_device_map(struct aml_node * node,bus_dma_tag_t dmat)197 acpi_iommu_device_map(struct aml_node *node, bus_dma_tag_t dmat)
198 {
199 	return acpiiort_device_map(node, dmat);
200 }
201