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