xref: /dflybsd-src/sys/bus/smbus/ichiic/ig4_acpi.c (revision 39bca54513448789b5040d3d5402d5ba3a71737d)
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>
45ab1e5d7fSImre Vadász #include <sys/serialize.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",
77*39bca545SMatthew Dillon 	"AMDI0510",
78*39bca545SMatthew Dillon 	"AMDI0010",
79*39bca545SMatthew Dillon 	"APMC0D0F",
8045f62dc9SImre Vadász 	NULL
8145f62dc9SImre Vadász };
8245f62dc9SImre Vadász 
8345f62dc9SImre Vadász static
8445f62dc9SImre Vadász int
ig4iic_acpi_probe(device_t dev)8545f62dc9SImre Vadász ig4iic_acpi_probe(device_t dev)
8645f62dc9SImre Vadász {
8745f62dc9SImre Vadász 
8845f62dc9SImre Vadász         if (acpi_disabled("ig4iic") ||
8945f62dc9SImre Vadász             ACPI_ID_PROBE(device_get_parent(dev), dev, ig4iic_ids) == NULL)
9045f62dc9SImre Vadász                 return (ENXIO);
9145f62dc9SImre Vadász 
92*39bca545SMatthew Dillon 	device_set_desc(dev, "Designware I2C Controller");
9345f62dc9SImre Vadász 
9445f62dc9SImre Vadász 	return (BUS_PROBE_DEFAULT);
9545f62dc9SImre Vadász }
9645f62dc9SImre Vadász 
9745f62dc9SImre Vadász static
9845f62dc9SImre Vadász int
ig4iic_acpi_attach(device_t dev)9945f62dc9SImre Vadász ig4iic_acpi_attach(device_t dev)
10045f62dc9SImre Vadász {
10145f62dc9SImre Vadász 	ig4iic_softc_t *sc = device_get_softc(dev);
10245f62dc9SImre Vadász 	int error;
10345f62dc9SImre Vadász 
104ab1e5d7fSImre Vadász 	lwkt_serialize_init(&sc->slz);
10545f62dc9SImre Vadász 
10645f62dc9SImre Vadász 	sc->dev = dev;
107a4549657SImre Vadász 	/* All the HIDs matched are Atom SOCs. */
108a4549657SImre Vadász 	sc->version = IG4_ATOM;
10945f62dc9SImre Vadász 	sc->regs_rid = 0;
11045f62dc9SImre Vadász 	sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
11145f62dc9SImre Vadász 					  &sc->regs_rid, RF_ACTIVE);
11245f62dc9SImre Vadász 	if (sc->regs_res == NULL) {
113*39bca545SMatthew Dillon 		device_printf(dev, "unable to map registers\n");
11445f62dc9SImre Vadász 		ig4iic_acpi_detach(dev);
11545f62dc9SImre Vadász 		return (ENXIO);
11645f62dc9SImre Vadász 	}
11745f62dc9SImre Vadász 	sc->intr_rid = 0;
11845f62dc9SImre Vadász 	sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
11945f62dc9SImre Vadász 					  &sc->intr_rid, RF_ACTIVE);
12045f62dc9SImre Vadász 	if (sc->intr_res == NULL) {
121*39bca545SMatthew Dillon 		device_printf(dev, "unable to map interrupt\n");
12245f62dc9SImre Vadász 		ig4iic_acpi_detach(dev);
12345f62dc9SImre Vadász 		return (ENXIO);
12445f62dc9SImre Vadász 	}
12545f62dc9SImre Vadász 	sc->regs_t = rman_get_bustag(sc->regs_res);
12645f62dc9SImre Vadász 	sc->regs_h = rman_get_bushandle(sc->regs_res);
12745f62dc9SImre Vadász 	sc->pci_attached = 1;
12845f62dc9SImre Vadász 
12945f62dc9SImre Vadász 	/* power up the controller */
13045f62dc9SImre Vadász 	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
13145f62dc9SImre Vadász 
13245f62dc9SImre Vadász 	error = ig4iic_attach(sc);
13345f62dc9SImre Vadász 	if (error)
13445f62dc9SImre Vadász 		ig4iic_acpi_detach(dev);
13545f62dc9SImre Vadász 
13645f62dc9SImre Vadász 	return error;
13745f62dc9SImre Vadász }
13845f62dc9SImre Vadász 
13945f62dc9SImre Vadász static
14045f62dc9SImre Vadász int
ig4iic_acpi_detach(device_t dev)14145f62dc9SImre Vadász ig4iic_acpi_detach(device_t dev)
14245f62dc9SImre Vadász {
14345f62dc9SImre Vadász 	ig4iic_softc_t *sc = device_get_softc(dev);
14445f62dc9SImre Vadász 	int error;
14545f62dc9SImre Vadász 
14645f62dc9SImre Vadász 	if (sc->pci_attached) {
14745f62dc9SImre Vadász 		error = ig4iic_detach(sc);
14845f62dc9SImre Vadász 		if (error)
14945f62dc9SImre Vadász 			return error;
15045f62dc9SImre Vadász 		sc->pci_attached = 0;
15145f62dc9SImre Vadász 	}
15245f62dc9SImre Vadász 
15345f62dc9SImre Vadász 	if (sc->intr_res) {
15445f62dc9SImre Vadász 		bus_release_resource(dev, SYS_RES_IRQ,
15545f62dc9SImre Vadász 				     sc->intr_rid, sc->intr_res);
15645f62dc9SImre Vadász 		sc->intr_res = NULL;
15745f62dc9SImre Vadász 	}
15845f62dc9SImre Vadász 	if (sc->regs_res) {
15945f62dc9SImre Vadász 		bus_release_resource(dev, SYS_RES_MEMORY,
16045f62dc9SImre Vadász 				     sc->regs_rid, sc->regs_res);
16145f62dc9SImre Vadász 		sc->regs_res = NULL;
16245f62dc9SImre Vadász 	}
16345f62dc9SImre Vadász 	sc->regs_t = 0;
16445f62dc9SImre Vadász 	sc->regs_h = 0;
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,
199df21e16dSImre Vadász         sizeof(struct ig4iic_softc),
200df21e16dSImre 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