xref: /openbsd-src/sys/dev/pci/dwiic_pci.c (revision 4b70baf6e17fc8b27fc1f7fa7929335753fa94c3)
1 /* $OpenBSD: dwiic_pci.c,v 1.4 2019/03/16 02:40:43 jcs Exp $ */
2 /*
3  * Synopsys DesignWare I2C controller
4  * PCI attachment
5  *
6  * Copyright (c) 2015-2017 joshua stein <jcs@openbsd.org>
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/kernel.h>
24 #include <sys/kthread.h>
25 
26 #include <dev/pci/pcidevs.h>
27 #include <dev/pci/pcireg.h>
28 #include <dev/pci/pcivar.h>
29 
30 #include <dev/ic/dwiicvar.h>
31 
32 /* 13.3: I2C Additional Registers Summary */
33 #define LPSS_RESETS		0x204
34 #define  LPSS_RESETS_I2C	(1 << 0) | (1 << 1)
35 #define  LPSS_RESETS_IDMA	(1 << 2)
36 #define LPSS_ACTIVELTR		0x210
37 #define LPSS_IDLELTR		0x214
38 #define LPSS_CAPS		0x2fc
39 #define  LPSS_CAPS_NO_IDMA	(1 << 8)
40 #define  LPSS_CAPS_TYPE_SHIFT	4
41 #define  LPSS_CAPS_TYPE_MASK	(0xf << LPSS_CAPS_TYPE_SHIFT)
42 
43 int		dwiic_pci_match(struct device *, void *, void *);
44 void		dwiic_pci_attach(struct device *, struct device *, void *);
45 int		dwiic_pci_activate(struct device *, int);
46 void		dwiic_pci_bus_scan(struct device *,
47 		    struct i2cbus_attach_args *, void *);
48 
49 #include "acpi.h"
50 #if NACPI > 0
51 struct aml_node *acpi_pci_match(struct device *dev, struct pci_attach_args *pa);
52 #endif
53 
54 struct cfattach dwiic_pci_ca = {
55 	sizeof(struct dwiic_softc),
56 	dwiic_pci_match,
57 	dwiic_pci_attach,
58 	NULL,
59 	dwiic_pci_activate,
60 };
61 
62 const struct pci_matchid dwiic_pci_ids[] = {
63 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_I2C_1 },
64 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_I2C_2 },
65 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_1 },
66 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_2 },
67 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_3 },
68 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_4 },
69 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_5 },
70 	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_6 },
71 };
72 
73 int
74 dwiic_pci_match(struct device *parent, void *match, void *aux)
75 {
76 	return (pci_matchbyid(aux, dwiic_pci_ids, nitems(dwiic_pci_ids)));
77 }
78 
79 void
80 dwiic_pci_attach(struct device *parent, struct device *self, void *aux)
81 {
82 	struct dwiic_softc *sc = (struct dwiic_softc *)self;
83 	struct pci_attach_args *pa = aux;
84 #if NACPI > 0
85 	struct aml_node *node;
86 #endif
87 	bus_size_t iosize;
88 	pci_intr_handle_t ih;
89 	const char *intrstr = NULL;
90 	uint8_t type;
91 
92 	memcpy(&sc->sc_paa, pa, sizeof(sc->sc_paa));
93 
94 	pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
95 
96 	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_MEM_TYPE_64BIT, 0,
97 	    &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) {
98 		printf(": can't map mem space\n");
99 		return;
100 	}
101 
102 	sc->sc_caps = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LPSS_CAPS);
103 	type = sc->sc_caps & LPSS_CAPS_TYPE_MASK;
104 	type >>= LPSS_CAPS_TYPE_SHIFT;
105 	if (type != 0) {
106 		printf(": type %d not supported\n", type);
107 		return;
108 	}
109 
110 	/* un-reset - page 958 */
111 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, LPSS_RESETS,
112 	    (LPSS_RESETS_I2C | LPSS_RESETS_IDMA));
113 
114 	/* fetch timing parameters */
115 	sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT);
116 	sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT);
117 	sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT);
118 	sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT);
119 	sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD);
120 
121 #if NACPI > 0
122 	/* fetch more accurate timing parameters from ACPI, if possible */
123 	node = acpi_pci_match(self, &sc->sc_paa);
124 	if (node != NULL) {
125 		sc->sc_devnode = node;
126 
127 		dwiic_acpi_get_params(sc, "SSCN", &sc->ss_hcnt, &sc->ss_lcnt,
128 		    NULL);
129 		dwiic_acpi_get_params(sc, "FMCN", &sc->fs_hcnt, &sc->fs_lcnt,
130 		    &sc->sda_hold_time);
131 	}
132 #endif
133 
134 	if (dwiic_init(sc)) {
135 		printf(": failed initializing\n");
136 		return;
137 	}
138 
139 	/* leave the controller disabled */
140 	dwiic_write(sc, DW_IC_INTR_MASK, 0);
141 	dwiic_enable(sc, 0);
142 	dwiic_read(sc, DW_IC_CLR_INTR);
143 
144 	/* install interrupt handler */
145 	sc->sc_poll = 1;
146 	if (pci_intr_map(&sc->sc_paa, &ih) == 0) {
147 		intrstr = pci_intr_string(sc->sc_paa.pa_pc, ih);
148 		sc->sc_ih = pci_intr_establish(sc->sc_paa.pa_pc, ih, IPL_BIO,
149 		    dwiic_intr, sc, sc->sc_dev.dv_xname);
150 		if (sc->sc_ih != NULL) {
151 			printf(": %s", intrstr);
152 			sc->sc_poll = 0;
153 		}
154 	}
155 	if (sc->sc_poll)
156 		printf(": polling");
157 
158 	printf("\n");
159 
160 	rw_init(&sc->sc_i2c_lock, "iiclk");
161 
162 	/* setup and attach iic bus */
163 	sc->sc_i2c_tag.ic_cookie = sc;
164 	sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus;
165 	sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus;
166 	sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec;
167 	sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish;
168 	sc->sc_i2c_tag.ic_intr_string = dwiic_i2c_intr_string;
169 
170 	bzero(&sc->sc_iba, sizeof(sc->sc_iba));
171 	sc->sc_iba.iba_name = "iic";
172 	sc->sc_iba.iba_tag = &sc->sc_i2c_tag;
173 	sc->sc_iba.iba_bus_scan = dwiic_pci_bus_scan;
174 	sc->sc_iba.iba_bus_scan_arg = sc;
175 
176 	config_found((struct device *)sc, &sc->sc_iba, iicbus_print);
177 
178 	return;
179 }
180 
181 int
182 dwiic_pci_activate(struct device *self, int act)
183 {
184 	struct dwiic_softc *sc = (struct dwiic_softc *)self;
185 
186 	switch (act) {
187 	case DVACT_WAKEUP:
188 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, LPSS_RESETS,
189 		    (LPSS_RESETS_I2C | LPSS_RESETS_IDMA));
190 
191 		dwiic_init(sc);
192 
193 		break;
194 	}
195 
196 	dwiic_activate(self, act);
197 
198 	return 0;
199 }
200 
201 void
202 dwiic_pci_bus_scan(struct device *iic, struct i2cbus_attach_args *iba,
203     void *aux)
204 {
205 	struct dwiic_softc *sc = (struct dwiic_softc *)aux;
206 
207 	sc->sc_iic = iic;
208 
209 	if (sc->sc_devnode != NULL) {
210 		/*
211 		 * XXX: until we can figure out why interrupts don't arrive for
212 		 * i2c slave devices on intel 100 series and newer, force
213 		 * polling for ihidev.
214 		 */
215 		sc->sc_poll_ihidev = 1;
216 
217 		aml_find_node(sc->sc_devnode, "_HID", dwiic_acpi_found_hid, sc);
218 	}
219 }
220