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

          Line data    Source code
       1             : /*      $OpenBSD: sdhc_acpi.c,v 1.13 2018/07/01 11:37:11 kettenis Exp $ */
       2             : /*
       3             :  * Copyright (c) 2016 Mark Kettenis
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      10             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      12             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      15             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16             :  */
      17             : 
      18             : #include <sys/param.h>
      19             : #include <sys/malloc.h>
      20             : #include <sys/systm.h>
      21             : 
      22             : #include <dev/acpi/acpireg.h>
      23             : #include <dev/acpi/acpivar.h>
      24             : #include <dev/acpi/acpidev.h>
      25             : #include <dev/acpi/amltypes.h>
      26             : #include <dev/acpi/dsdt.h>
      27             : #undef DEVNAME
      28             : #include <dev/sdmmc/sdhcreg.h>
      29             : #include <dev/sdmmc/sdhcvar.h>
      30             : #include <dev/sdmmc/sdmmcvar.h>
      31             : 
      32             : struct sdhc_acpi_softc {
      33             :         struct sdhc_softc sc;
      34             :         struct acpi_softc *sc_acpi;
      35             :         struct aml_node *sc_node;
      36             : 
      37             :         bus_space_tag_t sc_memt;
      38             :         bus_space_handle_t sc_memh;
      39             :         bus_addr_t sc_addr;
      40             :         bus_size_t sc_size;
      41             : 
      42             :         int sc_irq;
      43             :         int sc_irq_flags;
      44             :         void *sc_ih;
      45             : 
      46             :         struct aml_node *sc_gpio_int_node;
      47             :         struct aml_node *sc_gpio_io_node;
      48             :         uint16_t sc_gpio_int_pin;
      49             :         uint16_t sc_gpio_int_flags;
      50             :         uint16_t sc_gpio_io_pin;
      51             : 
      52             :         struct sdhc_host *sc_host;
      53             : };
      54             : 
      55             : int     sdhc_acpi_match(struct device *, void *, void *);
      56             : void    sdhc_acpi_attach(struct device *, struct device *, void *);
      57             : 
      58             : struct cfattach sdhc_acpi_ca = {
      59             :         sizeof(struct sdhc_acpi_softc), sdhc_acpi_match, sdhc_acpi_attach
      60             : };
      61             : 
      62             : const char *sdhc_hids[] = {
      63             :         "PNP0D40",
      64             :         "INT33BB",
      65             :         "80860F14",
      66             :         "PNP0FFF",
      67             :         NULL
      68             : };
      69             : 
      70             : int     sdhc_acpi_parse_resources(int, union acpi_resource *, void *);
      71             : int     sdhc_acpi_card_detect_nonremovable(struct sdhc_softc *);
      72             : int     sdhc_acpi_card_detect_gpio(struct sdhc_softc *);
      73             : int     sdhc_acpi_card_detect_intr(void *);
      74             : void    sdhc_acpi_power_on(struct sdhc_acpi_softc *, struct aml_node *);
      75             : void    sdhc_acpi_explore(struct sdhc_acpi_softc *);
      76             : 
      77             : int
      78           0 : sdhc_acpi_match(struct device *parent, void *match, void *aux)
      79             : {
      80           0 :         struct acpi_attach_args *aaa = aux;
      81           0 :         struct cfdata *cf = match;
      82             : 
      83           0 :         return acpi_matchhids(aaa, sdhc_hids, cf->cf_driver->cd_name);
      84             : }
      85             : 
      86             : void
      87           0 : sdhc_acpi_attach(struct device *parent, struct device *self, void *aux)
      88             : {
      89           0 :         struct acpi_attach_args *aaa = aux;
      90           0 :         struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)self;
      91           0 :         struct aml_value res;
      92             : 
      93           0 :         sc->sc_acpi = (struct acpi_softc *)parent;
      94           0 :         sc->sc_node = aaa->aaa_node;
      95           0 :         printf(" %s", sc->sc_node->name);
      96             : 
      97           0 :         if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
      98           0 :                 printf(", can't find registers\n");
      99           0 :                 return;
     100             :         }
     101             : 
     102           0 :         aml_parse_resource(&res, sdhc_acpi_parse_resources, sc);
     103           0 :         printf(" addr 0x%lx/0x%lx", sc->sc_addr, sc->sc_size);
     104           0 :         if (sc->sc_addr == 0 || sc->sc_size == 0) {
     105           0 :                 printf("\n");
     106           0 :                 return;
     107             :         }
     108             : 
     109           0 :         printf(" irq %d", sc->sc_irq);
     110             : 
     111           0 :         sc->sc_memt = aaa->aaa_memt;
     112           0 :         if (bus_space_map(sc->sc_memt, sc->sc_addr, sc->sc_size, 0,
     113           0 :             &sc->sc_memh)) {
     114           0 :                 printf(", can't map registers\n");
     115           0 :                 return;
     116             :         }
     117             : 
     118           0 :         sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_BIO,
     119           0 :             sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
     120           0 :         if (sc->sc_ih == NULL) {
     121           0 :                 printf(", can't establish interrupt\n");
     122           0 :                 return;
     123             :         }
     124             : 
     125           0 :         if (sc->sc_gpio_io_node && sc->sc_gpio_io_node->gpio) {
     126           0 :                 sc->sc.sc_card_detect = sdhc_acpi_card_detect_gpio;
     127           0 :                 printf(", gpio");
     128           0 :         }
     129             : 
     130           0 :         printf("\n");
     131             : 
     132           0 :         if (sc->sc_gpio_int_node && sc->sc_gpio_int_node->gpio) {
     133             :                 struct acpi_gpio *gpio = sc->sc_gpio_int_node->gpio;
     134             : 
     135           0 :                 gpio->intr_establish(gpio->cookie, sc->sc_gpio_int_pin,
     136           0 :                     sc->sc_gpio_int_flags, sdhc_acpi_card_detect_intr, sc);
     137           0 :         }
     138             : 
     139           0 :         sdhc_acpi_power_on(sc, sc->sc_node);
     140           0 :         sdhc_acpi_explore(sc);
     141             : 
     142           0 :         sc->sc.sc_host = &sc->sc_host;
     143           0 :         sc->sc.sc_dmat = aaa->aaa_dmat;
     144           0 :         sdhc_host_found(&sc->sc, sc->sc_memt, sc->sc_memh, sc->sc_size, 1, 0);
     145           0 : }
     146             : 
     147             : int
     148           0 : sdhc_acpi_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
     149             : {
     150           0 :         struct sdhc_acpi_softc *sc = arg;
     151           0 :         int type = AML_CRSTYPE(crs);
     152             :         struct aml_node *node;
     153             :         uint16_t pin;
     154             : 
     155           0 :         switch (type) {
     156             :         case LR_MEM32FIXED:
     157           0 :                 sc->sc_addr = crs->lr_m32fixed._bas;
     158           0 :                 sc->sc_size = crs->lr_m32fixed._len;
     159           0 :                 break;
     160             :         case LR_EXTIRQ:
     161           0 :                 sc->sc_irq = crs->lr_extirq.irq[0];
     162           0 :                 sc->sc_irq_flags = crs->lr_extirq.flags;
     163           0 :                 break;
     164             :         case LR_GPIO:
     165           0 :                 node = aml_searchname(sc->sc_node, (char *)&crs->pad[crs->lr_gpio.res_off]);
     166           0 :                 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
     167           0 :                 if (crs->lr_gpio.type == LR_GPIO_INT) {
     168           0 :                         sc->sc_gpio_int_node = node;
     169           0 :                         sc->sc_gpio_int_pin = pin;
     170           0 :                         sc->sc_gpio_int_flags = crs->lr_gpio.tflags;
     171           0 :                 } else if (crs->lr_gpio.type == LR_GPIO_IO) {
     172           0 :                         sc->sc_gpio_io_node = node;
     173           0 :                         sc->sc_gpio_io_pin = pin;
     174           0 :                 }
     175             :                 break;
     176             :         }
     177             : 
     178           0 :         return 0;
     179             : }
     180             : 
     181             : int
     182           0 : sdhc_acpi_card_detect_nonremovable(struct sdhc_softc *ssc)
     183             : {
     184           0 :         return 1;
     185             : }
     186             : 
     187             : int
     188           0 : sdhc_acpi_card_detect_gpio(struct sdhc_softc *ssc)
     189             : {
     190           0 :         struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)ssc;
     191           0 :         struct acpi_gpio *gpio = sc->sc_gpio_io_node->gpio;
     192           0 :         uint16_t pin = sc->sc_gpio_io_pin;
     193             : 
     194             :         /* Card detect GPIO signal is active-low. */
     195           0 :         return !gpio->read_pin(gpio->cookie, pin);
     196             : }
     197             : 
     198             : int
     199           0 : sdhc_acpi_card_detect_intr(void *arg)
     200             : {
     201           0 :         struct sdhc_acpi_softc *sc = arg;
     202             : 
     203           0 :         sdhc_needs_discover(&sc->sc);
     204             : 
     205           0 :         return (1);
     206             : }
     207             : 
     208             : void
     209           0 : sdhc_acpi_power_on(struct sdhc_acpi_softc *sc, struct aml_node *node)
     210             : {
     211           0 :         node = aml_searchname(node, "_PS0");
     212           0 :         if (node && aml_evalnode(sc->sc_acpi, node, 0, NULL, NULL))
     213           0 :                 printf("%s: _PS0 failed\n", sc->sc.sc_dev.dv_xname);
     214           0 : }
     215             : 
     216             : int
     217           0 : sdhc_acpi_do_explore(struct aml_node *node, void *arg)
     218             : {
     219           0 :         struct sdhc_acpi_softc *sc = arg;
     220           0 :         int64_t sta, rmv;
     221             : 
     222             :         /* We're only interested in our children. */
     223           0 :         if (node == sc->sc_node)
     224           0 :                 return 0;
     225             : 
     226             :         /* Only consider devices that are actually present. */
     227           0 :         if (node->value == NULL ||
     228           0 :             node->value->type != AML_OBJTYPE_DEVICE)
     229           0 :                 return 1;
     230           0 :         if (aml_evalinteger(sc->sc_acpi, node, "_STA", 0, NULL, &sta))
     231           0 :                 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000;
     232           0 :         if ((sta & STA_PRESENT) == 0)
     233           0 :                 return 1;
     234             : 
     235           0 :         acpi_attach_deps(sc->sc_acpi, node);
     236             : 
     237             :         /* Override card detect if we have non-removable devices. */
     238           0 :         if (aml_evalinteger(sc->sc_acpi, node, "_RMV", 0, NULL, &rmv))
     239           0 :                 rmv = 1;
     240           0 :         if (rmv == 0 && sc->sc.sc_card_detect == NULL)
     241           0 :                 sc->sc.sc_card_detect = sdhc_acpi_card_detect_nonremovable;
     242             : 
     243           0 :         sdhc_acpi_power_on(sc, node);
     244             : 
     245           0 :         return 1;
     246           0 : }
     247             : 
     248             : void
     249           0 : sdhc_acpi_explore(struct sdhc_acpi_softc *sc)
     250             : {
     251           0 :         aml_walknodes(sc->sc_node, AML_WALK_PRE, sdhc_acpi_do_explore, sc);
     252           0 : }

Generated by: LCOV version 1.13