xref: /netbsd-src/sys/arch/x86/pci/dwiic_pci.c (revision 5c40ffaf93547964ada04ba7799a489d1784b267)
1*5c40ffafSmartin /* $NetBSD: dwiic_pci.c,v 1.11 2024/11/11 17:28:38 martin Exp $ */
239de1096Sbouyer 
339de1096Sbouyer /*-
439de1096Sbouyer  * Copyright (c) 2017 The NetBSD Foundation, Inc.
539de1096Sbouyer  * All rights reserved.
639de1096Sbouyer  *
739de1096Sbouyer  * This code is derived from software contributed to The NetBSD Foundation
839de1096Sbouyer  * by Manuel Bouyer.
939de1096Sbouyer  *
1039de1096Sbouyer  * Redistribution and use in source and binary forms, with or without
1139de1096Sbouyer  * modification, are permitted provided that the following conditions
1239de1096Sbouyer  * are met:
1339de1096Sbouyer  * 1. Redistributions of source code must retain the above copyright
1439de1096Sbouyer  *    notice, this list of conditions and the following disclaimer.
1539de1096Sbouyer  * 2. Redistributions in binary form must reproduce the above copyright
1639de1096Sbouyer  *    notice, this list of conditions and the following disclaimer in the
1739de1096Sbouyer  *    documentation and/or other materials provided with the distribution.
1839de1096Sbouyer  *
1939de1096Sbouyer  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2039de1096Sbouyer  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2139de1096Sbouyer  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2239de1096Sbouyer  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2339de1096Sbouyer  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2439de1096Sbouyer  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2539de1096Sbouyer  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2639de1096Sbouyer  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2739de1096Sbouyer  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2839de1096Sbouyer  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2939de1096Sbouyer  * POSSIBILITY OF SUCH DAMAGE.
3039de1096Sbouyer  */
3139de1096Sbouyer /*
3239de1096Sbouyer  * Synopsys DesignWare I2C controller, PCI front-end
3339de1096Sbouyer  */
3439de1096Sbouyer 
3539de1096Sbouyer #include <sys/cdefs.h>
36*5c40ffafSmartin __KERNEL_RCSID(0, "$NetBSD: dwiic_pci.c,v 1.11 2024/11/11 17:28:38 martin Exp $");
3739de1096Sbouyer 
3839de1096Sbouyer #include <sys/param.h>
3939de1096Sbouyer #include <sys/systm.h>
4039de1096Sbouyer 
4139de1096Sbouyer #include <dev/pci/pcireg.h>
4239de1096Sbouyer #include <dev/pci/pcivar.h>
4339de1096Sbouyer #include <dev/pci/pcidevs.h>
4439de1096Sbouyer 
4539de1096Sbouyer #include <dev/acpi/acpivar.h>
4639de1096Sbouyer #include <dev/acpi/acpi_pci.h>
4739de1096Sbouyer #include <dev/acpi/acpi_util.h>
4839de1096Sbouyer #include <dev/acpi/acpi_i2c.h>
4939de1096Sbouyer 
5039de1096Sbouyer #include <dev/ic/dwiic_var.h>
5139de1096Sbouyer #include <arch/x86/pci/lpssreg.h>
5239de1096Sbouyer 
53*5c40ffafSmartin #include "acpica.h"
54*5c40ffafSmartin 
5539de1096Sbouyer //#define DWIIC_DEBUG
5639de1096Sbouyer 
5739de1096Sbouyer #ifdef DWIIC_DEBUG
5839de1096Sbouyer #define DPRINTF(x) printf x
5939de1096Sbouyer #else
6039de1096Sbouyer #define DPRINTF(x)
6139de1096Sbouyer #endif
6239de1096Sbouyer 
63f1e8be7fSandvar #if NACPICA > 0
64f1e8be7fSandvar #define	I2C_USE_ACPI
65f1e8be7fSandvar #endif /* NACPICA > 0 */
66f1e8be7fSandvar 
6739de1096Sbouyer struct pci_dwiic_softc {
6839de1096Sbouyer 	struct dwiic_softc	sc_dwiic;
6939de1096Sbouyer 	pci_chipset_tag_t	sc_pc;
7039de1096Sbouyer 	pcitag_t		sc_ptag;
7139de1096Sbouyer 	struct acpi_devnode	*sc_acpinode;
7239de1096Sbouyer };
7339de1096Sbouyer 
74bf8d193bSmsaitoh #define VIDDID(a, b) PCI_ID_CODE(PCI_VENDOR_ ## a, PCI_PRODUCT_ ## a ## _ ## b)
75bf8d193bSmsaitoh 
76bf8d193bSmsaitoh static const struct device_compatible_entry compat_data[] = {
77bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CORE4G_M_S_I2C_0) },
78bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CORE4G_M_S_I2C_1) },
79bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_I2C_0) },
80bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_I2C_1) },
81bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_I2C_2) },
82bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_I2C_3) },
83bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_LP_I2C_0) },
84bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_LP_I2C_1) },
85bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_LP_I2C_2) },
86bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_LP_I2C_3) },
87bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_LP_I2C_4) },
88bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 100SERIES_LP_I2C_5) },
89bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 2HS_I2C_0) },
90bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 2HS_I2C_1) },
91bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 2HS_I2C_2) },
92bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 2HS_I2C_3) },
93bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_I2C_0) },
94bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_I2C_1) },
95bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_I2C_2) },
96bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_I2C_3) },
97bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_U_I2C_0) },
98bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_U_I2C_1) },
99bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_U_I2C_2) },
100bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_U_I2C_3) },
101bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_U_I2C_4) },
102bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 3HS_U_I2C_5) },
103bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_H_I2C_0) },
104bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_H_I2C_1) },
105bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_H_I2C_2) },
106bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_H_I2C_3) },
107bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_V_I2C_0) },
108bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_V_I2C_1) },
109bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_V_I2C_2) },
110bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 4HS_V_I2C_3) },
111bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CMTLK_I2C_0) }, /* 4HS LP */
112bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CMTLK_I2C_1) },
113bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CMTLK_I2C_2) },
114bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CMTLK_I2C_3) },
115bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CMTLK_I2C_4) },
116bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, CMTLK_I2C_5) },
117bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 495_YU_I2C_0) },
118bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 495_YU_I2C_1) },
119bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 495_YU_I2C_2) },
120bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 495_YU_I2C_3) },
121bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 495_YU_I2C_4) },
122bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 495_YU_I2C_5) },
123bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_0) },
124bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_1) },
125bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_2) },
126bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_3) },
127bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_4) },
128bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_5) },
129bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_H_I2C_6) },
130bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_LP_I2C_0) },
131bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_LP_I2C_1) },
132bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_LP_I2C_2) },
133bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_LP_I2C_3) },
134bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_LP_I2C_4) },
135bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, 5HS_LP_I2C_5) },
136bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C1) },
137bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C2) },
138bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C3) },
139bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C4) },
140bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C5) },
141bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C6) },
142bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BAYTRAIL_SIO_I2C7) },
143bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_1) },
144bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_2) },
145bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_3) },
146bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_4) },
147bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_5) },
148bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_6) },
149bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, BSW_SIO_I2C_7) },
150bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_0) },
151bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_1) },
152bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_2) },
153bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_3) },
154bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_4) },
155bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_5) },
156bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_6) },
157bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, APL_I2C_7) },
158bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_0) },
159bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_1) },
160bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_2) },
161bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_3) },
162bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_4) },
163bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_5) },
164bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_6) },
165bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, GLK_I2C_7) },
166341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_0) },
167341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_1) },
168341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_2) },
169341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_3) },
170341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_4) },
171341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_5) },
172341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_6) },
173341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, EHL_SIO_I2C_7) },
174bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, JSL_LPSS_I2C_0) },
175bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, JSL_LPSS_I2C_1) },
176bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, JSL_LPSS_I2C_2) },
177bf8d193bSmsaitoh 	{ .id = VIDDID(INTEL, JSL_LPSS_I2C_3) },
178341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, JSL_LPSS_I2C_4) },
179341a1de0Smsaitoh 	{ .id = VIDDID(INTEL, JSL_LPSS_I2C_5) },
180bf8d193bSmsaitoh 
181bf8d193bSmsaitoh 	PCI_COMPAT_EOL
182bf8d193bSmsaitoh };
183bf8d193bSmsaitoh 
18439de1096Sbouyer static uint32_t
18539de1096Sbouyer lpss_read(struct pci_dwiic_softc *sc, int offset)
18639de1096Sbouyer {
1872ce73196Sriastradh 	return bus_space_read_4(sc->sc_dwiic.sc_iot, sc->sc_dwiic.sc_ioh,
18839de1096Sbouyer 	    offset);
18939de1096Sbouyer }
19039de1096Sbouyer 
19139de1096Sbouyer static void
19239de1096Sbouyer lpss_write(struct pci_dwiic_softc *sc, int offset, uint32_t val)
19339de1096Sbouyer {
19439de1096Sbouyer 	bus_space_write_4(sc->sc_dwiic.sc_iot, sc->sc_dwiic.sc_ioh,
19539de1096Sbouyer 	    offset, val);
19639de1096Sbouyer }
19739de1096Sbouyer 
19839de1096Sbouyer static int	pci_dwiic_match(device_t, cfdata_t, void *);
19939de1096Sbouyer static void	pci_dwiic_attach(device_t, device_t, void *);
20039de1096Sbouyer static bool	dwiic_pci_power(struct dwiic_softc *, bool);
20139de1096Sbouyer 
20239de1096Sbouyer CFATTACH_DECL_NEW(pcidwiic, sizeof(struct pci_dwiic_softc),
20339de1096Sbouyer     pci_dwiic_match, pci_dwiic_attach, dwiic_detach, NULL);
20439de1096Sbouyer 
20539de1096Sbouyer 
20639de1096Sbouyer int
20739de1096Sbouyer pci_dwiic_match(device_t parent, cfdata_t match, void *aux)
20839de1096Sbouyer {
20939de1096Sbouyer 	struct pci_attach_args *pa = aux;
21039de1096Sbouyer 
211bf8d193bSmsaitoh 	return pci_compatible_match(pa, compat_data);
21239de1096Sbouyer }
21339de1096Sbouyer 
21439de1096Sbouyer void
21539de1096Sbouyer pci_dwiic_attach(device_t parent, device_t self, void *aux)
21639de1096Sbouyer {
21739de1096Sbouyer 	struct pci_dwiic_softc *sc = device_private(self);
21839de1096Sbouyer 	struct pci_attach_args *pa = aux;
21939de1096Sbouyer 	const char *intrstr;
22039de1096Sbouyer 	pci_intr_handle_t intrhandle;
22139de1096Sbouyer 	char intrbuf[PCI_INTRSTR_LEN];
22239de1096Sbouyer 	pcireg_t memtype;
22339de1096Sbouyer 	pcireg_t csr;
22439de1096Sbouyer 	uint32_t caps;
22539de1096Sbouyer 
22639de1096Sbouyer 	sc->sc_dwiic.sc_dev = self;
22739de1096Sbouyer 	sc->sc_dwiic.sc_power = dwiic_pci_power;
22839de1096Sbouyer 	sc->sc_dwiic.sc_type = dwiic_type_sunrisepoint;
22939de1096Sbouyer 
23039de1096Sbouyer 	sc->sc_pc = pa->pa_pc;
23139de1096Sbouyer 	sc->sc_ptag = pa->pa_tag;
23239de1096Sbouyer 
23339de1096Sbouyer 	/* register access not enabled by BIOS */
23439de1096Sbouyer 	csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
23539de1096Sbouyer 	pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
23639de1096Sbouyer 	    csr | PCI_COMMAND_MEM_ENABLE);
23739de1096Sbouyer 
23839de1096Sbouyer 	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_BAR0);
23939de1096Sbouyer 	if (pci_mapreg_map(pa, PCI_BAR0, memtype, 0, &sc->sc_dwiic.sc_iot,
24039de1096Sbouyer 	    &sc->sc_dwiic.sc_ioh, NULL, NULL) != 0) {
24139de1096Sbouyer 		aprint_error(": can't map register space\n");
24239de1096Sbouyer 		goto out;
24339de1096Sbouyer 	}
24439de1096Sbouyer 	dwiic_pci_power(&sc->sc_dwiic, 1);
24539de1096Sbouyer 
24639de1096Sbouyer 	caps = lpss_read(sc, LPSS_CAP);
24739de1096Sbouyer 
24839de1096Sbouyer 	aprint_naive(": I2C controller\n");
24939de1096Sbouyer 	aprint_normal(": I2C controller instance %d\n",
25039de1096Sbouyer 	    (int)(caps & LPSS_CAP_INSTANCE));
25139de1096Sbouyer 
25239de1096Sbouyer 	if (pci_intr_map(pa, &intrhandle)) {
25339de1096Sbouyer 		aprint_error_dev(self, "can't map interrupt\n");
25439de1096Sbouyer 		goto out;
25539de1096Sbouyer 	}
25639de1096Sbouyer 	intrstr = pci_intr_string(pa->pa_pc, intrhandle,
25739de1096Sbouyer 	    intrbuf, sizeof(intrbuf));
25839de1096Sbouyer 
25939de1096Sbouyer 	sc->sc_dwiic.sc_ih = pci_intr_establish(pa->pa_pc, intrhandle,
26039de1096Sbouyer 	    IPL_VM, dwiic_intr, sc);
26139de1096Sbouyer 	if (sc->sc_dwiic.sc_ih == NULL) {
26239de1096Sbouyer 		aprint_error_dev(self, "couldn't establish interrupt");
26339de1096Sbouyer 		if (intrstr != NULL)
26439de1096Sbouyer 			aprint_error(" at %s", intrstr);
26539de1096Sbouyer 		aprint_error("\n");
26639de1096Sbouyer 		goto out;
26739de1096Sbouyer 	}
26839de1096Sbouyer 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
26939de1096Sbouyer 
27039de1096Sbouyer 	lpss_write(sc, LPSS_RESET, LPSS_RESET_CTRL_REL);
27139de1096Sbouyer 	lpss_write(sc, LPSS_REMAP_LO,
27239de1096Sbouyer 	    pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_BAR0));
27339de1096Sbouyer 	lpss_write(sc, LPSS_REMAP_HI,
27439de1096Sbouyer 	    pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_BAR0 + 0x4));
27539de1096Sbouyer 
276f1e8be7fSandvar #ifdef I2C_USE_ACPI
27739de1096Sbouyer 	sc->sc_acpinode = acpi_pcidev_find(0 /*XXX segment*/,
27839de1096Sbouyer 	    pa->pa_bus, pa->pa_device, pa->pa_function);
279f1e8be7fSandvar #else
280f1e8be7fSandvar 	sc->sc_acpinode = NULL;
281f1e8be7fSandvar #endif
28239de1096Sbouyer 
28339de1096Sbouyer 	if (sc->sc_acpinode) {
284f1e8be7fSandvar #ifdef I2C_USE_ACPI
28539de1096Sbouyer 		sc->sc_dwiic.sc_iba.iba_child_devices =
286172e088eSjmcneill 		    acpi_enter_i2c_devs(NULL, sc->sc_acpinode);
287f1e8be7fSandvar #endif
28839de1096Sbouyer 	} else {
28939de1096Sbouyer 		aprint_verbose_dev(self, "no matching ACPI node\n");
29039de1096Sbouyer 	}
29139de1096Sbouyer 
292838ba19bSriastradh 	if (!dwiic_attach(&sc->sc_dwiic))
293838ba19bSriastradh 		goto out;
29439de1096Sbouyer 
295c7fb772bSthorpej 	config_found(self, &sc->sc_dwiic.sc_iba, iicbus_print, CFARGS_NONE);
2966f07e526Sjakllsch 
29739de1096Sbouyer 	pmf_device_register(self, dwiic_suspend, dwiic_resume);
29839de1096Sbouyer 
29939de1096Sbouyer out:
30039de1096Sbouyer 	return;
30139de1096Sbouyer }
30239de1096Sbouyer 
30339de1096Sbouyer static bool
30439de1096Sbouyer dwiic_pci_power(struct dwiic_softc *dwsc, bool power)
30539de1096Sbouyer {
3062ce73196Sriastradh 	struct pci_dwiic_softc *sc = container_of(dwsc, struct pci_dwiic_softc,
3072ce73196Sriastradh 	    sc_dwiic);
3082ce73196Sriastradh 	pcireg_t pmreg, csr;
3092ce73196Sriastradh 	uint32_t reset, rlo, rhi;
31039de1096Sbouyer 
3112ce73196Sriastradh 	csr = pci_conf_read(sc->sc_pc, sc->sc_ptag, PCI_COMMAND_STATUS_REG);
3122ce73196Sriastradh 	reset = lpss_read(sc, LPSS_RESET);
3132ce73196Sriastradh 	rlo = lpss_read(sc, LPSS_REMAP_LO);
3142ce73196Sriastradh 	rhi = lpss_read(sc, LPSS_REMAP_HI);
3152ce73196Sriastradh 	aprint_debug_dev(dwsc->sc_dev,
3162ce73196Sriastradh 	    "status 0x%x reset 0x%x rlo 0x%x rhi 0x%x\n",
3172ce73196Sriastradh 	    csr, reset, rlo, rhi);
31839de1096Sbouyer 
31939de1096Sbouyer 	if (!power)
32039de1096Sbouyer 		lpss_write(sc, LPSS_CLKGATE, LPSS_CLKGATE_CTRL_OFF);
32139de1096Sbouyer 	if (pci_get_capability(sc->sc_pc, sc->sc_ptag, PCI_CAP_PWRMGMT,
32239de1096Sbouyer 	    &pmreg, NULL)) {
32339de1096Sbouyer 		DPRINTF(("%s: power status 0x%x", device_xname(dwsc->sc_dev),
32439de1096Sbouyer 		    pci_conf_read(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR)));
32539de1096Sbouyer 		pci_conf_write(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR,
32639de1096Sbouyer 		    power ? PCI_PMCSR_STATE_D0 : PCI_PMCSR_STATE_D3);
32739de1096Sbouyer 		DELAY(10000); /* 10 milliseconds */
32839de1096Sbouyer 		DPRINTF((" -> 0x%x\n",
32939de1096Sbouyer 		    pci_conf_read(sc->sc_pc, sc->sc_ptag, pmreg + PCI_PMCSR)));
33039de1096Sbouyer 	}
33139de1096Sbouyer 	if (power) {
33239de1096Sbouyer 		lpss_write(sc, LPSS_CLKGATE, LPSS_CLKGATE_CTRL_ON);
33339de1096Sbouyer 	}
33439de1096Sbouyer 	return true;
33539de1096Sbouyer }
336