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

Cache object: f7e829c09237ecbf2d1e333a6bc6cc64


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