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/arm/ti/ti_sdhci.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  * Copyright (c) 2013 Ian Lepore <ian@freebsd.org>
    3  * Copyright (c) 2011 Ben Gray <ben.r.gray@gmail.com>.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/10.2/sys/arm/ti/ti_sdhci.c 276287 2014-12-27 04:54:36Z ian $");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/gpio.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 #include <sys/module.h>
   38 #include <sys/resource.h>
   39 #include <sys/rman.h>
   40 #include <sys/sysctl.h>
   41 #include <sys/taskqueue.h>
   42 
   43 #include <machine/bus.h>
   44 #include <machine/resource.h>
   45 #include <machine/intr.h>
   46 
   47 #include <dev/fdt/fdt_common.h>
   48 #include <dev/ofw/ofw_bus.h>
   49 #include <dev/ofw/ofw_bus_subr.h>
   50 
   51 #include <dev/mmc/bridge.h>
   52 #include <dev/mmc/mmcreg.h>
   53 #include <dev/mmc/mmcbrvar.h>
   54 
   55 #include <dev/sdhci/sdhci.h>
   56 #include "sdhci_if.h"
   57 
   58 #include <arm/ti/ti_cpuid.h>
   59 #include <arm/ti/ti_prcm.h>
   60 #include "gpio_if.h"
   61 
   62 struct ti_sdhci_softc {
   63         device_t                dev;
   64         device_t                gpio_dev;
   65         struct resource *       mem_res;
   66         struct resource *       irq_res;
   67         void *                  intr_cookie;
   68         struct sdhci_slot       slot;
   69         uint32_t                mmchs_device_id;
   70         uint32_t                mmchs_reg_off;
   71         uint32_t                sdhci_reg_off;
   72         uint32_t                baseclk_hz;
   73         uint32_t                wp_gpio_pin;
   74         uint32_t                cmd_and_mode;
   75         uint32_t                sdhci_clkdiv;
   76         boolean_t               disable_highspeed;
   77         boolean_t               force_card_present;
   78 };
   79 
   80 /*
   81  * Table of supported FDT compat strings.
   82  *
   83  * Note that "ti,mmchs" is our own invention, and should be phased out in favor
   84  * of the documented names.
   85  *
   86  * Note that vendor Beaglebone dtsi files use "ti,omap3-hsmmc" for the am335x.
   87  */
   88 static struct ofw_compat_data compat_data[] = {
   89         {"ti,omap3-hsmmc",      1},
   90         {"ti,omap4-hsmmc",      1},
   91         {"ti,mmchs",            1},
   92         {NULL,                  0},
   93 };
   94 
   95 /*
   96  * The MMCHS hardware has a few control and status registers at the beginning of
   97  * the device's memory map, followed by the standard sdhci register block.
   98  * Different SoCs have the register blocks at different offsets from the
   99  * beginning of the device.  Define some constants to map out the registers we
  100  * access, and the various per-SoC offsets.  The SDHCI_REG_OFFSET is how far
  101  * beyond the MMCHS block the SDHCI block is found; it's the same on all SoCs.
  102  */
  103 #define OMAP3_MMCHS_REG_OFFSET          0x000
  104 #define OMAP4_MMCHS_REG_OFFSET          0x100
  105 #define AM335X_MMCHS_REG_OFFSET         0x100
  106 #define SDHCI_REG_OFFSET                0x100
  107 
  108 #define MMCHS_SYSCONFIG                 0x010
  109 #define   MMCHS_SYSCONFIG_RESET           (1 << 1)
  110 #define MMCHS_SYSSTATUS                 0x014
  111 #define   MMCHS_SYSSTATUS_RESETDONE       (1 << 0)
  112 #define MMCHS_CON                       0x02C
  113 #define   MMCHS_CON_DW8                   (1 << 5)
  114 #define   MMCHS_CON_DVAL_8_4MS            (3 << 9)
  115 #define   MMCHS_CON_OD                    (1 << 0)
  116 #define MMCHS_SYSCTL                    0x12C
  117 #define   MMCHS_SYSCTL_CLKD_MASK           0x3FF
  118 #define   MMCHS_SYSCTL_CLKD_SHIFT          6
  119 #define MMCHS_SD_CAPA                   0x140
  120 #define   MMCHS_SD_CAPA_VS18              (1 << 26)
  121 #define   MMCHS_SD_CAPA_VS30              (1 << 25)
  122 #define   MMCHS_SD_CAPA_VS33              (1 << 24)
  123 
  124 static inline uint32_t
  125 ti_mmchs_read_4(struct ti_sdhci_softc *sc, bus_size_t off)
  126 {
  127 
  128         return (bus_read_4(sc->mem_res, off + sc->mmchs_reg_off));
  129 }
  130 
  131 static inline void
  132 ti_mmchs_write_4(struct ti_sdhci_softc *sc, bus_size_t off, uint32_t val)
  133 {
  134 
  135         bus_write_4(sc->mem_res, off + sc->mmchs_reg_off, val);
  136 }
  137 
  138 static inline uint32_t
  139 RD4(struct ti_sdhci_softc *sc, bus_size_t off)
  140 {
  141 
  142         return (bus_read_4(sc->mem_res, off + sc->sdhci_reg_off));
  143 }
  144 
  145 static inline void
  146 WR4(struct ti_sdhci_softc *sc, bus_size_t off, uint32_t val)
  147 {
  148 
  149         bus_write_4(sc->mem_res, off + sc->sdhci_reg_off, val);
  150 }
  151 
  152 static uint8_t
  153 ti_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
  154 {
  155         struct ti_sdhci_softc *sc = device_get_softc(dev);
  156 
  157         return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xff);
  158 }
  159 
  160 static uint16_t
  161 ti_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
  162 {
  163         struct ti_sdhci_softc *sc = device_get_softc(dev);
  164         uint32_t clkdiv, val32;
  165 
  166         /*
  167          * The MMCHS hardware has a non-standard interpretation of the sdclock
  168          * divisor bits.  It uses the same bit positions as SDHCI 3.0 (15..6)
  169          * but doesn't split them into low:high fields.  Instead they're a
  170          * single number in the range 0..1023 and the number is exactly the
  171          * clock divisor (with 0 and 1 both meaning divide by 1).  The SDHCI
  172          * driver code expects a v2.0 or v3.0 divisor.  The shifting and masking
  173          * here extracts the MMCHS representation from the hardware word, cleans
  174          * those bits out, applies the 2N adjustment, and plugs the result into
  175          * the bit positions for the 2.0 or 3.0 divisor in the returned register
  176          * value. The ti_sdhci_write_2() routine performs the opposite
  177          * transformation when the SDHCI driver writes to the register.
  178          */
  179         if (off == SDHCI_CLOCK_CONTROL) {
  180                 val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
  181                 clkdiv = ((val32 >> MMCHS_SYSCTL_CLKD_SHIFT) &
  182                     MMCHS_SYSCTL_CLKD_MASK) / 2;
  183                 val32 &= ~(MMCHS_SYSCTL_CLKD_MASK << MMCHS_SYSCTL_CLKD_SHIFT);
  184                 val32 |= (clkdiv & SDHCI_DIVIDER_MASK) << SDHCI_DIVIDER_SHIFT;
  185                 if (slot->version >= SDHCI_SPEC_300)
  186                         val32 |= ((clkdiv >> SDHCI_DIVIDER_MASK_LEN) &
  187                             SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_HI_SHIFT;
  188                 return (val32 & 0xffff);
  189         }
  190 
  191         /*
  192          * Standard 32-bit handling of command and transfer mode.
  193          */
  194         if (off == SDHCI_TRANSFER_MODE) {
  195                 return (sc->cmd_and_mode >> 16);
  196         } else if (off == SDHCI_COMMAND_FLAGS) {
  197                 return (sc->cmd_and_mode & 0x0000ffff);
  198         }
  199 
  200         return ((RD4(sc, off & ~3) >> (off & 3) * 8) & 0xffff);
  201 }
  202 
  203 static uint32_t
  204 ti_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
  205 {
  206         struct ti_sdhci_softc *sc = device_get_softc(dev);
  207         uint32_t val32;
  208 
  209         val32 = RD4(sc, off);
  210 
  211         /*
  212          * If we need to disallow highspeed mode due to the OMAP4 erratum, strip
  213          * that flag from the returned capabilities.
  214          */
  215         if (off == SDHCI_CAPABILITIES && sc->disable_highspeed)
  216                 val32 &= ~SDHCI_CAN_DO_HISPD;
  217 
  218         /*
  219          * Force the card-present state if necessary.
  220          */
  221         if (off == SDHCI_PRESENT_STATE && sc->force_card_present)
  222                 val32 |= SDHCI_CARD_PRESENT;
  223 
  224         return (val32);
  225 }
  226 
  227 static void
  228 ti_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
  229     uint32_t *data, bus_size_t count)
  230 {
  231         struct ti_sdhci_softc *sc = device_get_softc(dev);
  232 
  233         bus_read_multi_4(sc->mem_res, off + sc->sdhci_reg_off, data, count);
  234 }
  235 
  236 static void
  237 ti_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off, 
  238     uint8_t val)
  239 {
  240         struct ti_sdhci_softc *sc = device_get_softc(dev);
  241         uint32_t val32;
  242 
  243         val32 = RD4(sc, off & ~3);
  244         val32 &= ~(0xff << (off & 3) * 8);
  245         val32 |= (val << (off & 3) * 8);
  246 
  247         WR4(sc, off & ~3, val32);
  248 }
  249 
  250 static void
  251 ti_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, 
  252     uint16_t val)
  253 {
  254         struct ti_sdhci_softc *sc = device_get_softc(dev);
  255         uint32_t clkdiv, val32;
  256 
  257         /*
  258          * Translate between the hardware and SDHCI 2.0 or 3.0 representations
  259          * of the clock divisor.  See the comments in ti_sdhci_read_2() for
  260          * details.
  261          */
  262         if (off == SDHCI_CLOCK_CONTROL) {
  263                 clkdiv = (val >> SDHCI_DIVIDER_SHIFT) & SDHCI_DIVIDER_MASK;
  264                 if (slot->version >= SDHCI_SPEC_300)
  265                         clkdiv |= ((val >> SDHCI_DIVIDER_HI_SHIFT) &
  266                             SDHCI_DIVIDER_HI_MASK) << SDHCI_DIVIDER_MASK_LEN;
  267                 clkdiv *= 2;
  268                 if (clkdiv > MMCHS_SYSCTL_CLKD_MASK)
  269                         clkdiv = MMCHS_SYSCTL_CLKD_MASK;
  270                 val32 = RD4(sc, SDHCI_CLOCK_CONTROL);
  271                 val32 &= 0xffff0000;
  272                 val32 |= val & ~(MMCHS_SYSCTL_CLKD_MASK <<
  273                     MMCHS_SYSCTL_CLKD_SHIFT);
  274                 val32 |= clkdiv << MMCHS_SYSCTL_CLKD_SHIFT;
  275                 WR4(sc, SDHCI_CLOCK_CONTROL, val32);
  276                 return;
  277         }
  278 
  279         /*
  280          * Standard 32-bit handling of command and transfer mode.
  281          */
  282         if (off == SDHCI_TRANSFER_MODE) {
  283                 sc->cmd_and_mode = (sc->cmd_and_mode & 0xffff0000) |
  284                     ((uint32_t)val & 0x0000ffff);
  285                 return;
  286         } else if (off == SDHCI_COMMAND_FLAGS) {
  287                 sc->cmd_and_mode = (sc->cmd_and_mode & 0x0000ffff) |
  288                     ((uint32_t)val << 16);
  289                 WR4(sc, SDHCI_TRANSFER_MODE, sc->cmd_and_mode);
  290                 return;
  291         }
  292 
  293         val32 = RD4(sc, off & ~3);
  294         val32 &= ~(0xffff << (off & 3) * 8);
  295         val32 |= ((val & 0xffff) << (off & 3) * 8);
  296         WR4(sc, off & ~3, val32);       
  297 }
  298 
  299 static void
  300 ti_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, 
  301     uint32_t val)
  302 {
  303         struct ti_sdhci_softc *sc = device_get_softc(dev);
  304 
  305         WR4(sc, off, val);
  306 }
  307 
  308 static void
  309 ti_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
  310     uint32_t *data, bus_size_t count)
  311 {
  312         struct ti_sdhci_softc *sc = device_get_softc(dev);
  313 
  314         bus_write_multi_4(sc->mem_res, off + sc->sdhci_reg_off, data, count);
  315 }
  316 
  317 static void
  318 ti_sdhci_intr(void *arg)
  319 {
  320         struct ti_sdhci_softc *sc = arg;
  321 
  322         sdhci_generic_intr(&sc->slot);
  323 }
  324 
  325 static int
  326 ti_sdhci_update_ios(device_t brdev, device_t reqdev)
  327 {
  328         struct ti_sdhci_softc *sc = device_get_softc(brdev);
  329         struct sdhci_slot *slot;
  330         struct mmc_ios *ios;
  331         uint32_t val32, newval32;
  332 
  333         slot = device_get_ivars(reqdev);
  334         ios = &slot->host.ios;
  335 
  336         /*
  337          * There is an 8-bit-bus bit in the MMCHS control register which, when
  338          * set, overrides the 1 vs 4 bit setting in the standard SDHCI
  339          * registers.  Set that bit first according to whether an 8-bit bus is
  340          * requested, then let the standard driver handle everything else.
  341          */
  342         val32 = ti_mmchs_read_4(sc, MMCHS_CON);
  343         newval32  = val32;
  344 
  345         if (ios->bus_width == bus_width_8)
  346                 newval32 |= MMCHS_CON_DW8;
  347         else
  348                 newval32 &= ~MMCHS_CON_DW8;
  349 
  350         if (ios->bus_mode == opendrain)
  351                 newval32 |= MMCHS_CON_OD;
  352         else /* if (ios->bus_mode == pushpull) */
  353                 newval32 &= ~MMCHS_CON_OD;
  354 
  355         if (newval32 != val32)
  356                 ti_mmchs_write_4(sc, MMCHS_CON, newval32);
  357 
  358         return (sdhci_generic_update_ios(brdev, reqdev));
  359 }
  360 
  361 static int
  362 ti_sdhci_get_ro(device_t brdev, device_t reqdev)
  363 {
  364         struct ti_sdhci_softc *sc = device_get_softc(brdev);
  365         unsigned int readonly = 0;
  366 
  367         /* If a gpio pin is configured, read it. */
  368         if (sc->gpio_dev != NULL) {
  369                 GPIO_PIN_GET(sc->gpio_dev, sc->wp_gpio_pin, &readonly);
  370         }
  371 
  372         return (readonly);
  373 }
  374 
  375 static int
  376 ti_sdhci_detach(device_t dev)
  377 {
  378 
  379         return (EBUSY);
  380 }
  381 
  382 static void
  383 ti_sdhci_hw_init(device_t dev)
  384 {
  385         struct ti_sdhci_softc *sc = device_get_softc(dev);
  386         clk_ident_t clk;
  387         uint32_t regval;
  388         unsigned long timeout;
  389 
  390         /* Enable the controller and interface/functional clocks */
  391         clk = MMC0_CLK + sc->mmchs_device_id;
  392         if (ti_prcm_clk_enable(clk) != 0) {
  393                 device_printf(dev, "Error: failed to enable MMC clock\n");
  394                 return;
  395         }
  396 
  397         /* Get the frequency of the source clock */
  398         if (ti_prcm_clk_get_source_freq(clk, &sc->baseclk_hz) != 0) {
  399                 device_printf(dev, "Error: failed to get source clock freq\n");
  400                 return;
  401         }
  402 
  403         /* Issue a softreset to the controller */
  404         ti_mmchs_write_4(sc, MMCHS_SYSCONFIG, MMCHS_SYSCONFIG_RESET);
  405         timeout = 1000;
  406         while (!(ti_mmchs_read_4(sc, MMCHS_SYSSTATUS) &
  407             MMCHS_SYSSTATUS_RESETDONE)) {
  408                 if (--timeout == 0) {
  409                         device_printf(dev,
  410                             "Error: Controller reset operation timed out\n");
  411                         break;
  412                 }
  413                 DELAY(100);
  414         }
  415 
  416         /*
  417          * Reset the command and data state machines and also other aspects of
  418          * the controller such as bus clock and power.
  419          *
  420          * If we read the software reset register too fast after writing it we
  421          * can get back a zero that means the reset hasn't started yet rather
  422          * than that the reset is complete. Per TI recommendations, work around
  423          * it by reading until we see the reset bit asserted, then read until
  424          * it's clear. We also set the SDHCI_QUIRK_WAITFOR_RESET_ASSERTED quirk
  425          * so that the main sdhci driver uses this same logic in its resets.
  426          */
  427         ti_sdhci_write_1(dev, NULL, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL);
  428         timeout = 10000;
  429         while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
  430             SDHCI_RESET_ALL) != SDHCI_RESET_ALL) {
  431                 if (--timeout == 0) {
  432                         break;
  433                 }
  434                 DELAY(1);
  435         }
  436         timeout = 10000;
  437         while ((ti_sdhci_read_1(dev, NULL, SDHCI_SOFTWARE_RESET) &
  438             SDHCI_RESET_ALL)) {
  439                 if (--timeout == 0) {
  440                         device_printf(dev,
  441                             "Error: Software reset operation timed out\n");
  442                         break;
  443                 }
  444                 DELAY(100);
  445         }
  446 
  447         /*
  448          * The attach() routine has examined fdt data and set flags in
  449          * slot.host.caps to reflect what voltages we can handle.  Set those
  450          * values in the CAPA register.  The manual says that these values can
  451          * only be set once, "before initialization" whatever that means, and
  452          * that they survive a reset.  So maybe doing this will be a no-op if
  453          * u-boot has already initialized the hardware.
  454          */
  455         regval = ti_mmchs_read_4(sc, MMCHS_SD_CAPA);
  456         if (sc->slot.host.caps & MMC_OCR_LOW_VOLTAGE)
  457                 regval |= MMCHS_SD_CAPA_VS18;
  458         if (sc->slot.host.caps & (MMC_OCR_290_300 | MMC_OCR_300_310))
  459                 regval |= MMCHS_SD_CAPA_VS30;
  460         ti_mmchs_write_4(sc, MMCHS_SD_CAPA, regval);
  461 
  462         /* Set initial host configuration (1-bit, std speed, pwr off). */
  463         ti_sdhci_write_1(dev, NULL, SDHCI_HOST_CONTROL, 0);
  464         ti_sdhci_write_1(dev, NULL, SDHCI_POWER_CONTROL, 0);
  465 
  466         /* Set the initial controller configuration. */
  467         ti_mmchs_write_4(sc, MMCHS_CON, MMCHS_CON_DVAL_8_4MS);
  468 }
  469 
  470 static int
  471 ti_sdhci_attach(device_t dev)
  472 {
  473         struct ti_sdhci_softc *sc = device_get_softc(dev);
  474         int rid, err;
  475         pcell_t prop;
  476         phandle_t node;
  477 
  478         sc->dev = dev;
  479 
  480         /*
  481          * Get the MMCHS device id from FDT.  If it's not there use the newbus
  482          * unit number (which will work as long as the devices are in order and
  483          * none are skipped in the fdt).  Note that this is a property we made
  484          * up and added in freebsd, it doesn't exist in the published bindings.
  485          */
  486         node = ofw_bus_get_node(dev);
  487         if ((OF_getprop(node, "mmchs-device-id", &prop, sizeof(prop))) <= 0) {
  488                 sc->mmchs_device_id = device_get_unit(dev);
  489                 device_printf(dev, "missing mmchs-device-id attribute in FDT, "
  490                     "using unit number (%d)", sc->mmchs_device_id);
  491         } else
  492                 sc->mmchs_device_id = fdt32_to_cpu(prop);
  493 
  494         /*
  495          * The hardware can inherently do dual-voltage (1p8v, 3p0v) on the first
  496          * device, and only 1p8v on other devices unless an external transceiver
  497          * is used.  The only way we could know about a transceiver is fdt data.
  498          * Note that we have to do this before calling ti_sdhci_hw_init() so
  499          * that it can set the right values in the CAPA register, which can only
  500          * be done once and never reset.
  501          */
  502         sc->slot.host.caps |= MMC_OCR_LOW_VOLTAGE;
  503         if (sc->mmchs_device_id == 0 || OF_hasprop(node, "ti,dual-volt")) {
  504                 sc->slot.host.caps |= MMC_OCR_290_300 | MMC_OCR_300_310;
  505         }
  506 
  507         /*
  508          * See if we've got a GPIO-based write detect pin.  This is not the
  509          * standard documented property for this, we added it in freebsd.
  510          */
  511         if ((OF_getprop(node, "mmchs-wp-gpio-pin", &prop, sizeof(prop))) <= 0)
  512                 sc->wp_gpio_pin = 0xffffffff;
  513         else
  514                 sc->wp_gpio_pin = fdt32_to_cpu(prop);
  515 
  516         if (sc->wp_gpio_pin != 0xffffffff) {
  517                 sc->gpio_dev = devclass_get_device(devclass_find("gpio"), 0);
  518                 if (sc->gpio_dev == NULL) 
  519                         device_printf(dev, "Error: No GPIO device, "
  520                             "Write Protect pin will not function\n");
  521                 else
  522                         GPIO_PIN_SETFLAGS(sc->gpio_dev, sc->wp_gpio_pin,
  523                                           GPIO_PIN_INPUT);
  524         }
  525 
  526         /*
  527          * Set the offset from the device's memory start to the MMCHS registers.
  528          * Also for OMAP4 disable high speed mode due to erratum ID i626.
  529          */
  530         if (ti_chip() == CHIP_OMAP_3)
  531                 sc->mmchs_reg_off = OMAP3_MMCHS_REG_OFFSET;
  532         else if (ti_chip() == CHIP_OMAP_4) {
  533                 sc->mmchs_reg_off = OMAP4_MMCHS_REG_OFFSET;
  534                 sc->disable_highspeed = true;
  535         } else if (ti_chip() == CHIP_AM335X)
  536                 sc->mmchs_reg_off = AM335X_MMCHS_REG_OFFSET;
  537         else
  538                 panic("Unknown OMAP device\n");
  539 
  540         /*
  541          * The standard SDHCI registers are at a fixed offset (the same on all
  542          * SoCs) beyond the MMCHS registers.
  543          */
  544         sc->sdhci_reg_off = sc->mmchs_reg_off + SDHCI_REG_OFFSET;
  545 
  546         /* Resource setup. */
  547         rid = 0;
  548         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  549             RF_ACTIVE);
  550         if (!sc->mem_res) {
  551                 device_printf(dev, "cannot allocate memory window\n");
  552                 err = ENXIO;
  553                 goto fail;
  554         }
  555 
  556         rid = 0;
  557         sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  558             RF_ACTIVE);
  559         if (!sc->irq_res) {
  560                 device_printf(dev, "cannot allocate interrupt\n");
  561                 err = ENXIO;
  562                 goto fail;
  563         }
  564 
  565         if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
  566             NULL, ti_sdhci_intr, sc, &sc->intr_cookie)) {
  567                 device_printf(dev, "cannot setup interrupt handler\n");
  568                 err = ENXIO;
  569                 goto fail;
  570         }
  571 
  572         /* Initialise the MMCHS hardware. */
  573         ti_sdhci_hw_init(dev);
  574 
  575         /*
  576          * The capabilities register can only express base clock frequencies in
  577          * the range of 0-63MHz for a v2.0 controller.  Since our clock runs
  578          * faster than that, the hardware sets the frequency to zero in the
  579          * register.  When the register contains zero, the sdhci driver expects
  580          * slot.max_clk to already have the right value in it.
  581          */
  582         sc->slot.max_clk = sc->baseclk_hz;
  583 
  584         /*
  585          * The MMCHS timeout counter is based on the output sdclock.  Tell the
  586          * sdhci driver to recalculate the timeout clock whenever the output
  587          * sdclock frequency changes.
  588          */
  589         sc->slot.quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
  590 
  591         /*
  592          * The MMCHS hardware shifts the 136-bit response data (in violation of
  593          * the spec), so tell the sdhci driver not to do the same in software.
  594          */
  595         sc->slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
  596 
  597         /*
  598          * Reset bits are broken, have to wait to see the bits asserted
  599          * before waiting to see them de-asserted.
  600          */
  601         sc->slot.quirks |= SDHCI_QUIRK_WAITFOR_RESET_ASSERTED;
  602 
  603         /*
  604          * DMA is not really broken, I just haven't implemented it yet.
  605          */
  606         sc->slot.quirks |= SDHCI_QUIRK_BROKEN_DMA;
  607 
  608         /*
  609          *  Set up the hardware and go.  Note that this sets many of the
  610          *  slot.host.* fields, so we have to do this before overriding any of
  611          *  those values based on fdt data, below.
  612          */
  613         sdhci_init_slot(dev, &sc->slot, 0);
  614 
  615         /*
  616          * The SDHCI controller doesn't realize it, but we can support 8-bit
  617          * even though we're not a v3.0 controller.  If there's an fdt bus-width
  618          * property, honor it.
  619          */
  620         if (OF_getencprop(node, "bus-width", &prop, sizeof(prop)) > 0) {
  621                 sc->slot.host.caps &= ~(MMC_CAP_4_BIT_DATA | 
  622                     MMC_CAP_8_BIT_DATA);
  623                 switch (prop) {
  624                 case 8:
  625                         sc->slot.host.caps |= MMC_CAP_8_BIT_DATA;
  626                         /* FALLTHROUGH */
  627                 case 4:
  628                         sc->slot.host.caps |= MMC_CAP_4_BIT_DATA;
  629                         break;
  630                 case 1:
  631                         break;
  632                 default:
  633                         device_printf(dev, "Bad bus-width value %u\n", prop);
  634                         break;
  635                 }
  636         }
  637 
  638         /*
  639          * If the slot is flagged with the non-removable property, set our flag
  640          * to always force the SDHCI_CARD_PRESENT bit on.
  641          */
  642         node = ofw_bus_get_node(dev);
  643         if (OF_hasprop(node, "non-removable"))
  644                 sc->force_card_present = true;
  645 
  646         bus_generic_probe(dev);
  647         bus_generic_attach(dev);
  648 
  649         sdhci_start_slot(&sc->slot);
  650 
  651         return (0);
  652 
  653 fail:
  654         if (sc->intr_cookie)
  655                 bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
  656         if (sc->irq_res)
  657                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
  658         if (sc->mem_res)
  659                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
  660 
  661         return (err);
  662 }
  663 
  664 static int
  665 ti_sdhci_probe(device_t dev)
  666 {
  667 
  668         if (!ofw_bus_status_okay(dev))
  669                 return (ENXIO);
  670 
  671         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
  672                 device_set_desc(dev, "TI MMCHS (SDHCI 2.0)");
  673                 return (BUS_PROBE_DEFAULT);
  674         }
  675 
  676         return (ENXIO);
  677 }
  678 
  679 static device_method_t ti_sdhci_methods[] = {
  680         /* Device interface */
  681         DEVMETHOD(device_probe,         ti_sdhci_probe),
  682         DEVMETHOD(device_attach,        ti_sdhci_attach),
  683         DEVMETHOD(device_detach,        ti_sdhci_detach),
  684 
  685         /* Bus interface */
  686         DEVMETHOD(bus_read_ivar,        sdhci_generic_read_ivar),
  687         DEVMETHOD(bus_write_ivar,       sdhci_generic_write_ivar),
  688         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  689 
  690         /* MMC bridge interface */
  691         DEVMETHOD(mmcbr_update_ios,     ti_sdhci_update_ios),
  692         DEVMETHOD(mmcbr_request,        sdhci_generic_request),
  693         DEVMETHOD(mmcbr_get_ro,         ti_sdhci_get_ro),
  694         DEVMETHOD(mmcbr_acquire_host,   sdhci_generic_acquire_host),
  695         DEVMETHOD(mmcbr_release_host,   sdhci_generic_release_host),
  696 
  697         /* SDHCI registers accessors */
  698         DEVMETHOD(sdhci_read_1,         ti_sdhci_read_1),
  699         DEVMETHOD(sdhci_read_2,         ti_sdhci_read_2),
  700         DEVMETHOD(sdhci_read_4,         ti_sdhci_read_4),
  701         DEVMETHOD(sdhci_read_multi_4,   ti_sdhci_read_multi_4),
  702         DEVMETHOD(sdhci_write_1,        ti_sdhci_write_1),
  703         DEVMETHOD(sdhci_write_2,        ti_sdhci_write_2),
  704         DEVMETHOD(sdhci_write_4,        ti_sdhci_write_4),
  705         DEVMETHOD(sdhci_write_multi_4,  ti_sdhci_write_multi_4),
  706 
  707         DEVMETHOD_END
  708 };
  709 
  710 static devclass_t ti_sdhci_devclass;
  711 
  712 static driver_t ti_sdhci_driver = {
  713         "sdhci_ti",
  714         ti_sdhci_methods,
  715         sizeof(struct ti_sdhci_softc),
  716 };
  717 
  718 DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, 0, 0);
  719 MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1);

Cache object: 6b77b03856badc13aad6752e79399cfc


[ 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.