LCOV - code coverage report
Current view: top level - dev/acpi - dwiic_acpi.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 270 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: dwiic_acpi.c,v 1.8 2018/07/01 11:37:11 kettenis 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 <sys/param.h>
      21             : #include <sys/systm.h>
      22             : #include <sys/kernel.h>
      23             : #include <sys/kthread.h>
      24             : 
      25             : #include <dev/acpi/acpireg.h>
      26             : #include <dev/acpi/acpivar.h>
      27             : #include <dev/acpi/acpidev.h>
      28             : #include <dev/acpi/amltypes.h>
      29             : #include <dev/acpi/dsdt.h>
      30             : 
      31             : #include <dev/ic/dwiicvar.h>
      32             : 
      33             : struct dwiic_crs {
      34             :         int irq_int;
      35             :         uint8_t irq_flags;
      36             :         uint32_t addr_min;
      37             :         uint32_t addr_bas;
      38             :         uint32_t addr_len;
      39             :         uint16_t i2c_addr;
      40             :         struct aml_node *devnode;
      41             :         struct aml_node *gpio_int_node;
      42             :         uint16_t gpio_int_pin;
      43             :         uint16_t gpio_int_flags;
      44             : };
      45             : 
      46             : int             dwiic_acpi_match(struct device *, void *, void *);
      47             : void            dwiic_acpi_attach(struct device *, struct device *, void *);
      48             : 
      49             : int             dwiic_acpi_parse_crs(int, union acpi_resource *, void *);
      50             : int             dwiic_acpi_found_ihidev(struct dwiic_softc *,
      51             :                     struct aml_node *, char *, struct dwiic_crs);
      52             : int             dwiic_acpi_found_iatp(struct dwiic_softc *, struct aml_node *,
      53             :                     char *, struct dwiic_crs);
      54             : void            dwiic_acpi_get_params(struct dwiic_softc *, char *, uint16_t *,
      55             :                     uint16_t *, uint32_t *);
      56             : void            dwiic_acpi_power(struct dwiic_softc *, int);
      57             : void            dwiic_acpi_bus_scan(struct device *,
      58             :                     struct i2cbus_attach_args *, void *);
      59             : 
      60             : struct cfattach dwiic_acpi_ca = {
      61             :         sizeof(struct dwiic_softc),
      62             :         dwiic_acpi_match,
      63             :         dwiic_acpi_attach,
      64             :         NULL,
      65             :         dwiic_activate
      66             : };
      67             : 
      68             : const char *dwiic_hids[] = {
      69             :         "INT33C2",
      70             :         "INT33C3",
      71             :         "INT3432",
      72             :         "INT3433",
      73             :         "80860F41",
      74             :         "808622C1",
      75             :         NULL
      76             : };
      77             : 
      78             : const char *ihidev_hids[] = {
      79             :         "PNP0C50",
      80             :         "ACPI0C50",
      81             :         NULL
      82             : };
      83             : 
      84             : const char *iatp_hids[] = {
      85             :         "ATML0000",
      86             :         "ATML0001",
      87             :         NULL
      88             : };
      89             : 
      90             : int
      91           0 : dwiic_acpi_match(struct device *parent, void *match, void *aux)
      92             : {
      93           0 :         struct acpi_attach_args *aaa = aux;
      94           0 :         struct cfdata *cf = match;
      95             : 
      96           0 :         return acpi_matchhids(aaa, dwiic_hids, cf->cf_driver->cd_name);
      97             : }
      98             : 
      99             : void
     100           0 : dwiic_acpi_attach(struct device *parent, struct device *self, void *aux)
     101             : {
     102           0 :         struct dwiic_softc *sc = (struct dwiic_softc *)self;
     103           0 :         struct acpi_attach_args *aa = aux;
     104           0 :         struct aml_value res;
     105           0 :         struct dwiic_crs crs;
     106             : 
     107           0 :         sc->sc_acpi = (struct acpi_softc *)parent;
     108           0 :         sc->sc_devnode = aa->aaa_node;
     109           0 :         memcpy(&sc->sc_hid, aa->aaa_dev, sizeof(sc->sc_hid));
     110             : 
     111           0 :         printf(" %s", sc->sc_devnode->name);
     112             : 
     113           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) {
     114           0 :                 printf(", no _CRS method\n");
     115           0 :                 return;
     116             :         }
     117           0 :         if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) {
     118           0 :                 printf(", invalid _CRS object (type %d len %d)\n",
     119           0 :                     res.type, res.length);
     120           0 :                 aml_freevalue(&res);
     121           0 :                 return;
     122             :         }
     123           0 :         memset(&crs, 0, sizeof(crs));
     124           0 :         crs.devnode = sc->sc_devnode;
     125           0 :         aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
     126           0 :         aml_freevalue(&res);
     127             : 
     128           0 :         if (crs.addr_bas == 0) {
     129           0 :                 printf(", can't find address\n");
     130           0 :                 return;
     131             :         }
     132             : 
     133           0 :         printf(" addr 0x%x/0x%x", crs.addr_bas, crs.addr_len);
     134             : 
     135           0 :         sc->sc_iot = aa->aaa_memt;
     136           0 :         if (bus_space_map(sc->sc_iot, crs.addr_bas, crs.addr_len, 0,
     137           0 :             &sc->sc_ioh)) {
     138           0 :                 printf(", failed mapping at 0x%x\n", crs.addr_bas);
     139           0 :                 return;
     140             :         }
     141             : 
     142             :         /* power up the controller */
     143           0 :         dwiic_acpi_power(sc, 1);
     144             : 
     145             :         /* fetch timing parameters */
     146           0 :         sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT);
     147           0 :         sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT);
     148           0 :         sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT);
     149           0 :         sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT);
     150           0 :         sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD);
     151           0 :         dwiic_acpi_get_params(sc, "SSCN", &sc->ss_hcnt, &sc->ss_lcnt, NULL);
     152           0 :         dwiic_acpi_get_params(sc, "FMCN", &sc->fs_hcnt, &sc->fs_lcnt,
     153             :             &sc->sda_hold_time);
     154             : 
     155           0 :         if (dwiic_init(sc)) {
     156           0 :                 printf(", failed initializing\n");
     157           0 :                 bus_space_unmap(sc->sc_iot, sc->sc_ioh, crs.addr_len);
     158           0 :                 return;
     159             :         }
     160             : 
     161             :         /* leave the controller disabled */
     162           0 :         dwiic_write(sc, DW_IC_INTR_MASK, 0);
     163           0 :         dwiic_enable(sc, 0);
     164           0 :         dwiic_read(sc, DW_IC_CLR_INTR);
     165             : 
     166             :         /* try to register interrupt with apic, but not fatal without it */
     167           0 :         if (crs.irq_int > 0) {
     168           0 :                 printf(" irq %d", crs.irq_int);
     169             : 
     170           0 :                 sc->sc_ih = acpi_intr_establish(crs.irq_int, crs.irq_flags,
     171           0 :                     IPL_BIO, dwiic_intr, sc, sc->sc_dev.dv_xname);
     172           0 :                 if (sc->sc_ih == NULL)
     173           0 :                         printf(", can't establish interrupt");
     174             :         }
     175             : 
     176           0 :         printf("\n");
     177             : 
     178           0 :         rw_init(&sc->sc_i2c_lock, "iiclk");
     179             : 
     180             :         /* setup and attach iic bus */
     181           0 :         sc->sc_i2c_tag.ic_cookie = sc;
     182           0 :         sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus;
     183           0 :         sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus;
     184           0 :         sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec;
     185           0 :         sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish;
     186           0 :         sc->sc_i2c_tag.ic_intr_string = dwiic_i2c_intr_string;
     187             : 
     188           0 :         bzero(&sc->sc_iba, sizeof(sc->sc_iba));
     189           0 :         sc->sc_iba.iba_name = "iic";
     190           0 :         sc->sc_iba.iba_tag = &sc->sc_i2c_tag;
     191           0 :         sc->sc_iba.iba_bus_scan = dwiic_acpi_bus_scan;
     192           0 :         sc->sc_iba.iba_bus_scan_arg = sc;
     193             : 
     194           0 :         config_found((struct device *)sc, &sc->sc_iba, iicbus_print);
     195             : 
     196             : #ifndef SMALL_KERNEL
     197           0 :         sc->sc_devnode->i2c = &sc->sc_i2c_tag;
     198           0 :         acpi_register_gsb(sc->sc_acpi, sc->sc_devnode);
     199             : #endif
     200             : 
     201           0 :         return;
     202           0 : }
     203             : 
     204             : int
     205           0 : dwiic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg)
     206             : {
     207           0 :         struct dwiic_crs *sc_crs = arg;
     208             :         struct aml_node *node;
     209             :         uint16_t pin;
     210             : 
     211           0 :         switch (AML_CRSTYPE(crs)) {
     212             :         case SR_IRQ:
     213           0 :                 sc_crs->irq_int = ffs(letoh16(crs->sr_irq.irq_mask)) - 1;
     214           0 :                 sc_crs->irq_flags = crs->sr_irq.irq_flags;
     215           0 :                 break;
     216             : 
     217             :         case LR_EXTIRQ:
     218           0 :                 sc_crs->irq_int = letoh32(crs->lr_extirq.irq[0]);
     219           0 :                 sc_crs->irq_flags = crs->lr_extirq.flags;
     220           0 :                 break;
     221             : 
     222             :         case LR_GPIO:
     223           0 :                 node = aml_searchname(sc_crs->devnode,
     224           0 :                     (char *)&crs->pad[crs->lr_gpio.res_off]);
     225           0 :                 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
     226           0 :                 if (crs->lr_gpio.type == LR_GPIO_INT) {
     227           0 :                         sc_crs->gpio_int_node = node;
     228           0 :                         sc_crs->gpio_int_pin = pin;
     229           0 :                         sc_crs->gpio_int_flags = crs->lr_gpio.tflags;
     230           0 :                 }
     231             :                 break;
     232             : 
     233             :         case LR_MEM32:
     234           0 :                 sc_crs->addr_min = letoh32(crs->lr_m32._min);
     235           0 :                 sc_crs->addr_len = letoh32(crs->lr_m32._len);
     236           0 :                 break;
     237             : 
     238             :         case LR_MEM32FIXED:
     239           0 :                 sc_crs->addr_bas = letoh32(crs->lr_m32fixed._bas);
     240           0 :                 sc_crs->addr_len = letoh32(crs->lr_m32fixed._len);
     241           0 :                 break;
     242             : 
     243             :         case LR_SERBUS:
     244           0 :                 if (crs->lr_serbus.type == LR_SERBUS_I2C)
     245           0 :                         sc_crs->i2c_addr = letoh16(crs->lr_i2cbus._adr);
     246             :                 break;
     247             : 
     248             :         default:
     249             :                 DPRINTF(("%s: unknown resource type %d\n", __func__,
     250             :                     AML_CRSTYPE(crs)));
     251             :         }
     252             : 
     253           0 :         return 0;
     254             : }
     255             : 
     256             : void
     257           0 : dwiic_acpi_get_params(struct dwiic_softc *sc, char *method, uint16_t *hcnt,
     258             :     uint16_t *lcnt, uint32_t *sda_hold_time)
     259             : {
     260           0 :         struct aml_value res;
     261             : 
     262           0 :         if (!aml_searchname(sc->sc_devnode, method))
     263           0 :                 return;
     264             : 
     265           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_devnode, method, 0, NULL, &res)) {
     266           0 :                 printf(": eval of %s at %s failed", method,
     267           0 :                     aml_nodename(sc->sc_devnode));
     268           0 :                 return;
     269             :         }
     270             : 
     271           0 :         if (res.type != AML_OBJTYPE_PACKAGE) {
     272           0 :                 printf(": %s is not a package (%d)", method, res.type);
     273           0 :                 aml_freevalue(&res);
     274           0 :                 return;
     275             :         }
     276             : 
     277           0 :         if (res.length <= 2) {
     278           0 :                 printf(": %s returned package of len %d", method, res.length);
     279           0 :                 aml_freevalue(&res);
     280           0 :                 return;
     281             :         }
     282             : 
     283           0 :         *hcnt = aml_val2int(res.v_package[0]);
     284           0 :         *lcnt = aml_val2int(res.v_package[1]);
     285           0 :         if (sda_hold_time)
     286           0 :                 *sda_hold_time = aml_val2int(res.v_package[2]);
     287           0 :         aml_freevalue(&res);
     288           0 : }
     289             : 
     290             : void
     291           0 : dwiic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba,
     292             :     void *aux)
     293             : {
     294           0 :         struct dwiic_softc *sc = (struct dwiic_softc *)aux;
     295             : 
     296           0 :         sc->sc_iic = iic;
     297           0 :         aml_find_node(sc->sc_devnode, "_HID", dwiic_acpi_found_hid, sc);
     298           0 : }
     299             : 
     300             : void *
     301           0 : dwiic_i2c_intr_establish(void *cookie, void *ih, int level,
     302             :     int (*func)(void *), void *arg, const char *name)
     303             : {
     304           0 :         struct dwiic_crs *crs = ih;
     305             : 
     306           0 :         if (crs->gpio_int_node && crs->gpio_int_node->gpio) {
     307             :                 struct acpi_gpio *gpio = crs->gpio_int_node->gpio;
     308           0 :                 gpio->intr_establish(gpio->cookie, crs->gpio_int_pin,
     309           0 :                                      crs->gpio_int_flags, func, arg);
     310             :                 return ih;
     311             :         }
     312             : 
     313           0 :         return acpi_intr_establish(crs->irq_int, crs->irq_flags,
     314             :             level, func, arg, name);
     315           0 : }
     316             : 
     317             : const char *
     318           0 : dwiic_i2c_intr_string(void *cookie, void *ih)
     319             : {
     320           0 :         struct dwiic_crs *crs = ih;
     321             :         static char irqstr[64];
     322             : 
     323           0 :         if (crs->gpio_int_node && crs->gpio_int_node->gpio)
     324           0 :                 snprintf(irqstr, sizeof(irqstr), "gpio %d", crs->gpio_int_pin);
     325             :         else
     326           0 :                 snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int);
     327             : 
     328           0 :         return irqstr;
     329             : }
     330             : 
     331             : int
     332           0 : dwiic_matchhids(const char *hid, const char *hids[])
     333             : {
     334             :         int i;
     335             : 
     336           0 :         for (i = 0; hids[i]; i++)
     337           0 :                 if (!strcmp(hid, hids[i]))
     338           0 :                         return (1);
     339             : 
     340           0 :         return (0);
     341           0 : }
     342             : 
     343             : int
     344           0 : dwiic_acpi_found_hid(struct aml_node *node, void *arg)
     345             : {
     346           0 :         struct dwiic_softc *sc = (struct dwiic_softc *)arg;
     347           0 :         struct dwiic_crs crs;
     348           0 :         struct aml_value res;
     349           0 :         int64_t sta;
     350           0 :         char cdev[16], dev[16];
     351           0 :         struct i2c_attach_args ia;
     352             : 
     353             :         /* Skip our own _HID. */
     354           0 :         if (node->parent == sc->sc_devnode)
     355           0 :                 return 0;
     356             : 
     357           0 :         if (acpi_parsehid(node, arg, cdev, dev, 16) != 0)
     358           0 :                 return 0;
     359             : 
     360           0 :         if (aml_evalinteger(acpi_softc, node->parent, "_STA", 0, NULL, &sta))
     361           0 :                 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
     362             : 
     363           0 :         if ((sta & STA_PRESENT) == 0)
     364           0 :                 return 0;
     365             : 
     366             :         DPRINTF(("%s: found HID %s at %s\n", sc->sc_dev.dv_xname, dev,
     367             :             aml_nodename(node)));
     368             : 
     369           0 :         if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res)) {
     370           0 :                 printf("%s: no _CRS method at %s\n", sc->sc_dev.dv_xname,
     371           0 :                     aml_nodename(node->parent));
     372           0 :                 return (0);
     373             :         }
     374           0 :         if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) {
     375           0 :                 printf("%s: invalid _CRS object (type %d len %d)\n",
     376           0 :                     sc->sc_dev.dv_xname, res.type, res.length);
     377           0 :                 aml_freevalue(&res);
     378           0 :                 return (0);
     379             :         }
     380           0 :         memset(&crs, 0, sizeof(crs));
     381           0 :         crs.devnode = sc->sc_devnode;
     382           0 :         aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
     383           0 :         aml_freevalue(&res);
     384             : 
     385           0 :         acpi_attach_deps(acpi_softc, node->parent);
     386             : 
     387           0 :         if (dwiic_matchhids(cdev, ihidev_hids))
     388           0 :                 return dwiic_acpi_found_ihidev(sc, node, dev, crs);
     389           0 :         else if (dwiic_matchhids(dev, iatp_hids))
     390           0 :                 return dwiic_acpi_found_iatp(sc, node, dev, crs);
     391             : 
     392           0 :         memset(&ia, 0, sizeof(ia));
     393           0 :         ia.ia_tag = sc->sc_iba.iba_tag;
     394           0 :         ia.ia_name = dev;
     395           0 :         ia.ia_addr = crs.i2c_addr;
     396           0 :         ia.ia_cookie = node->parent;
     397             : 
     398           0 :         if (crs.irq_int != 0 || crs.gpio_int_node != NULL)
     399           0 :                 ia.ia_intr = &crs;
     400             : 
     401           0 :         config_found(sc->sc_iic, &ia, dwiic_i2c_print);
     402           0 :         node->parent->attached = 1;
     403             : 
     404           0 :         return 0;
     405           0 : }
     406             : 
     407             : int
     408           0 : dwiic_acpi_found_ihidev(struct dwiic_softc *sc, struct aml_node *node,
     409             :     char *dev, struct dwiic_crs crs)
     410             : {
     411           0 :         struct i2c_attach_args ia;
     412           0 :         struct aml_value cmd[4], res;
     413             : 
     414             :         /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */
     415             :         static uint8_t i2c_hid_guid[] = {
     416             :                 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
     417             :                 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
     418             :         };
     419             : 
     420           0 :         if (!aml_searchname(node->parent, "_DSM")) {
     421           0 :                 printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname,
     422           0 :                     aml_nodename(node->parent));
     423           0 :                 return 0;
     424             :         }
     425             : 
     426           0 :         bzero(&cmd, sizeof(cmd));
     427           0 :         cmd[0].type = AML_OBJTYPE_BUFFER;
     428           0 :         cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid;
     429           0 :         cmd[0].length = sizeof(i2c_hid_guid);
     430             :         /* rev */
     431           0 :         cmd[1].type = AML_OBJTYPE_INTEGER;
     432           0 :         cmd[1].v_integer = 1;
     433           0 :         cmd[1].length = 1;
     434             :         /* func */
     435           0 :         cmd[2].type = AML_OBJTYPE_INTEGER;
     436           0 :         cmd[2].v_integer = 1; /* HID */
     437           0 :         cmd[2].length = 1;
     438             :         /* not used */
     439           0 :         cmd[3].type = AML_OBJTYPE_PACKAGE;
     440           0 :         cmd[3].length = 0;
     441             : 
     442           0 :         if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) {
     443           0 :                 printf("%s: eval of _DSM at %s failed\n",
     444           0 :                     sc->sc_dev.dv_xname, aml_nodename(node->parent));
     445           0 :                 return 0;
     446             :         }
     447             : 
     448           0 :         if (res.type != AML_OBJTYPE_INTEGER) {
     449           0 :                 printf("%s: bad _DSM result at %s: %d\n",
     450           0 :                     sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type);
     451           0 :                 aml_freevalue(&res);
     452           0 :                 return 0;
     453             :         }
     454             : 
     455           0 :         memset(&ia, 0, sizeof(ia));
     456           0 :         ia.ia_tag = sc->sc_iba.iba_tag;
     457           0 :         ia.ia_size = 1;
     458           0 :         ia.ia_name = "ihidev";
     459           0 :         ia.ia_size = aml_val2int(&res); /* hid descriptor address */
     460           0 :         ia.ia_addr = crs.i2c_addr;
     461           0 :         ia.ia_cookie = dev;
     462             : 
     463           0 :         aml_freevalue(&res);
     464             : 
     465           0 :         if (!sc->sc_poll_ihidev &&
     466           0 :             !(crs.irq_int == 0 && crs.gpio_int_node == NULL))
     467           0 :                 ia.ia_intr = &crs;
     468             : 
     469           0 :         if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) {
     470           0 :                 node->parent->attached = 1;
     471           0 :                 return 0;
     472             :         }
     473             : 
     474           0 :         return 1;
     475           0 : }
     476             : 
     477             : int
     478           0 : dwiic_acpi_found_iatp(struct dwiic_softc *sc, struct aml_node *node, char *dev,
     479             :     struct dwiic_crs crs)
     480             : {
     481           0 :         struct i2c_attach_args ia;
     482           0 :         struct aml_value res;
     483             : 
     484           0 :         if (aml_evalname(acpi_softc, node->parent, "GPIO", 0, NULL, &res))
     485             :                 /* no gpio, assume this is the bootloader interface */
     486           0 :                 return (0);
     487             : 
     488           0 :         memset(&ia, 0, sizeof(ia));
     489           0 :         ia.ia_tag = sc->sc_iba.iba_tag;
     490           0 :         ia.ia_size = 1;
     491           0 :         ia.ia_name = "iatp";
     492           0 :         ia.ia_addr = crs.i2c_addr;
     493           0 :         ia.ia_cookie = dev;
     494             : 
     495           0 :         if (crs.irq_int <= 0 && crs.gpio_int_node == NULL) {
     496           0 :                 printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname,
     497           0 :                    aml_nodename(node->parent));
     498           0 :                 return 0;
     499             :         }
     500           0 :         ia.ia_intr = &crs;
     501             : 
     502           0 :         if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) {
     503           0 :                 node->parent->attached = 1;
     504           0 :                 return 0;
     505             :         }
     506             : 
     507           0 :         return 1;
     508           0 : }
     509             : 
     510             : void
     511           0 : dwiic_acpi_power(struct dwiic_softc *sc, int power)
     512             : {
     513           0 :         char ps[] = "_PS0";
     514             : 
     515           0 :         if (!power)
     516           0 :                 ps[3] = '3';
     517             : 
     518           0 :         if (aml_searchname(sc->sc_devnode, ps)) {
     519           0 :                 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, ps, 0, NULL,
     520             :                     NULL)) {
     521           0 :                         printf("%s: failed powering %s with %s\n",
     522           0 :                             sc->sc_dev.dv_xname, power ? "on" : "off",
     523             :                             ps);
     524           0 :                         return;
     525             :                 }
     526             : 
     527           0 :                 DELAY(10000); /* 10 milliseconds */
     528           0 :         } else
     529             :                 DPRINTF(("%s: no %s method\n", sc->sc_dev.dv_xname, ps));
     530             : 
     531           0 :         if (strcmp(sc->sc_hid, "INT3432") == 0 ||
     532           0 :             strcmp(sc->sc_hid, "INT3433") == 0) {
     533             :                 /*
     534             :                  * XXX: broadwell i2c devices may need this for initial power
     535             :                  * up and/or after s3 resume.
     536             :                  *
     537             :                  * linux does this write via LPSS -> clk_register_gate ->
     538             :                  * clk_gate_enable -> clk_gate_endisable -> clk_writel
     539             :                  */
     540           0 :                 dwiic_write(sc, 0x800, 1);
     541           0 :         }
     542           0 : }

Generated by: LCOV version 1.13