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 39int pwr_action = 1; 40 41int acpi_fdt_match(struct device *, void *, void *); 42void acpi_fdt_attach(struct device *, struct device *, void *); 43 44const struct cfattach acpi_fdt_ca = { 45 sizeof(struct acpi_softc), acpi_fdt_match, acpi_fdt_attach 46}; 47 48int 49acpi_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 56void 57acpi_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 75int 76acpi_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 100void 101acpi_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 107int 108acpi_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 114void 115acpi_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 121int 122acpi_acquire_glk(uint32_t *lock) 123{ 124 /* No global lock. */ 125 return 1; 126} 127 128int 129acpi_release_glk(uint32_t *lock) 130{ 131 /* No global lock. */ 132 return 0; 133} 134 135void 136acpi_attach_machdep(struct acpi_softc *sc) 137{ 138#if NAPM > 0 139 apm_setinfohook(acpi_apminfo); 140#endif 141} 142 143void * 144acpi_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 186void 187acpi_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 196bus_dma_tag_t 197acpi_iommu_device_map(struct aml_node *node, bus_dma_tag_t dmat) 198{ 199 return acpiiort_device_map(node, dmat); 200} 201