1 /* $OpenBSD: dwiic_acpi.c,v 1.22 2023/07/08 02:43:02 jcs Exp $ */
2 /*
3 * Synopsys DesignWare I2C controller
4 *
5 * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include "iosf.h"
21
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/kernel.h>
25
26 #include <dev/acpi/acpireg.h>
27 #include <dev/acpi/acpivar.h>
28 #include <dev/acpi/acpidev.h>
29 #include <dev/acpi/amltypes.h>
30 #include <dev/acpi/dsdt.h>
31
32 #include <dev/ic/dwiicvar.h>
33 #include <dev/ic/iosfvar.h>
34
35 struct dwiic_crs {
36 int irq_int;
37 uint8_t irq_flags;
38 uint16_t i2c_addr;
39 struct aml_node *devnode;
40 struct aml_node *gpio_int_node;
41 uint16_t gpio_int_pin;
42 uint16_t gpio_int_flags;
43 };
44
45 int dwiic_acpi_match(struct device *, void *, void *);
46 void dwiic_acpi_attach(struct device *, struct device *, void *);
47
48 int dwiic_acpi_parse_crs(int, union acpi_resource *, void *);
49 int dwiic_acpi_found_ihidev(struct dwiic_softc *,
50 struct aml_node *, char *, struct dwiic_crs);
51 int dwiic_acpi_found_iatp(struct dwiic_softc *, struct aml_node *,
52 char *, struct dwiic_crs);
53 int dwiic_acpi_found_ietp(struct dwiic_softc *, struct aml_node *,
54 char *, struct dwiic_crs);
55 void dwiic_acpi_get_params(struct dwiic_softc *, char *, uint16_t *,
56 uint16_t *, uint32_t *);
57 void dwiic_acpi_power(struct dwiic_softc *, int);
58 void dwiic_acpi_bus_scan(struct device *,
59 struct i2cbus_attach_args *, void *);
60
61 #if NIOSF > 0
62 int dwiic_acpi_acquire_bus(void *, int);
63 void dwiic_acpi_release_bus(void *, int);
64 #endif
65
66 const struct cfattach dwiic_acpi_ca = {
67 sizeof(struct dwiic_softc),
68 dwiic_acpi_match,
69 dwiic_acpi_attach,
70 NULL,
71 dwiic_activate
72 };
73
74 const char *dwiic_hids[] = {
75 "AMDI0010",
76 "APMC0D0F",
77 "INT33C2",
78 "INT33C3",
79 "INT3432",
80 "INT3433",
81 "80860F41",
82 "808622C1",
83 NULL
84 };
85
86 const char *ihidev_hids[] = {
87 "PNP0C50",
88 "ACPI0C50",
89 NULL
90 };
91
92 const char *ietp_hids[] = {
93 "ELAN0000",
94 "ELAN0100",
95 "ELAN0600",
96 "ELAN0601",
97 "ELAN0602",
98 "ELAN0603",
99 "ELAN0604",
100 "ELAN0605",
101 "ELAN0606",
102 "ELAN0607",
103 "ELAN0608",
104 "ELAN0609",
105 "ELAN060B",
106 "ELAN060C",
107 "ELAN060F",
108 "ELAN0610",
109 "ELAN0611",
110 "ELAN0612",
111 "ELAN0615",
112 "ELAN0616",
113 "ELAN0617",
114 "ELAN0618",
115 "ELAN0619",
116 "ELAN061A",
117 "ELAN061B",
118 "ELAN061C",
119 "ELAN061D",
120 "ELAN061E",
121 "ELAN061F",
122 "ELAN0620",
123 "ELAN0621",
124 "ELAN0622",
125 "ELAN0623",
126 "ELAN0624",
127 "ELAN0625",
128 "ELAN0626",
129 "ELAN0627",
130 "ELAN0628",
131 "ELAN0629",
132 "ELAN062A",
133 "ELAN062B",
134 "ELAN062C",
135 "ELAN062D",
136 "ELAN062E", /* Lenovo V340 Whiskey Lake U */
137 "ELAN062F", /* Lenovo V340 Comet Lake U */
138 "ELAN0631",
139 "ELAN0632",
140 "ELAN0633", /* Lenovo S145 */
141 "ELAN0634", /* Lenovo V340 Ice lake */
142 "ELAN0635", /* Lenovo V1415-IIL */
143 "ELAN0636", /* Lenovo V1415-Dali */
144 "ELAN0637", /* Lenovo V1415-IGLR */
145 "ELAN1000",
146 NULL
147 };
148
149 const char *iatp_hids[] = {
150 "ATML0000",
151 "ATML0001",
152 NULL
153 };
154
155 int
dwiic_acpi_match(struct device * parent,void * match,void * aux)156 dwiic_acpi_match(struct device *parent, void *match, void *aux)
157 {
158 struct acpi_attach_args *aaa = aux;
159 struct cfdata *cf = match;
160
161 if (aaa->aaa_naddr < 1)
162 return 0;
163 return acpi_matchhids(aaa, dwiic_hids, cf->cf_driver->cd_name);
164 }
165
166 void
dwiic_acpi_attach(struct device * parent,struct device * self,void * aux)167 dwiic_acpi_attach(struct device *parent, struct device *self, void *aux)
168 {
169 struct dwiic_softc *sc = (struct dwiic_softc *)self;
170 struct acpi_attach_args *aaa = aux;
171 struct aml_value res;
172 struct dwiic_crs crs;
173 uint64_t sem;
174
175 sc->sc_acpi = (struct acpi_softc *)parent;
176 sc->sc_devnode = aaa->aaa_node;
177 memcpy(&sc->sc_hid, aaa->aaa_dev, sizeof(sc->sc_hid));
178
179 printf(" %s", sc->sc_devnode->name);
180
181 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) {
182 printf(", no _CRS method\n");
183 return;
184 }
185 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) {
186 printf(", invalid _CRS object (type %d len %d)\n",
187 res.type, res.length);
188 aml_freevalue(&res);
189 return;
190 }
191 memset(&crs, 0, sizeof(crs));
192 crs.devnode = sc->sc_devnode;
193 aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
194 aml_freevalue(&res);
195
196 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]);
197
198 sc->sc_iot = aaa->aaa_bst[0];
199 if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0],
200 0, &sc->sc_ioh)) {
201 printf(": can't map registers\n");
202 return;
203 }
204
205 /* power up the controller */
206 dwiic_acpi_power(sc, 1);
207
208 /* fetch timing parameters */
209 dwiic_acpi_get_params(sc, "SSCN", &sc->ss_hcnt, &sc->ss_lcnt, NULL);
210 dwiic_acpi_get_params(sc, "FMCN", &sc->fs_hcnt, &sc->fs_lcnt,
211 &sc->sda_hold_time);
212
213 if (dwiic_init(sc)) {
214 printf(", failed initializing\n");
215 bus_space_unmap(sc->sc_iot, sc->sc_ioh, aaa->aaa_size[0]);
216 return;
217 }
218
219 /* leave the controller disabled */
220 dwiic_write(sc, DW_IC_INTR_MASK, 0);
221 dwiic_enable(sc, 0);
222 dwiic_read(sc, DW_IC_CLR_INTR);
223
224 /* try to register interrupt with apic, but not fatal without it */
225 if (aaa->aaa_nirq > 0) {
226 printf(" irq %d", aaa->aaa_irq[0]);
227
228 sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0],
229 IPL_BIO, dwiic_intr, sc, sc->sc_dev.dv_xname);
230 if (sc->sc_ih == NULL)
231 printf(": can't establish interrupt");
232 }
233
234 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
235 "_SEM", 0, NULL, &sem))
236 sem = 0;
237
238 if (sem)
239 printf(", sem");
240
241 printf("\n");
242
243 rw_init(&sc->sc_i2c_lock, "iiclk");
244
245 /* setup and attach iic bus */
246 sc->sc_i2c_tag.ic_cookie = sc;
247 sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus;
248 sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus;
249 sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec;
250 sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish;
251 sc->sc_i2c_tag.ic_intr_disestablish = dwiic_i2c_intr_disestablish;
252 sc->sc_i2c_tag.ic_intr_string = dwiic_i2c_intr_string;
253
254 #if NIOSF > 0
255 if (sem) {
256 sc->sc_i2c_tag.ic_acquire_bus = dwiic_acpi_acquire_bus;
257 sc->sc_i2c_tag.ic_release_bus = dwiic_acpi_release_bus;
258 }
259 #endif
260
261 bzero(&sc->sc_iba, sizeof(sc->sc_iba));
262 sc->sc_iba.iba_name = "iic";
263 sc->sc_iba.iba_tag = &sc->sc_i2c_tag;
264 sc->sc_iba.iba_bus_scan = dwiic_acpi_bus_scan;
265 sc->sc_iba.iba_bus_scan_arg = sc;
266
267 config_found((struct device *)sc, &sc->sc_iba, iicbus_print);
268
269 #ifndef SMALL_KERNEL
270 sc->sc_devnode->i2c = &sc->sc_i2c_tag;
271 acpi_register_gsb(sc->sc_acpi, sc->sc_devnode);
272 #endif
273 }
274
275 int
dwiic_acpi_parse_crs(int crsidx,union acpi_resource * crs,void * arg)276 dwiic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg)
277 {
278 struct dwiic_crs *sc_crs = arg;
279 struct aml_node *node;
280 uint16_t pin;
281 uint8_t flags;
282
283 switch (AML_CRSTYPE(crs)) {
284 case SR_IRQ:
285 sc_crs->irq_int = ffs(letoh16(crs->sr_irq.irq_mask)) - 1;
286 /* Default is exclusive, active-high, edge triggered. */
287 if (AML_CRSLEN(crs) < 4)
288 flags = SR_IRQ_MODE;
289 else
290 flags = crs->sr_irq.irq_flags;
291 /* Map flags to those of the extended interrupt descriptor. */
292 if (flags & SR_IRQ_SHR)
293 sc_crs->irq_flags |= LR_EXTIRQ_SHR;
294 if (flags & SR_IRQ_POLARITY)
295 sc_crs->irq_flags |= LR_EXTIRQ_POLARITY;
296 if (flags & SR_IRQ_MODE)
297 sc_crs->irq_flags |= LR_EXTIRQ_MODE;
298 break;
299
300 case LR_EXTIRQ:
301 sc_crs->irq_int = letoh32(crs->lr_extirq.irq[0]);
302 sc_crs->irq_flags = crs->lr_extirq.flags;
303 break;
304
305 case LR_GPIO:
306 node = aml_searchname(sc_crs->devnode,
307 (char *)&crs->pad[crs->lr_gpio.res_off]);
308 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
309 if (crs->lr_gpio.type == LR_GPIO_INT) {
310 sc_crs->gpio_int_node = node;
311 sc_crs->gpio_int_pin = pin;
312 sc_crs->gpio_int_flags = crs->lr_gpio.tflags;
313 }
314 break;
315
316 case LR_SERBUS:
317 if (crs->lr_serbus.type == LR_SERBUS_I2C)
318 sc_crs->i2c_addr = letoh16(crs->lr_i2cbus._adr);
319 break;
320
321 case LR_MEM32:
322 case LR_MEM32FIXED:
323 break;
324
325 default:
326 DPRINTF(("%s: unknown resource type %d\n", __func__,
327 AML_CRSTYPE(crs)));
328 }
329
330 return 0;
331 }
332
333 void
dwiic_acpi_get_params(struct dwiic_softc * sc,char * method,uint16_t * hcnt,uint16_t * lcnt,uint32_t * sda_hold_time)334 dwiic_acpi_get_params(struct dwiic_softc *sc, char *method, uint16_t *hcnt,
335 uint16_t *lcnt, uint32_t *sda_hold_time)
336 {
337 struct aml_value res;
338
339 if (!aml_searchname(sc->sc_devnode, method))
340 return;
341
342 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, method, 0, NULL, &res)) {
343 printf(": eval of %s at %s failed", method,
344 aml_nodename(sc->sc_devnode));
345 return;
346 }
347
348 if (res.type != AML_OBJTYPE_PACKAGE) {
349 printf(": %s is not a package (%d)", method, res.type);
350 aml_freevalue(&res);
351 return;
352 }
353
354 if (res.length <= 2) {
355 printf(": %s returned package of len %d", method, res.length);
356 aml_freevalue(&res);
357 return;
358 }
359
360 *hcnt = aml_val2int(res.v_package[0]);
361 *lcnt = aml_val2int(res.v_package[1]);
362 if (sda_hold_time)
363 *sda_hold_time = aml_val2int(res.v_package[2]);
364 aml_freevalue(&res);
365 }
366
367 void
dwiic_acpi_bus_scan(struct device * iic,struct i2cbus_attach_args * iba,void * aux)368 dwiic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba,
369 void *aux)
370 {
371 struct dwiic_softc *sc = (struct dwiic_softc *)aux;
372
373 sc->sc_iic = iic;
374 aml_find_node(sc->sc_devnode, "_HID", dwiic_acpi_found_hid, sc);
375 }
376
377 void *
dwiic_i2c_intr_establish(void * cookie,void * ih,int level,int (* func)(void *),void * arg,const char * name)378 dwiic_i2c_intr_establish(void *cookie, void *ih, int level,
379 int (*func)(void *), void *arg, const char *name)
380 {
381 struct dwiic_crs *crs = ih;
382
383 if (crs->gpio_int_node) {
384 if (!crs->gpio_int_node->gpio)
385 /* found ACPI device but no driver for it */
386 return NULL;
387
388 struct acpi_gpio *gpio = crs->gpio_int_node->gpio;
389 gpio->intr_establish(gpio->cookie, crs->gpio_int_pin,
390 crs->gpio_int_flags, func, arg);
391 return ih;
392 }
393
394 return acpi_intr_establish(crs->irq_int, crs->irq_flags,
395 level, func, arg, name);
396 }
397
398 void
dwiic_i2c_intr_disestablish(void * cookie,void * ih)399 dwiic_i2c_intr_disestablish(void *cookie, void *ih)
400 {
401 /* XXX GPIO interrupts */
402 acpi_intr_disestablish(ih);
403 }
404
405 const char *
dwiic_i2c_intr_string(void * cookie,void * ih)406 dwiic_i2c_intr_string(void *cookie, void *ih)
407 {
408 struct dwiic_crs *crs = ih;
409 static char irqstr[64];
410
411 if (crs->gpio_int_node) {
412 if (crs->gpio_int_node->gpio)
413 snprintf(irqstr, sizeof(irqstr), "gpio %d",
414 crs->gpio_int_pin);
415 } else
416 snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int);
417
418 return irqstr;
419 }
420
421 int
dwiic_matchhids(const char * hid,const char * hids[])422 dwiic_matchhids(const char *hid, const char *hids[])
423 {
424 int i;
425
426 for (i = 0; hids[i]; i++)
427 if (!strcmp(hid, hids[i]))
428 return (1);
429
430 return (0);
431 }
432
433 int
dwiic_acpi_found_hid(struct aml_node * node,void * arg)434 dwiic_acpi_found_hid(struct aml_node *node, void *arg)
435 {
436 struct dwiic_softc *sc = (struct dwiic_softc *)arg;
437 struct dwiic_crs crs;
438 struct aml_value res;
439 int64_t sta;
440 char cdev[16], dev[16];
441 struct i2c_attach_args ia;
442
443 /* Skip our own _HID. */
444 if (node->parent == sc->sc_devnode)
445 return 0;
446
447 if (acpi_parsehid(node, arg, cdev, dev, 16) != 0)
448 return 0;
449
450 if (aml_evalinteger(acpi_softc, node->parent, "_STA", 0, NULL, &sta))
451 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
452
453 if ((sta & STA_PRESENT) == 0)
454 return 0;
455
456 DPRINTF(("%s: found HID %s at %s\n", sc->sc_dev.dv_xname, dev,
457 aml_nodename(node)));
458
459 if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res))
460 return 0;
461
462 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) {
463 printf("%s: invalid _CRS object (type %d len %d)\n",
464 sc->sc_dev.dv_xname, res.type, res.length);
465 aml_freevalue(&res);
466 return (0);
467 }
468 memset(&crs, 0, sizeof(crs));
469 crs.devnode = sc->sc_devnode;
470 aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
471 aml_freevalue(&res);
472
473 acpi_attach_deps(acpi_softc, node->parent);
474
475 if (dwiic_matchhids(cdev, ihidev_hids))
476 return dwiic_acpi_found_ihidev(sc, node, dev, crs);
477 else if (dwiic_matchhids(dev, iatp_hids))
478 return dwiic_acpi_found_iatp(sc, node, dev, crs);
479 else if (dwiic_matchhids(dev, ietp_hids) || dwiic_matchhids(cdev, ietp_hids))
480 return dwiic_acpi_found_ietp(sc, node, dev, crs);
481
482 memset(&ia, 0, sizeof(ia));
483 ia.ia_tag = sc->sc_iba.iba_tag;
484 ia.ia_name = dev;
485 ia.ia_addr = crs.i2c_addr;
486 ia.ia_cookie = node->parent;
487
488 if (crs.irq_int != 0 || crs.gpio_int_node != NULL)
489 ia.ia_intr = &crs;
490
491 config_found(sc->sc_iic, &ia, dwiic_i2c_print);
492 node->parent->attached = 1;
493
494 return 0;
495 }
496
497 int
dwiic_acpi_found_ihidev(struct dwiic_softc * sc,struct aml_node * node,char * dev,struct dwiic_crs crs)498 dwiic_acpi_found_ihidev(struct dwiic_softc *sc, struct aml_node *node,
499 char *dev, struct dwiic_crs crs)
500 {
501 struct i2c_attach_args ia;
502 struct aml_value cmd[4], res;
503
504 /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */
505 static uint8_t i2c_hid_guid[] = {
506 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
507 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
508 };
509
510 if (!aml_searchname(node->parent, "_DSM")) {
511 printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname,
512 aml_nodename(node->parent));
513 return 0;
514 }
515
516 bzero(&cmd, sizeof(cmd));
517 cmd[0].type = AML_OBJTYPE_BUFFER;
518 cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid;
519 cmd[0].length = sizeof(i2c_hid_guid);
520 /* rev */
521 cmd[1].type = AML_OBJTYPE_INTEGER;
522 cmd[1].v_integer = 1;
523 cmd[1].length = 1;
524 /* func */
525 cmd[2].type = AML_OBJTYPE_INTEGER;
526 cmd[2].v_integer = 1; /* HID */
527 cmd[2].length = 1;
528 /* not used */
529 cmd[3].type = AML_OBJTYPE_PACKAGE;
530 cmd[3].length = 0;
531
532 if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) {
533 printf("%s: eval of _DSM at %s failed\n",
534 sc->sc_dev.dv_xname, aml_nodename(node->parent));
535 return 0;
536 }
537
538 if (res.type != AML_OBJTYPE_INTEGER) {
539 printf("%s: bad _DSM result at %s: %d\n",
540 sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type);
541 aml_freevalue(&res);
542 return 0;
543 }
544
545 memset(&ia, 0, sizeof(ia));
546 ia.ia_tag = sc->sc_iba.iba_tag;
547 ia.ia_size = 1;
548 ia.ia_name = "ihidev";
549 ia.ia_size = aml_val2int(&res); /* hid descriptor address */
550 ia.ia_addr = crs.i2c_addr;
551 ia.ia_cookie = dev;
552
553 aml_freevalue(&res);
554
555 if (sc->sc_poll_ihidev)
556 ia.ia_poll = 1;
557 if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL))
558 ia.ia_intr = &crs;
559
560 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) {
561 node->parent->attached = 1;
562 return 0;
563 }
564
565 return 1;
566 }
567
568 int
dwiic_acpi_found_ietp(struct dwiic_softc * sc,struct aml_node * node,char * dev,struct dwiic_crs crs)569 dwiic_acpi_found_ietp(struct dwiic_softc *sc, struct aml_node *node,
570 char *dev, struct dwiic_crs crs)
571 {
572 struct i2c_attach_args ia;
573
574 memset(&ia, 0, sizeof(ia));
575 ia.ia_tag = sc->sc_iba.iba_tag;
576 ia.ia_size = 1;
577 ia.ia_name = "ietp";
578 ia.ia_addr = crs.i2c_addr;
579 ia.ia_cookie = dev;
580
581 if (sc->sc_poll_ihidev)
582 ia.ia_poll = 1;
583 if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL))
584 ia.ia_intr = &crs;
585
586 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) {
587 node->parent->attached = 1;
588 return 0;
589 }
590
591 return 1;
592 }
593
594 int
dwiic_acpi_found_iatp(struct dwiic_softc * sc,struct aml_node * node,char * dev,struct dwiic_crs crs)595 dwiic_acpi_found_iatp(struct dwiic_softc *sc, struct aml_node *node, char *dev,
596 struct dwiic_crs crs)
597 {
598 struct i2c_attach_args ia;
599 struct aml_value res;
600
601 if (aml_evalname(acpi_softc, node->parent, "GPIO", 0, NULL, &res))
602 /* no gpio, assume this is the bootloader interface */
603 return (0);
604
605 memset(&ia, 0, sizeof(ia));
606 ia.ia_tag = sc->sc_iba.iba_tag;
607 ia.ia_size = 1;
608 ia.ia_name = "iatp";
609 ia.ia_addr = crs.i2c_addr;
610 ia.ia_cookie = dev;
611
612 if (crs.irq_int <= 0 && crs.gpio_int_node == NULL) {
613 printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname,
614 aml_nodename(node->parent));
615 return 0;
616 }
617 ia.ia_intr = &crs;
618
619 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) {
620 node->parent->attached = 1;
621 return 0;
622 }
623
624 return 1;
625 }
626
627 void
dwiic_acpi_power(struct dwiic_softc * sc,int power)628 dwiic_acpi_power(struct dwiic_softc *sc, int power)
629 {
630 char ps[] = "_PS0";
631
632 if (!power)
633 ps[3] = '3';
634
635 if (aml_searchname(sc->sc_devnode, ps)) {
636 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, ps, 0, NULL,
637 NULL)) {
638 printf("%s: failed powering %s with %s\n",
639 sc->sc_dev.dv_xname, power ? "on" : "off",
640 ps);
641 return;
642 }
643
644 DELAY(10000); /* 10 milliseconds */
645 } else
646 DPRINTF(("%s: no %s method\n", sc->sc_dev.dv_xname, ps));
647
648 if (strcmp(sc->sc_hid, "INT3432") == 0 ||
649 strcmp(sc->sc_hid, "INT3433") == 0) {
650 /*
651 * XXX: broadwell i2c devices may need this for initial power
652 * up and/or after s3 resume.
653 *
654 * linux does this write via LPSS -> clk_register_gate ->
655 * clk_gate_enable -> clk_gate_endisable -> clk_writel
656 */
657 dwiic_write(sc, 0x800, 1);
658 }
659 }
660
661 #if NIOSF > 0
662 extern int iosf_i2c_acquire(int);
663 extern void iosf_i2c_release(int);
664
665 int
dwiic_acpi_acquire_bus(void * cookie,int flags)666 dwiic_acpi_acquire_bus(void *cookie, int flags)
667 {
668 int rv;
669
670 rv = dwiic_i2c_acquire_bus(cookie, flags);
671 if (rv != 0)
672 return (rv);
673
674 return (iosf_i2c_acquire(flags));
675 }
676
677 void
dwiic_acpi_release_bus(void * cookie,int flags)678 dwiic_acpi_release_bus(void *cookie, int flags)
679 {
680 iosf_i2c_release(flags);
681 dwiic_i2c_release_bus(cookie, flags);
682 }
683 #endif /* NIOSF > 0 */
684