145f62dc9SImre Vadász /* 245f62dc9SImre Vadász * Copyright (c) 2014 The DragonFly Project. All rights reserved. 345f62dc9SImre Vadász * 445f62dc9SImre Vadász * This code is derived from software contributed to The DragonFly Project 545f62dc9SImre Vadász * by Matthew Dillon <dillon@backplane.com> 645f62dc9SImre Vadász * 745f62dc9SImre Vadász * Redistribution and use in source and binary forms, with or without 845f62dc9SImre Vadász * modification, are permitted provided that the following conditions 945f62dc9SImre Vadász * are met: 1045f62dc9SImre Vadász * 1145f62dc9SImre Vadász * 1. Redistributions of source code must retain the above copyright 1245f62dc9SImre Vadász * notice, this list of conditions and the following disclaimer. 1345f62dc9SImre Vadász * 2. Redistributions in binary form must reproduce the above copyright 1445f62dc9SImre Vadász * notice, this list of conditions and the following disclaimer in 1545f62dc9SImre Vadász * the documentation and/or other materials provided with the 1645f62dc9SImre Vadász * distribution. 1745f62dc9SImre Vadász * 3. Neither the name of The DragonFly Project nor the names of its 1845f62dc9SImre Vadász * contributors may be used to endorse or promote products derived 1945f62dc9SImre Vadász * from this software without specific, prior written permission. 2045f62dc9SImre Vadász * 2145f62dc9SImre Vadász * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2245f62dc9SImre Vadász * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2345f62dc9SImre Vadász * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2445f62dc9SImre Vadász * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 2545f62dc9SImre Vadász * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2645f62dc9SImre Vadász * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 2745f62dc9SImre Vadász * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2845f62dc9SImre Vadász * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2945f62dc9SImre Vadász * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 3045f62dc9SImre Vadász * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 3145f62dc9SImre Vadász * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3245f62dc9SImre Vadász * SUCH DAMAGE. 3345f62dc9SImre Vadász */ 3445f62dc9SImre Vadász /* 3545f62dc9SImre Vadász * Intel 4th generation mobile cpus integrated I2C device, smbus driver. 3645f62dc9SImre Vadász * 3745f62dc9SImre Vadász * See ig4_reg.h for datasheet reference and notes. 3845f62dc9SImre Vadász */ 3945f62dc9SImre Vadász 4045f62dc9SImre Vadász #include <sys/param.h> 4145f62dc9SImre Vadász #include <sys/systm.h> 4245f62dc9SImre Vadász #include <sys/kernel.h> 4345f62dc9SImre Vadász #include <sys/module.h> 4445f62dc9SImre Vadász #include <sys/errno.h> 4545f62dc9SImre Vadász #include <sys/lock.h> 4645f62dc9SImre Vadász #include <sys/syslog.h> 4745f62dc9SImre Vadász #include <sys/bus.h> 4845f62dc9SImre Vadász 4945f62dc9SImre Vadász #include <sys/rman.h> 5045f62dc9SImre Vadász 5145f62dc9SImre Vadász #include "opt_acpi.h" 5245f62dc9SImre Vadász #include "acpi.h" 5345f62dc9SImre Vadász #include <dev/acpica/acpivar.h> 5445f62dc9SImre Vadász 5545f62dc9SImre Vadász #include <bus/pci/pcivar.h> 5645f62dc9SImre Vadász 5745f62dc9SImre Vadász #include <bus/smbus/smbconf.h> 5845f62dc9SImre Vadász 5945f62dc9SImre Vadász #include "smbus_if.h" 6045f62dc9SImre Vadász 6145f62dc9SImre Vadász #include "ig4_reg.h" 6245f62dc9SImre Vadász #include "ig4_var.h" 6345f62dc9SImre Vadász 6445f62dc9SImre Vadász ACPI_MODULE_NAME("ig4iic"); 6545f62dc9SImre Vadász 6645f62dc9SImre Vadász static int ig4iic_acpi_probe(device_t dev); 6745f62dc9SImre Vadász static int ig4iic_acpi_attach(device_t dev); 6845f62dc9SImre Vadász static int ig4iic_acpi_detach(device_t dev); 6945f62dc9SImre Vadász 7045f62dc9SImre Vadász static char *ig4iic_ids[] = { 7145f62dc9SImre Vadász "INT33C2", 7245f62dc9SImre Vadász "INT33C3", 7345f62dc9SImre Vadász "INT3432", 7445f62dc9SImre Vadász "INT3433", 7545f62dc9SImre Vadász "80860F41", 7645f62dc9SImre Vadász "808622C1", 7745f62dc9SImre Vadász NULL 7845f62dc9SImre Vadász }; 7945f62dc9SImre Vadász 8045f62dc9SImre Vadász static 8145f62dc9SImre Vadász int 8245f62dc9SImre Vadász ig4iic_acpi_probe(device_t dev) 8345f62dc9SImre Vadász { 8445f62dc9SImre Vadász 8545f62dc9SImre Vadász if (acpi_disabled("ig4iic") || 8645f62dc9SImre Vadász ACPI_ID_PROBE(device_get_parent(dev), dev, ig4iic_ids) == NULL) 8745f62dc9SImre Vadász return (ENXIO); 8845f62dc9SImre Vadász 8945f62dc9SImre Vadász device_set_desc(dev, "Intel SoC I2C Controller"); 9045f62dc9SImre Vadász 9145f62dc9SImre Vadász return (BUS_PROBE_DEFAULT); 9245f62dc9SImre Vadász } 9345f62dc9SImre Vadász 9445f62dc9SImre Vadász static 9545f62dc9SImre Vadász int 9645f62dc9SImre Vadász ig4iic_acpi_attach(device_t dev) 9745f62dc9SImre Vadász { 9845f62dc9SImre Vadász ig4iic_softc_t *sc = device_get_softc(dev); 9945f62dc9SImre Vadász int error; 10045f62dc9SImre Vadász 10145f62dc9SImre Vadász bzero(sc, sizeof(*sc)); 10245f62dc9SImre Vadász 10345f62dc9SImre Vadász lockinit(&sc->lk, "ig4iic", 0, LK_CANRECURSE); 10445f62dc9SImre Vadász 10545f62dc9SImre Vadász sc->dev = dev; 106a4549657SImre Vadász /* All the HIDs matched are Atom SOCs. */ 107a4549657SImre Vadász sc->version = IG4_ATOM; 10845f62dc9SImre Vadász sc->regs_rid = 0; 10945f62dc9SImre Vadász sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 11045f62dc9SImre Vadász &sc->regs_rid, RF_ACTIVE); 11145f62dc9SImre Vadász if (sc->regs_res == NULL) { 11245f62dc9SImre Vadász device_printf(dev, "unable to map registers"); 11345f62dc9SImre Vadász ig4iic_acpi_detach(dev); 11445f62dc9SImre Vadász return (ENXIO); 11545f62dc9SImre Vadász } 11645f62dc9SImre Vadász sc->intr_rid = 0; 11745f62dc9SImre Vadász sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 11845f62dc9SImre Vadász &sc->intr_rid, RF_ACTIVE); 11945f62dc9SImre Vadász if (sc->intr_res == NULL) { 12045f62dc9SImre Vadász device_printf(dev, "unable to map interrupt"); 12145f62dc9SImre Vadász ig4iic_acpi_detach(dev); 12245f62dc9SImre Vadász return (ENXIO); 12345f62dc9SImre Vadász } 12445f62dc9SImre Vadász sc->regs_t = rman_get_bustag(sc->regs_res); 12545f62dc9SImre Vadász sc->regs_h = rman_get_bushandle(sc->regs_res); 12645f62dc9SImre Vadász sc->pci_attached = 1; 12745f62dc9SImre Vadász 12845f62dc9SImre Vadász /* power up the controller */ 12945f62dc9SImre Vadász pci_set_powerstate(dev, PCI_POWERSTATE_D0); 13045f62dc9SImre Vadász 13145f62dc9SImre Vadász error = ig4iic_attach(sc); 13245f62dc9SImre Vadász if (error) 13345f62dc9SImre Vadász ig4iic_acpi_detach(dev); 13445f62dc9SImre Vadász 13545f62dc9SImre Vadász return error; 13645f62dc9SImre Vadász } 13745f62dc9SImre Vadász 13845f62dc9SImre Vadász static 13945f62dc9SImre Vadász int 14045f62dc9SImre Vadász ig4iic_acpi_detach(device_t dev) 14145f62dc9SImre Vadász { 14245f62dc9SImre Vadász ig4iic_softc_t *sc = device_get_softc(dev); 14345f62dc9SImre Vadász int error; 14445f62dc9SImre Vadász 14545f62dc9SImre Vadász if (sc->pci_attached) { 14645f62dc9SImre Vadász error = ig4iic_detach(sc); 14745f62dc9SImre Vadász if (error) 14845f62dc9SImre Vadász return error; 14945f62dc9SImre Vadász sc->pci_attached = 0; 15045f62dc9SImre Vadász } 15145f62dc9SImre Vadász 15245f62dc9SImre Vadász if (sc->intr_res) { 15345f62dc9SImre Vadász bus_release_resource(dev, SYS_RES_IRQ, 15445f62dc9SImre Vadász sc->intr_rid, sc->intr_res); 15545f62dc9SImre Vadász sc->intr_res = NULL; 15645f62dc9SImre Vadász } 15745f62dc9SImre Vadász if (sc->regs_res) { 15845f62dc9SImre Vadász bus_release_resource(dev, SYS_RES_MEMORY, 15945f62dc9SImre Vadász sc->regs_rid, sc->regs_res); 16045f62dc9SImre Vadász sc->regs_res = NULL; 16145f62dc9SImre Vadász } 16245f62dc9SImre Vadász sc->regs_t = 0; 16345f62dc9SImre Vadász sc->regs_h = 0; 16445f62dc9SImre Vadász lockuninit(&sc->lk); 16545f62dc9SImre Vadász 16645f62dc9SImre Vadász pci_set_powerstate(dev, PCI_POWERSTATE_D3); 16745f62dc9SImre Vadász 16845f62dc9SImre Vadász return 0; 16945f62dc9SImre Vadász } 17045f62dc9SImre Vadász 17145f62dc9SImre Vadász static device_method_t ig4iic_acpi_methods[] = { 17245f62dc9SImre Vadász /* Device interface */ 17345f62dc9SImre Vadász DEVMETHOD(device_probe, ig4iic_acpi_probe), 17445f62dc9SImre Vadász DEVMETHOD(device_attach, ig4iic_acpi_attach), 17545f62dc9SImre Vadász DEVMETHOD(device_detach, ig4iic_acpi_detach), 17645f62dc9SImre Vadász 17745f62dc9SImre Vadász /* Bus methods */ 17845f62dc9SImre Vadász DEVMETHOD(bus_print_child, bus_generic_print_child), 17945f62dc9SImre Vadász 18045f62dc9SImre Vadász /* SMBus methods from ig4_smb.c */ 18145f62dc9SImre Vadász DEVMETHOD(smbus_callback, ig4iic_smb_callback), 18245f62dc9SImre Vadász DEVMETHOD(smbus_quick, ig4iic_smb_quick), 18345f62dc9SImre Vadász DEVMETHOD(smbus_sendb, ig4iic_smb_sendb), 18445f62dc9SImre Vadász DEVMETHOD(smbus_recvb, ig4iic_smb_recvb), 18545f62dc9SImre Vadász DEVMETHOD(smbus_writeb, ig4iic_smb_writeb), 18645f62dc9SImre Vadász DEVMETHOD(smbus_writew, ig4iic_smb_writew), 18745f62dc9SImre Vadász DEVMETHOD(smbus_readb, ig4iic_smb_readb), 18845f62dc9SImre Vadász DEVMETHOD(smbus_readw, ig4iic_smb_readw), 18945f62dc9SImre Vadász DEVMETHOD(smbus_pcall, ig4iic_smb_pcall), 19045f62dc9SImre Vadász DEVMETHOD(smbus_bwrite, ig4iic_smb_bwrite), 19145f62dc9SImre Vadász DEVMETHOD(smbus_bread, ig4iic_smb_bread), 19245f62dc9SImre Vadász DEVMETHOD(smbus_trans, ig4iic_smb_trans), 19345f62dc9SImre Vadász DEVMETHOD_END 19445f62dc9SImre Vadász }; 19545f62dc9SImre Vadász 19645f62dc9SImre Vadász static driver_t ig4iic_acpi_driver = { 19745f62dc9SImre Vadász "ig4iic", 19845f62dc9SImre Vadász ig4iic_acpi_methods, 199*df21e16dSImre Vadász sizeof(struct ig4iic_softc), 200*df21e16dSImre Vadász .gpri = KOBJ_GPRI_ACPI+1 20145f62dc9SImre Vadász }; 20245f62dc9SImre Vadász 20345f62dc9SImre Vadász static devclass_t ig4iic_acpi_devclass; 20445f62dc9SImre Vadász 20545f62dc9SImre Vadász DRIVER_MODULE(ig4iic, acpi, ig4iic_acpi_driver, ig4iic_acpi_devclass, NULL, NULL); 20645f62dc9SImre Vadász MODULE_DEPEND(ig4iic, acpi, 1, 1, 1); 20745f62dc9SImre Vadász MODULE_DEPEND(ig4iic, smbacpi, 1, 1, 1); 208