ig4_acpi.c revision 311809
1341825Sdim/*- 2234287Sdim * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3353358Sdim * All rights reserved. 4353358Sdim * 5353358Sdim * Redistribution and use in source and binary forms, with or without 6234287Sdim * modification, are permitted provided that the following conditions 7234287Sdim * are met: 8234287Sdim * 1. Redistributions of source code must retain the above copyright 9234287Sdim * notice, this list of conditions and the following disclaimer. 10234287Sdim * 2. Redistributions in binary form must reproduce the above copyright 11234287Sdim * notice, this list of conditions and the following disclaimer in the 12341825Sdim * documentation and/or other materials provided with the distribution. 13341825Sdim * 14234287Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16234287Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17261991Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18234287Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19234287Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20234287Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21341825Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22341825Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23341825Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24341825Sdim * SUCH DAMAGE. 25234287Sdim */ 26234287Sdim 27341825Sdim#include <sys/cdefs.h> 28341825Sdim__FBSDID("$FreeBSD: stable/11/sys/dev/ichiic/ig4_acpi.c 311809 2017-01-09 19:32:57Z gonzo $"); 29234287Sdim 30234287Sdim#include "opt_acpi.h" 31234287Sdim 32234287Sdim#include <sys/param.h> 33234287Sdim#include <sys/bus.h> 34234287Sdim#include <sys/kernel.h> 35234287Sdim#include <sys/module.h> 36234287Sdim#include <sys/proc.h> 37234287Sdim#include <sys/rman.h> 38234287Sdim 39234287Sdim#include <machine/bus.h> 40234287Sdim#include <machine/resource.h> 41234287Sdim 42234287Sdim#include <contrib/dev/acpica/include/acpi.h> 43234287Sdim#include <contrib/dev/acpica/include/accommon.h> 44234287Sdim 45234287Sdim#include <dev/acpica/acpivar.h> 46234287Sdim#include <dev/iicbus/iiconf.h> 47234287Sdim 48234287Sdim#include <dev/ichiic/ig4_reg.h> 49234287Sdim#include <dev/ichiic/ig4_var.h> 50234287Sdim 51234287Sdimstatic int ig4iic_acpi_probe(device_t dev); 52234287Sdimstatic int ig4iic_acpi_attach(device_t dev); 53234287Sdimstatic int ig4iic_acpi_detach(device_t dev); 54249423Sdim 55341825Sdimstatic char *ig4iic_ids[] = { 56276479Sdim "INT33C2", 57341825Sdim "INT33C3", 58234287Sdim "INT3432", 59341825Sdim "INT3433", 60261991Sdim "80860F41", 61234287Sdim "808622C1", 62234287Sdim "AMDI0510", 63234287Sdim "APMC0D0F", 64234287Sdim NULL 65276479Sdim}; 66341825Sdim 67234287Sdimstatic int 68234287Sdimig4iic_acpi_probe(device_t dev) 69234287Sdim{ 70234287Sdim 71234287Sdim if (acpi_disabled("ig4iic") || 72341825Sdim ACPI_ID_PROBE(device_get_parent(dev), dev, ig4iic_ids) == NULL) 73234287Sdim return (ENXIO); 74234287Sdim 75234287Sdim device_set_desc(dev, "Designware I2C Controller"); 76234287Sdim return (0); 77341825Sdim} 78234287Sdim 79234287Sdimstatic int 80234287Sdimig4iic_acpi_attach(device_t dev) 81234287Sdim{ 82341825Sdim ig4iic_softc_t *sc; 83234287Sdim int error; 84234287Sdim 85234287Sdim sc = device_get_softc(dev); 86234287Sdim 87234287Sdim sc->dev = dev; 88234287Sdim sc->regs_rid = 0; 89234287Sdim sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 90234287Sdim &sc->regs_rid, RF_ACTIVE); 91234287Sdim if (sc->regs_res == NULL) { 92234287Sdim device_printf(dev, "unable to map registers\n"); 93234287Sdim ig4iic_acpi_detach(dev); 94234287Sdim return (ENXIO); 95234287Sdim } 96234287Sdim sc->intr_rid = 0; 97234287Sdim sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 98234287Sdim &sc->intr_rid, RF_SHAREABLE | RF_ACTIVE); 99234287Sdim if (sc->intr_res == NULL) { 100234287Sdim device_printf(dev, "unable to map interrupt\n"); 101341825Sdim ig4iic_acpi_detach(dev); 102234287Sdim return (ENXIO); 103234287Sdim } 104234287Sdim sc->platform_attached = 1; 105341825Sdim 106234287Sdim error = ig4iic_attach(sc); 107234287Sdim if (error) 108234287Sdim ig4iic_acpi_detach(dev); 109341825Sdim 110234287Sdim return (error); 111234287Sdim} 112234287Sdim 113341825Sdimstatic int 114234287Sdimig4iic_acpi_detach(device_t dev) 115234287Sdim{ 116234287Sdim ig4iic_softc_t *sc = device_get_softc(dev); 117234287Sdim int error; 118234287Sdim 119341825Sdim if (sc->platform_attached) { 120341825Sdim error = ig4iic_detach(sc); 121234287Sdim if (error) 122234287Sdim return (error); 123234287Sdim sc->platform_attached = 0; 124234287Sdim } 125234287Sdim 126234287Sdim if (sc->intr_res) { 127234287Sdim bus_release_resource(dev, SYS_RES_IRQ, 128234287Sdim sc->intr_rid, sc->intr_res); 129234287Sdim sc->intr_res = NULL; 130234287Sdim } 131234287Sdim if (sc->regs_res) { 132234287Sdim bus_release_resource(dev, SYS_RES_MEMORY, 133234287Sdim sc->regs_rid, sc->regs_res); 134234287Sdim sc->regs_res = NULL; 135234287Sdim } 136234287Sdim 137234287Sdim return (0); 138234287Sdim} 139234287Sdim 140234287Sdimstatic device_method_t ig4iic_acpi_methods[] = { 141234287Sdim /* Device interface */ 142234287Sdim DEVMETHOD(device_probe, ig4iic_acpi_probe), 143234287Sdim DEVMETHOD(device_attach, ig4iic_acpi_attach), 144234287Sdim DEVMETHOD(device_detach, ig4iic_acpi_detach), 145276479Sdim 146234287Sdim /* iicbus interface */ 147276479Sdim DEVMETHOD(iicbus_transfer, ig4iic_transfer), 148234287Sdim DEVMETHOD(iicbus_reset, ig4iic_reset), 149234287Sdim DEVMETHOD(iicbus_callback, iicbus_null_callback), 150341825Sdim 151234287Sdim DEVMETHOD_END 152341825Sdim}; 153234287Sdim 154341825Sdimstatic driver_t ig4iic_acpi_driver = { 155 "ig4iic_acpi", 156 ig4iic_acpi_methods, 157 sizeof(struct ig4iic_softc), 158}; 159 160static devclass_t ig4iic_acpi_devclass; 161DRIVER_MODULE(ig4iic_acpi, acpi, ig4iic_acpi_driver, ig4iic_acpi_devclass, 0, 0); 162 163MODULE_DEPEND(ig4iic_acpi, acpi, 1, 1, 1); 164MODULE_DEPEND(ig4iic_acpi, pci, 1, 1, 1); 165MODULE_DEPEND(ig4iic_acpi, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); 166MODULE_VERSION(ig4iic_acpi, 1); 167