The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sdhci/sdhci_xenon.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2018 Rubicon Communications, LLC (Netgate)
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 /*
   29  * Marvell Xenon SDHCI controller driver.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/module.h>
   42 #include <sys/mutex.h>
   43 #include <sys/resource.h>
   44 #include <sys/rman.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/taskqueue.h>
   47 
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 
   51 #include <dev/extres/regulator/regulator.h>
   52 
   53 #include <dev/mmc/bridge.h>
   54 #include <dev/mmc/mmcbrvar.h>
   55 #include <dev/mmc/mmcreg.h>
   56 
   57 #include <dev/sdhci/sdhci.h>
   58 #include <dev/sdhci/sdhci_xenon.h>
   59 
   60 #include "mmcbr_if.h"
   61 #include "sdhci_if.h"
   62 
   63 #include "opt_mmccam.h"
   64 #include "opt_soc.h"
   65 
   66 #define MAX_SLOTS               6
   67 
   68 static uint8_t
   69 sdhci_xenon_read_1(device_t dev, struct sdhci_slot *slot __unused,
   70     bus_size_t off)
   71 {
   72         struct sdhci_xenon_softc *sc = device_get_softc(dev);
   73 
   74         return (bus_read_1(sc->mem_res, off));
   75 }
   76 
   77 static void
   78 sdhci_xenon_write_1(device_t dev, struct sdhci_slot *slot __unused,
   79     bus_size_t off, uint8_t val)
   80 {
   81         struct sdhci_xenon_softc *sc = device_get_softc(dev);
   82 
   83         bus_write_1(sc->mem_res, off, val);
   84 }
   85 
   86 static uint16_t
   87 sdhci_xenon_read_2(device_t dev, struct sdhci_slot *slot __unused,
   88     bus_size_t off)
   89 {
   90         struct sdhci_xenon_softc *sc = device_get_softc(dev);
   91 
   92         return (bus_read_2(sc->mem_res, off));
   93 }
   94 
   95 static void
   96 sdhci_xenon_write_2(device_t dev, struct sdhci_slot *slot __unused,
   97     bus_size_t off, uint16_t val)
   98 {
   99         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  100 
  101         bus_write_2(sc->mem_res, off, val);
  102 }
  103 
  104 static uint32_t
  105 sdhci_xenon_read_4(device_t dev, struct sdhci_slot *slot __unused,
  106     bus_size_t off)
  107 {
  108         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  109 
  110         return bus_read_4(sc->mem_res, off);
  111 }
  112 
  113 static void
  114 sdhci_xenon_write_4(device_t dev, struct sdhci_slot *slot __unused,
  115     bus_size_t off, uint32_t val)
  116 {
  117         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  118 
  119         bus_write_4(sc->mem_res, off, val);
  120 }
  121 
  122 static void
  123 sdhci_xenon_read_multi_4(device_t dev, struct sdhci_slot *slot __unused,
  124     bus_size_t off, uint32_t *data, bus_size_t count)
  125 {
  126         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  127 
  128         bus_read_multi_4(sc->mem_res, off, data, count);
  129 }
  130 
  131 static void
  132 sdhci_xenon_write_multi_4(device_t dev, struct sdhci_slot *slot __unused,
  133     bus_size_t off, uint32_t *data, bus_size_t count)
  134 {
  135         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  136 
  137         bus_write_multi_4(sc->mem_res, off, data, count);
  138 }
  139 
  140 static void
  141 sdhci_xenon_intr(void *arg)
  142 {
  143         struct sdhci_xenon_softc *sc = (struct sdhci_xenon_softc *)arg;
  144 
  145         sdhci_generic_intr(sc->slot);
  146 }
  147 
  148 static int
  149 sdhci_xenon_get_ro(device_t bus, device_t dev)
  150 {
  151         struct sdhci_xenon_softc *sc = device_get_softc(bus);
  152 
  153         return (sdhci_generic_get_ro(bus, dev) ^ sc->wp_inverted);
  154 }
  155 
  156 static void
  157 sdhci_xenon_set_uhs_timing(device_t brdev, struct sdhci_slot *slot)
  158 {
  159         const struct mmc_ios *ios;
  160         uint16_t hostctrl2;
  161 
  162         if (slot->version < SDHCI_SPEC_300)
  163                 return;
  164 
  165         mtx_assert(&slot->mtx, MA_OWNED);
  166         ios = &slot->host.ios;
  167 
  168         /* Update timing parameteres in SDHCI_HOST_CONTROL2 register. */
  169         hostctrl2 = sdhci_xenon_read_2(brdev, slot, SDHCI_HOST_CONTROL2);
  170         hostctrl2 &= ~SDHCI_CTRL2_UHS_MASK;
  171         if (ios->clock > SD_SDR50_MAX) {
  172                 if (ios->timing == bus_timing_mmc_hs400 ||
  173                     ios->timing == bus_timing_mmc_hs400es)
  174                         hostctrl2 |= XENON_CTRL2_MMC_HS400;
  175                 else if (ios->timing == bus_timing_mmc_hs200)
  176                         hostctrl2 |= XENON_CTRL2_MMC_HS200;
  177                 else
  178                         hostctrl2 |= SDHCI_CTRL2_UHS_SDR104;
  179         }
  180         else if (ios->clock > SD_SDR25_MAX)
  181                 hostctrl2 |= SDHCI_CTRL2_UHS_SDR50;
  182         else if (ios->clock > SD_SDR12_MAX) {
  183                 if (ios->timing == bus_timing_uhs_ddr50 ||
  184                     ios->timing == bus_timing_mmc_ddr52)
  185                         hostctrl2 |= SDHCI_CTRL2_UHS_DDR50;
  186                 else
  187                         hostctrl2 |= SDHCI_CTRL2_UHS_SDR25;
  188         } else if (ios->clock > SD_MMC_CARD_ID_FREQUENCY)
  189                 hostctrl2 |= SDHCI_CTRL2_UHS_SDR12;
  190         sdhci_xenon_write_2(brdev, slot, SDHCI_HOST_CONTROL2, hostctrl2);
  191 }
  192 
  193 static int
  194 sdhci_xenon_phy_init(device_t brdev, struct mmc_ios *ios)
  195 {
  196         int i;
  197         struct sdhci_xenon_softc *sc;
  198         uint32_t reg;
  199 
  200         sc = device_get_softc(brdev);
  201         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST);
  202         reg |= XENON_SAMPL_INV_QSP_PHASE_SELECT;
  203         switch (ios->timing) {
  204         case bus_timing_normal:
  205         case bus_timing_hs:
  206         case bus_timing_uhs_sdr12:
  207         case bus_timing_uhs_sdr25:
  208         case bus_timing_uhs_sdr50:
  209                 reg |= XENON_TIMING_ADJUST_SLOW_MODE;
  210                 break;
  211         default:
  212                 reg &= ~XENON_TIMING_ADJUST_SLOW_MODE;
  213         }
  214         if (sc->slow_mode)
  215                 reg |= XENON_TIMING_ADJUST_SLOW_MODE;
  216         bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg);
  217 
  218         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST);
  219         reg |= XENON_PHY_INITIALIZATION;
  220         bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg);
  221 
  222         /* Wait for the eMMC PHY init. */
  223         for (i = 100; i > 0; i--) {
  224                 DELAY(100);
  225 
  226                 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST);
  227                 if ((reg & XENON_PHY_INITIALIZATION) == 0)
  228                         break;
  229         }
  230 
  231         if (i == 0) {
  232                 device_printf(brdev, "eMMC PHY failed to initialize\n");
  233                 return (ETIMEDOUT);
  234         }
  235 
  236         return (0);
  237 }
  238 
  239 static int
  240 sdhci_xenon_phy_set(device_t brdev, struct mmc_ios *ios)
  241 {
  242         struct sdhci_xenon_softc *sc;
  243         uint32_t reg;
  244 
  245         sc = device_get_softc(brdev);
  246         /* Setup pad, set bit[28] and bits[26:24] */
  247         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL);
  248         reg |= (XENON_FC_DQ_RECEN | XENON_FC_CMD_RECEN |
  249                 XENON_FC_QSP_RECEN | XENON_OEN_QSN);
  250         /* All FC_XX_RECEIVCE should be set as CMOS Type */
  251         reg |= XENON_FC_ALL_CMOS_RECEIVER;
  252         bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL, reg);
  253 
  254         /* Set CMD and DQ Pull Up */
  255         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1);
  256         reg |= (XENON_EMMC_FC_CMD_PU | XENON_EMMC_FC_DQ_PU);
  257         reg &= ~(XENON_EMMC_FC_CMD_PD | XENON_EMMC_FC_DQ_PD);
  258         bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1, reg);
  259 
  260         if (ios->timing == bus_timing_normal)
  261                 return (sdhci_xenon_phy_init(brdev, ios));
  262 
  263         /* Clear SDIO mode, no SDIO support for now. */
  264         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST);
  265         reg &= ~XENON_TIMING_ADJUST_SDIO_MODE;
  266         bus_write_4(sc->mem_res, XENON_EMMC_PHY_TIMING_ADJUST, reg);
  267 
  268         /*
  269          * Set preferred ZNR and ZPR value.
  270          * The ZNR and ZPR value vary between different boards.
  271          * Define them both in the DTS for the board!
  272          */
  273         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL2);
  274         reg &= ~((XENON_ZNR_MASK << XENON_ZNR_SHIFT) | XENON_ZPR_MASK);
  275         reg |= ((sc->znr << XENON_ZNR_SHIFT) | sc->zpr);
  276         bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL2, reg);
  277 
  278         /* Disable the SD clock to set EMMC_PHY_FUNC_CONTROL. */
  279         reg = bus_read_4(sc->mem_res, SDHCI_CLOCK_CONTROL);
  280         reg &= ~SDHCI_CLOCK_CARD_EN;
  281         bus_write_4(sc->mem_res, SDHCI_CLOCK_CONTROL, reg);
  282 
  283         reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_FUNC_CONTROL);
  284         switch (ios->timing) {
  285         case bus_timing_mmc_hs400:
  286                 reg |= (XENON_DQ_DDR_MODE_MASK << XENON_DQ_DDR_MODE_SHIFT) |
  287                     XENON_CMD_DDR_MODE;
  288                 reg &= ~XENON_DQ_ASYNC_MODE;
  289                 break;
  290         case bus_timing_uhs_ddr50:
  291         case bus_timing_mmc_ddr52:
  292                 reg |= (XENON_DQ_DDR_MODE_MASK << XENON_DQ_DDR_MODE_SHIFT) |
  293                     XENON_CMD_DDR_MODE | XENON_DQ_ASYNC_MODE;
  294                 break;
  295         default:
  296                 reg &= ~((XENON_DQ_DDR_MODE_MASK << XENON_DQ_DDR_MODE_SHIFT) |
  297                     XENON_CMD_DDR_MODE);
  298                 reg |= XENON_DQ_ASYNC_MODE;
  299         }
  300         bus_write_4(sc->mem_res, XENON_EMMC_PHY_FUNC_CONTROL, reg);
  301 
  302         /* Enable SD clock. */
  303         reg = bus_read_4(sc->mem_res, SDHCI_CLOCK_CONTROL);
  304         reg |= SDHCI_CLOCK_CARD_EN;
  305         bus_write_4(sc->mem_res, SDHCI_CLOCK_CONTROL, reg);
  306 
  307         if (ios->timing == bus_timing_mmc_hs400)
  308                 bus_write_4(sc->mem_res, XENON_EMMC_PHY_LOGIC_TIMING_ADJUST,
  309                     XENON_LOGIC_TIMING_VALUE);
  310         else {
  311                 /* Disable both SDHC Data Strobe and Enhanced Strobe. */
  312                 reg = bus_read_4(sc->mem_res, XENON_SLOT_EMMC_CTRL);
  313                 reg &= ~(XENON_ENABLE_DATA_STROBE | XENON_ENABLE_RESP_STROBE);
  314                 bus_write_4(sc->mem_res, XENON_SLOT_EMMC_CTRL, reg);
  315 
  316                 /* Clear Strobe line Pull down or Pull up. */
  317                 reg = bus_read_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1);
  318                 reg &= ~(XENON_EMMC_FC_QSP_PD | XENON_EMMC_FC_QSP_PU);
  319                 bus_write_4(sc->mem_res, XENON_EMMC_PHY_PAD_CONTROL1, reg);
  320         }
  321 
  322         return (sdhci_xenon_phy_init(brdev, ios));
  323 }
  324 
  325 static int
  326 sdhci_xenon_update_ios(device_t brdev, device_t reqdev)
  327 {
  328         int err;
  329         struct sdhci_xenon_softc *sc;
  330         struct mmc_ios *ios;
  331         struct sdhci_slot *slot;
  332         uint32_t reg;
  333 
  334         err = sdhci_generic_update_ios(brdev, reqdev);
  335         if (err != 0)
  336                 return (err);
  337 
  338         sc = device_get_softc(brdev);
  339         slot = device_get_ivars(reqdev);
  340         ios = &slot->host.ios;
  341 
  342         switch (ios->power_mode) {
  343         case power_on:
  344                 break;
  345         case power_off:
  346                 if (bootverbose)
  347                         device_printf(sc->dev, "Powering down sd/mmc\n");
  348 
  349                 if (sc->vmmc_supply)
  350                         regulator_disable(sc->vmmc_supply);
  351                 if (sc->vqmmc_supply)
  352                         regulator_disable(sc->vqmmc_supply);
  353                 break;
  354         case power_up:
  355                 if (bootverbose)
  356                         device_printf(sc->dev, "Powering up sd/mmc\n");
  357 
  358                 if (sc->vmmc_supply)
  359                         regulator_enable(sc->vmmc_supply);
  360                 if (sc->vqmmc_supply)
  361                         regulator_enable(sc->vqmmc_supply);
  362                 break;
  363         };
  364 
  365         /* Update the PHY settings. */
  366         if (ios->clock != 0)
  367                 sdhci_xenon_phy_set(brdev, ios);
  368 
  369         if (ios->clock > SD_MMC_CARD_ID_FREQUENCY) {
  370                 /* Enable SDCLK_IDLEOFF. */
  371                 reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL);
  372                 reg |= 1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id);
  373                 bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg);
  374         }
  375 
  376         return (0);
  377 }
  378 
  379 static int
  380 sdhci_xenon_switch_vccq(device_t brdev, device_t reqdev)
  381 {
  382         struct sdhci_xenon_softc *sc;
  383         struct sdhci_slot *slot;
  384         uint16_t hostctrl2;
  385         int uvolt, err;
  386 
  387         slot = device_get_ivars(reqdev);
  388 
  389         if (slot->version < SDHCI_SPEC_300)
  390                 return (0);
  391 
  392         sc = device_get_softc(brdev);
  393 
  394         if (sc->vqmmc_supply == NULL && !sc->skip_regulators)
  395                 return (EOPNOTSUPP);
  396 
  397         err = 0;
  398 
  399         hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
  400         switch (slot->host.ios.vccq) {
  401         case vccq_330:
  402                 if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
  403                         return (0);
  404                 hostctrl2 &= ~SDHCI_CTRL2_S18_ENABLE;
  405                 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
  406 
  407                 if (!sc->skip_regulators) {
  408                         uvolt = 3300000;
  409                         err = regulator_set_voltage(sc->vqmmc_supply,
  410                             uvolt, uvolt);
  411                         if (err != 0) {
  412                                 device_printf(sc->dev,
  413                                     "Cannot set vqmmc to %d<->%d\n",
  414                                     uvolt,
  415                                     uvolt);
  416                                 return (err);
  417                         }
  418                 }
  419 
  420                 /*
  421                  * According to the 'SD Host Controller Simplified
  422                  * Specification 4.20 the host driver should take more
  423                  * than 5ms for stable time of host voltage regulator
  424                  * from changing 1.8V Signaling Enable.
  425                  */
  426                 DELAY(5000);
  427                 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
  428                 if (!(hostctrl2 & SDHCI_CTRL2_S18_ENABLE))
  429                         return (0);
  430                 return (EAGAIN);
  431         case vccq_180:
  432                 if (!(slot->host.caps & MMC_CAP_SIGNALING_180)) {
  433                         return (EINVAL);
  434                 }
  435                 if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
  436                         return (0);
  437                 hostctrl2 |= SDHCI_CTRL2_S18_ENABLE;
  438                 bus_write_2(sc->mem_res, SDHCI_HOST_CONTROL2, hostctrl2);
  439 
  440                 if (!sc->skip_regulators) {
  441                         uvolt = 1800000;
  442                         err = regulator_set_voltage(sc->vqmmc_supply,
  443                                 uvolt, uvolt);
  444                         if (err != 0) {
  445                                 device_printf(sc->dev,
  446                                         "Cannot set vqmmc to %d<->%d\n",
  447                                         uvolt,
  448                                         uvolt);
  449                                 return (err);
  450                         }
  451                 }
  452 
  453                 /*
  454                  * According to the 'SD Host Controller Simplified
  455                  * Specification 4.20 the host driver should take more
  456                  * than 5ms for stable time of host voltage regulator
  457                  * from changing 1.8V Signaling Enable.
  458                  */
  459                 DELAY(5000);
  460                 hostctrl2 = bus_read_2(sc->mem_res, SDHCI_HOST_CONTROL2);
  461                 if (hostctrl2 & SDHCI_CTRL2_S18_ENABLE)
  462                         return (0);
  463                 return (EAGAIN);
  464         default:
  465                 device_printf(brdev,
  466                     "Attempt to set unsupported signaling voltage\n");
  467                 return (EINVAL);
  468         }
  469 }
  470 
  471 static void
  472 sdhci_xenon_parse_prop(device_t dev)
  473 {
  474         struct sdhci_xenon_softc *sc;
  475         uint32_t val;
  476 
  477         sc = device_get_softc(dev);
  478         val = 0;
  479 
  480         if (device_get_property(dev, "quirks",
  481             &val, sizeof(val), DEVICE_PROP_UINT32) > 0)
  482                 sc->slot->quirks = val;
  483         sc->znr = XENON_ZNR_DEF_VALUE;
  484         if (device_get_property(dev, "marvell,xenon-phy-znr",
  485             &val, sizeof(val), DEVICE_PROP_UINT32) > 0)
  486                 sc->znr = val & XENON_ZNR_MASK;
  487         sc->zpr = XENON_ZPR_DEF_VALUE;
  488         if (device_get_property(dev, "marvell,xenon-phy-zpr",
  489             &val, sizeof(val), DEVICE_PROP_UINT32) > 0)
  490                 sc->zpr = val & XENON_ZPR_MASK;
  491         if (device_has_property(dev, "marvell,xenon-phy-slow-mode"))
  492                 sc->slow_mode = true;
  493 }
  494 
  495 int
  496 sdhci_xenon_attach(device_t dev)
  497 {
  498         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  499         int err, rid;
  500         uint32_t reg;
  501 
  502         sc->dev = dev;
  503         sc->slot_id = 0;
  504 
  505         /* Allocate IRQ. */
  506         rid = 0;
  507         sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  508             RF_ACTIVE);
  509         if (sc->irq_res == NULL) {
  510                 device_printf(dev, "Can't allocate IRQ\n");
  511                 return (ENOMEM);
  512         }
  513 
  514         /* Allocate memory. */
  515         rid = 0;
  516         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  517             &rid, RF_ACTIVE);
  518         if (sc->mem_res == NULL) {
  519                 bus_release_resource(dev, SYS_RES_IRQ,
  520                     rman_get_rid(sc->irq_res), sc->irq_res);
  521                 device_printf(dev, "Can't allocate memory for slot\n");
  522                 return (ENOMEM);
  523         }
  524 
  525         sdhci_xenon_parse_prop(dev);
  526 
  527         sc->slot->max_clk = XENON_MMC_MAX_CLK;
  528         if (sc->slot->host.f_max > 0)
  529                 sc->slot->max_clk = sc->slot->host.f_max;
  530 
  531         if (sdhci_init_slot(dev, sc->slot, 0))
  532                 goto fail;
  533 
  534         /* 1.2V signaling is not supported. */
  535         sc->slot->host.caps &= ~MMC_CAP_SIGNALING_120;
  536 
  537         /* Disable UHS in case of the PHY slow mode. */
  538         if (sc->slow_mode)
  539                 sc->slot->host.caps &= ~MMC_CAP_SIGNALING_180;
  540 
  541         /* Activate the interrupt */
  542         err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
  543             NULL, sdhci_xenon_intr, sc, &sc->intrhand);
  544         if (err) {
  545                 device_printf(dev, "Cannot setup IRQ\n");
  546                 goto fail;
  547         }
  548 
  549         /* Disable Auto Clock Gating. */
  550         reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL);
  551         reg |= XENON_AUTO_CLKGATE_DISABLE;
  552         bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg);
  553 
  554         /* Enable this SD controller. */
  555         reg |= (1 << sc->slot_id);
  556         bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg);
  557 
  558         /* Enable Parallel Transfer. */
  559         reg = bus_read_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL);
  560         reg |= (1 << sc->slot_id);
  561         bus_write_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL, reg);
  562 
  563         /* Enable Auto Clock Gating. */
  564         reg &= ~XENON_AUTO_CLKGATE_DISABLE;
  565         bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg);
  566 
  567         /* Disable SDCLK_IDLEOFF before the card initialization. */
  568         reg = bus_read_4(sc->mem_res, XENON_SYS_OP_CTRL);
  569         reg &= ~(1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sc->slot_id));
  570         bus_write_4(sc->mem_res, XENON_SYS_OP_CTRL, reg);
  571 
  572         /* Mask command conflict errors. */
  573         reg = bus_read_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL);
  574         reg |= XENON_MASK_CMD_CONFLICT_ERR;
  575         bus_write_4(sc->mem_res, XENON_SYS_EXT_OP_CTRL, reg);
  576 
  577         /* Process cards detection. */
  578         sdhci_start_slot(sc->slot);
  579 
  580         return (0);
  581 
  582 fail:
  583         bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res),
  584             sc->irq_res);
  585         bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res),
  586             sc->mem_res);
  587         free(sc->slot, M_DEVBUF);
  588         sc->slot = NULL;
  589 
  590         return (ENXIO);
  591 }
  592 
  593 int
  594 sdhci_xenon_detach(device_t dev)
  595 {
  596         struct sdhci_xenon_softc *sc = device_get_softc(dev);
  597 
  598         bus_generic_detach(dev);
  599         bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
  600         bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res),
  601             sc->irq_res);
  602         sdhci_cleanup_slot(sc->slot);
  603         bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem_res),
  604             sc->mem_res);
  605         free(sc->slot, M_DEVBUF);
  606         sc->slot = NULL;
  607 
  608         return (0);
  609 }
  610 
  611 static device_method_t sdhci_xenon_methods[] = {
  612         /* Bus interface */
  613         DEVMETHOD(bus_read_ivar,        sdhci_generic_read_ivar),
  614         DEVMETHOD(bus_write_ivar,       sdhci_generic_write_ivar),
  615 
  616         /* mmcbr_if */
  617         DEVMETHOD(mmcbr_update_ios,     sdhci_xenon_update_ios),
  618         DEVMETHOD(mmcbr_request,        sdhci_generic_request),
  619         DEVMETHOD(mmcbr_get_ro,         sdhci_xenon_get_ro),
  620         DEVMETHOD(mmcbr_acquire_host,   sdhci_generic_acquire_host),
  621         DEVMETHOD(mmcbr_release_host,   sdhci_generic_release_host),
  622         DEVMETHOD(mmcbr_switch_vccq,    sdhci_xenon_switch_vccq),
  623         DEVMETHOD(mmcbr_tune,           sdhci_generic_tune),
  624         DEVMETHOD(mmcbr_retune,         sdhci_generic_retune),
  625 
  626         /* SDHCI registers accessors */
  627         DEVMETHOD(sdhci_read_1,         sdhci_xenon_read_1),
  628         DEVMETHOD(sdhci_read_2,         sdhci_xenon_read_2),
  629         DEVMETHOD(sdhci_read_4,         sdhci_xenon_read_4),
  630         DEVMETHOD(sdhci_read_multi_4,   sdhci_xenon_read_multi_4),
  631         DEVMETHOD(sdhci_write_1,        sdhci_xenon_write_1),
  632         DEVMETHOD(sdhci_write_2,        sdhci_xenon_write_2),
  633         DEVMETHOD(sdhci_write_4,        sdhci_xenon_write_4),
  634         DEVMETHOD(sdhci_write_multi_4,  sdhci_xenon_write_multi_4),
  635         DEVMETHOD(sdhci_set_uhs_timing, sdhci_xenon_set_uhs_timing),
  636 
  637         DEVMETHOD_END
  638 };
  639 
  640 DEFINE_CLASS_0(sdhci_xenon, sdhci_xenon_driver, sdhci_xenon_methods,
  641     sizeof(struct sdhci_xenon_softc));
  642 
  643 SDHCI_DEPEND(sdhci_xenon);
  644 #ifndef MMCCAM
  645 MMC_DECLARE_BRIDGE(sdhci_xenon);
  646 #endif

Cache object: 29098009c29e02db53a6cedfd216054e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.