1 /* 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2025 Poul-Henning Kamp <phk@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29 #include <sys/cdefs.h> 30 #include "opt_acpi.h" 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/kernel.h> 35 #include <sys/module.h> 36 #include <sys/proc.h> 37 #include <sys/rman.h> 38 39 #include <machine/bus.h> 40 #include <machine/resource.h> 41 42 #include <contrib/dev/acpica/include/acpi.h> 43 #include <contrib/dev/acpica/include/accommon.h> 44 45 #include <dev/acpica/acpivar.h> 46 #include <dev/iicbus/iiconf.h> 47 48 #include <dev/iicbus/controller/qcom/geni_iic_var.h> 49 50 static int geniiic_acpi_probe(device_t dev); 51 static int geniiic_acpi_attach(device_t dev); 52 static int geniiic_acpi_detach(device_t dev); 53 54 static char *geniiic_ids[] = { 55 "QCOM0C10", 56 NULL 57 }; 58 59 static int 60 geniiic_acpi_probe(device_t dev) 61 { 62 int rv; 63 64 if (acpi_disabled("geniiic")) 65 return (ENXIO); 66 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, geniiic_ids, NULL); 67 if (rv > 0) 68 return (rv); 69 70 device_set_desc(dev, "Qualcomm GENI I2C Controller"); 71 return (rv); 72 } 73 74 static int 75 geniiic_acpi_attach(device_t dev) 76 { 77 geniiic_softc_t *sc; 78 char *str; 79 int error; 80 81 sc = device_get_softc(dev); 82 83 sc->dev = dev; 84 error = ACPI_ID_PROBE(device_get_parent(dev), dev, geniiic_ids, &str); 85 if (error > 0) 86 return (error); 87 88 sc->regs_rid = 0; 89 sc->regs_res = bus_alloc_resource_any(dev, 90 SYS_RES_MEMORY, &sc->regs_rid, RF_ACTIVE); 91 if (sc->regs_res == NULL) { 92 device_printf(dev, "unable to map registers\n"); 93 geniiic_acpi_detach(dev); 94 return (ENXIO); 95 } 96 sc->intr_rid = 0; 97 sc->intr_res = bus_alloc_resource_any(dev, 98 SYS_RES_IRQ, &sc->intr_rid, RF_SHAREABLE | RF_ACTIVE); 99 if (sc->intr_res == NULL) { 100 device_printf(dev, "unable to map interrupt\n"); 101 geniiic_acpi_detach(dev); 102 return (ENXIO); 103 } 104 sc->platform_attached = true; 105 106 error = geniiic_attach(sc); 107 if (error) 108 geniiic_acpi_detach(dev); 109 110 return (error); 111 } 112 113 static int 114 geniiic_acpi_detach(device_t dev) 115 { 116 geniiic_softc_t *sc = device_get_softc(dev); 117 int error; 118 119 if (sc->platform_attached) { 120 error = geniiic_detach(sc); 121 if (error) 122 return (error); 123 sc->platform_attached = false; 124 } 125 126 if (sc->intr_res) { 127 bus_release_resource(dev, SYS_RES_IRQ, 128 sc->intr_rid, sc->intr_res); 129 sc->intr_res = NULL; 130 } 131 if (sc->regs_res) { 132 bus_release_resource(dev, SYS_RES_MEMORY, 133 sc->regs_rid, sc->regs_res); 134 sc->regs_res = NULL; 135 } 136 137 return (0); 138 } 139 140 static int 141 geniiic_acpi_suspend(device_t dev) 142 { 143 geniiic_softc_t *sc = device_get_softc(dev); 144 145 return (geniiic_suspend(sc)); 146 } 147 148 static int 149 geniiic_acpi_resume(device_t dev) 150 { 151 geniiic_softc_t *sc = device_get_softc(dev); 152 153 return (geniiic_resume(sc)); 154 } 155 156 static device_method_t geniiic_acpi_methods[] = { 157 /* Device interface */ 158 DEVMETHOD(device_probe, geniiic_acpi_probe), 159 DEVMETHOD(device_attach, geniiic_acpi_attach), 160 DEVMETHOD(device_detach, geniiic_acpi_detach), 161 DEVMETHOD(device_suspend, geniiic_acpi_suspend), 162 DEVMETHOD(device_resume, geniiic_acpi_resume), 163 164 /* Bus interface */ 165 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 166 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 167 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 168 DEVMETHOD(bus_release_resource, bus_generic_release_resource), 169 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 170 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 171 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource), 172 173 /* iicbus interface */ 174 DEVMETHOD(iicbus_transfer, geniiic_transfer), 175 DEVMETHOD(iicbus_reset, geniiic_reset), 176 DEVMETHOD(iicbus_callback, geniiic_callback), 177 178 DEVMETHOD_END 179 }; 180 181 static driver_t geniiic_acpi_driver = { 182 "geniiic", 183 geniiic_acpi_methods, 184 sizeof(struct geniiic_softc), 185 }; 186 187 DRIVER_MODULE_ORDERED(geniiic, acpi, geniiic_acpi_driver, 0, 0, SI_ORDER_ANY); 188 MODULE_DEPEND(geniiic, acpi, 1, 1, 1); 189 ACPI_PNP_INFO(geniiic_ids); 190