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/broadcom/bcm2835/bcm2835_sdhost.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 Klaus P. Ohrhallinger <k@7he.at>
    5  * All rights reserved.
    6  *
    7  * Based on bcm2835_sdhci.c:
    8  * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  */
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 /*
   37  * pin 48-53 - card slot
   38  * pin 34-39 - radio module
   39  *
   40  * alt-0 - rubbish SDHCI  (0x7e202000) aka sdhost
   41  * alt-3 - advanced SDHCI (0x7e300000) aka sdhci/mmc/sdio
   42  *
   43  * driving card slot with mmc:
   44  *
   45  * sdhost_pins {
   46  *         brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>;
   47  *         brcm,function = <0x7>;
   48  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
   49  *         phandle = <0x17>;
   50  * };
   51  * sdio_pins {
   52  *         brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
   53  *         brcm,function = <0x4>;
   54  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
   55  *         phandle = <0x18>;
   56  * };
   57  *
   58  * driving card slot with sdhost:
   59  *
   60  * sdhost_pins {
   61  *         brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>;
   62  *         brcm,function = <0x4>;
   63  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
   64  *         phandle = <0x17>;
   65  * };
   66  * sdio_pins {
   67  *         brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
   68  *         brcm,function = <0x7>;
   69  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
   70  *         phandle = <0x18>;
   71  * };
   72  *
   73  */
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/kobj.h>
   78 #include <sys/bus.h>
   79 #include <sys/kernel.h>
   80 #include <sys/lock.h>
   81 #include <sys/malloc.h>
   82 #include <sys/module.h>
   83 #include <sys/mutex.h>
   84 #include <sys/rman.h>
   85 #include <sys/sysctl.h>
   86 #include <sys/taskqueue.h>
   87 #include <sys/gpio.h>
   88 
   89 #include <machine/bus.h>
   90 
   91 #include <dev/ofw/ofw_bus.h>
   92 #include <dev/ofw/ofw_bus_subr.h>
   93 
   94 #include <dev/mmc/bridge.h>
   95 #include <dev/mmc/mmcreg.h>
   96 
   97 #include <dev/sdhci/sdhci.h>
   98 
   99 #include "mmcbr_if.h"
  100 #include "sdhci_if.h"
  101 
  102 #include "opt_mmccam.h"
  103 
  104 #include "bcm2835_dma.h"
  105 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
  106 #include "bcm2835_vcbus.h"
  107 
  108 /* #define SDHOST_DEBUG */
  109 
  110 /* Registers */
  111 #define HC_COMMAND              0x00    /* Command and flags */
  112 #define HC_ARGUMENT             0x04
  113 #define HC_TIMEOUTCOUNTER       0x08
  114 #define HC_CLOCKDIVISOR         0x0c
  115 #define HC_RESPONSE_0           0x10
  116 #define HC_RESPONSE_1           0x14
  117 #define HC_RESPONSE_2           0x18
  118 #define HC_RESPONSE_3           0x1c
  119 #define HC_HOSTSTATUS           0x20
  120 #define HC_POWER                0x30
  121 #define HC_DEBUG                0x34
  122 #define HC_HOSTCONFIG           0x38
  123 #define HC_BLOCKSIZE            0x3c
  124 #define HC_DATAPORT             0x40
  125 #define HC_BLOCKCOUNT           0x50
  126 
  127 /* Flags for HC_COMMAND register */
  128 #define HC_CMD_ENABLE                   0x8000
  129 #define HC_CMD_FAILED                   0x4000
  130 #define HC_CMD_BUSY                     0x0800
  131 #define HC_CMD_RESPONSE_NONE            0x0400
  132 #define HC_CMD_RESPONSE_LONG            0x0200
  133 #define HC_CMD_WRITE                    0x0080
  134 #define HC_CMD_READ                     0x0040
  135 #define HC_CMD_COMMAND_MASK             0x003f
  136 
  137 #define HC_CLOCKDIVISOR_MAXVAL          0x07ff
  138 
  139 /* Flags for HC_HOSTSTATUS register */
  140 #define HC_HSTST_HAVEDATA               0x0001
  141 #define HC_HSTST_ERROR_FIFO             0x0008
  142 #define HC_HSTST_ERROR_CRC7             0x0010
  143 #define HC_HSTST_ERROR_CRC16            0x0020
  144 #define HC_HSTST_TIMEOUT_CMD            0x0040
  145 #define HC_HSTST_TIMEOUT_DATA           0x0080
  146 #define HC_HSTST_INT_BLOCK              0x0200
  147 #define HC_HSTST_INT_BUSY               0x0400
  148 
  149 #define HC_HSTST_RESET                  0xffff
  150 
  151 #define HC_HSTST_MASK_ERROR_DATA        (HC_HSTST_ERROR_FIFO | \
  152     HC_HSTST_ERROR_CRC7 | HC_HSTST_ERROR_CRC16 | HC_HSTST_TIMEOUT_DATA)
  153 
  154 #define HC_HSTST_MASK_ERROR_ALL         (HC_HSTST_MASK_ERROR_DATA | \
  155     HC_HSTST_TIMEOUT_CMD)
  156 
  157 /* Flags for HC_HOSTCONFIG register */
  158 #define HC_HSTCF_INTBUS_WIDE            0x0002
  159 #define HC_HSTCF_EXTBUS_4BIT            0x0004
  160 #define HC_HSTCF_SLOW_CARD              0x0008
  161 #define HC_HSTCF_INT_DATA               0x0010
  162 #define HC_HSTCF_INT_BLOCK              0x0100
  163 #define HC_HSTCF_INT_BUSY               0x0400
  164 
  165 /* Flags for HC_DEBUG register */
  166 #define HC_DBG_FIFO_THRESH_WRITE_SHIFT  9
  167 #define HC_DBG_FIFO_THRESH_READ_SHIFT   14
  168 #define HC_DBG_FIFO_THRESH_MASK         0x001f
  169 
  170 /* Settings */
  171 #define HC_FIFO_SIZE            16
  172 #define HC_FIFO_THRESH_READ     4
  173 #define HC_FIFO_THRESH_WRITE    4
  174 
  175 #define HC_TIMEOUT_DEFAULT      0x00f00000
  176 
  177 #define BCM2835_DEFAULT_SDHCI_FREQ      50
  178 
  179 static int bcm2835_sdhost_debug = 0;
  180 
  181 #ifdef SDHOST_DEBUG
  182 
  183 TUNABLE_INT("hw.bcm2835.sdhost.debug", &bcm2835_sdhost_debug);
  184 SYSCTL_INT(_hw_sdhci, OID_AUTO, bcm2835_sdhost_debug, CTLFLAG_RWTUN,
  185     &bcm2835_sdhost_debug, 0, "bcm2835-sdhost Debug level");
  186 
  187 #define dprintf(fmt, args...) \
  188         do { \
  189                 if (bcm2835_sdhost_debug > 0) \
  190                         printf(fmt,##args); \
  191         } while (0)
  192 #else
  193 
  194 #define dprintf(fmt, args...)
  195 
  196 #endif /* ! SDHOST_DEBUG */
  197 
  198 static struct ofw_compat_data compat_data[] = {
  199         {"brcm,bcm2835-sdhost",         1},
  200         {NULL,                          0}
  201 };
  202 
  203 struct bcm_sdhost_softc {
  204         device_t                sc_dev;
  205         struct resource *       sc_mem_res;
  206         struct resource *       sc_irq_res;
  207         bus_space_tag_t         sc_bst;
  208         bus_space_handle_t      sc_bsh;
  209         void *                  sc_intrhand;
  210         struct mmc_request *    sc_req;
  211         struct sdhci_slot       sc_slot;
  212 
  213         struct mtx              mtx;
  214 
  215         char                    cmdbusy;
  216         char                    mmc_app_cmd;
  217 
  218         u_int32_t               sdhci_int_status;
  219         u_int32_t               sdhci_signal_enable;
  220         u_int32_t               sdhci_present_state;
  221         u_int32_t               sdhci_blocksize;
  222         u_int32_t               sdhci_blockcount;
  223 
  224         u_int32_t               sdcard_rca;
  225 };
  226 
  227 static int bcm_sdhost_probe(device_t);
  228 static int bcm_sdhost_attach(device_t);
  229 static int bcm_sdhost_detach(device_t);
  230 static void bcm_sdhost_intr(void *);
  231 
  232 static int bcm_sdhost_get_ro(device_t, device_t);
  233 
  234 static inline uint32_t
  235 RD4(struct bcm_sdhost_softc *sc, bus_size_t off)
  236 {
  237         uint32_t val;
  238 
  239         val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
  240 
  241         return (val);
  242 }
  243 
  244 static inline void
  245 WR4(struct bcm_sdhost_softc *sc, bus_size_t off, uint32_t val)
  246 {
  247 
  248         bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
  249 }
  250 
  251 #ifdef notyet
  252 static inline uint16_t
  253 RD2(struct bcm_sdhost_softc *sc, bus_size_t off)
  254 {
  255         uint32_t val;
  256 
  257         val = RD4(sc, off & ~3);
  258 
  259         return ((val >> (off & 3)*8) & 0xffff);
  260 }
  261 #endif
  262 
  263 static inline uint8_t
  264 RD1(struct bcm_sdhost_softc *sc, bus_size_t off)
  265 {
  266         uint32_t val;
  267 
  268         val = RD4(sc, off & ~3);
  269 
  270         return ((val >> (off & 3)*8) & 0xff);
  271 }
  272 
  273 static inline void
  274 WR2(struct bcm_sdhost_softc *sc, bus_size_t off, uint16_t val)
  275 {
  276         uint32_t val32;
  277 
  278         val32 = RD4(sc, off & ~3);
  279         val32 &= ~(0xffff << (off & 3)*8);
  280         val32 |= (val << (off & 3)*8);
  281         WR4(sc, off & ~3, val32);
  282 }
  283 
  284 static inline void
  285 WR1(struct bcm_sdhost_softc *sc, bus_size_t off, uint8_t val)
  286 {
  287         uint32_t val32;
  288 
  289         val32 = RD4(sc, off & ~3);
  290         val32 &= ~(0xff << (off & 3)*8);
  291         val32 |= (val << (off & 3)*8);
  292         WR4(sc, off & ~3, val32);
  293 }
  294 
  295 static void
  296 bcm_sdhost_print_regs(struct bcm_sdhost_softc *sc, struct sdhci_slot *slot,
  297     int line, int error)
  298 {
  299 
  300         if (bcm2835_sdhost_debug > 0 || error > 0) {
  301                 printf("%s: sc=%p slot=%p\n",
  302                     __func__, sc, slot);
  303                 printf("HC_COMMAND:        0x%08x\n",
  304                     RD4(sc, HC_COMMAND));
  305                 printf("HC_ARGUMENT:       0x%08x\n",
  306                     RD4(sc, HC_ARGUMENT));
  307                 printf("HC_TIMEOUTCOUNTER: 0x%08x\n",
  308                     RD4(sc, HC_TIMEOUTCOUNTER));
  309                 printf("HC_CLOCKDIVISOR:   0x%08x\n",
  310                     RD4(sc, HC_CLOCKDIVISOR));
  311                 printf("HC_RESPONSE_0:     0x%08x\n",
  312                     RD4(sc, HC_RESPONSE_0));
  313                 printf("HC_RESPONSE_1:     0x%08x\n",
  314                     RD4(sc, HC_RESPONSE_1));
  315                 printf("HC_RESPONSE_2:     0x%08x\n",
  316                     RD4(sc, HC_RESPONSE_2));
  317                 printf("HC_RESPONSE_3:     0x%08x\n",
  318                     RD4(sc, HC_RESPONSE_3));
  319                 printf("HC_HOSTSTATUS:     0x%08x\n",
  320                     RD4(sc, HC_HOSTSTATUS));
  321                 printf("HC_POWER:          0x%08x\n",
  322                     RD4(sc, HC_POWER));
  323                 printf("HC_DEBUG:          0x%08x\n",
  324                     RD4(sc, HC_DEBUG));
  325                 printf("HC_HOSTCONFIG:     0x%08x\n",
  326                     RD4(sc, HC_HOSTCONFIG));
  327                 printf("HC_BLOCKSIZE:      0x%08x\n",
  328                     RD4(sc, HC_BLOCKSIZE));
  329                 printf("HC_BLOCKCOUNT:     0x%08x\n",
  330                     RD4(sc, HC_BLOCKCOUNT));
  331 
  332         } else {
  333                 /*
  334                 printf("%04d | HC_COMMAND: 0x%08x HC_ARGUMENT: 0x%08x "
  335                     "HC_HOSTSTATUS: 0x%08x HC_HOSTCONFIG: 0x%08x\n",
  336                     line, RD4(sc, HC_COMMAND), RD4(sc, HC_ARGUMENT),
  337                     RD4(sc, HC_HOSTSTATUS), RD4(sc, HC_HOSTCONFIG));
  338                 */
  339         }
  340 }
  341 
  342 static void
  343 bcm_sdhost_reset(device_t dev, struct sdhci_slot *slot)
  344 {
  345         struct bcm_sdhost_softc *sc = device_get_softc(dev);
  346         u_int32_t dbg;
  347 
  348         WR4(sc, HC_POWER, 0);
  349 
  350         WR4(sc, HC_COMMAND, 0);
  351         WR4(sc, HC_ARGUMENT, 0);
  352         WR4(sc, HC_TIMEOUTCOUNTER, HC_TIMEOUT_DEFAULT);
  353         WR4(sc, HC_CLOCKDIVISOR, 0);
  354         WR4(sc, HC_HOSTSTATUS, HC_HSTST_RESET);
  355         WR4(sc, HC_HOSTCONFIG, 0);
  356         WR4(sc, HC_BLOCKSIZE, 0);
  357         WR4(sc, HC_BLOCKCOUNT, 0);
  358 
  359         dbg = RD4(sc, HC_DEBUG);
  360         dbg &= ~( (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_READ_SHIFT) |
  361                   (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_WRITE_SHIFT) );
  362         dbg |= (HC_FIFO_THRESH_READ << HC_DBG_FIFO_THRESH_READ_SHIFT) |
  363                (HC_FIFO_THRESH_WRITE << HC_DBG_FIFO_THRESH_WRITE_SHIFT);
  364         WR4(sc, HC_DEBUG, dbg);
  365 
  366         DELAY(250000);
  367 
  368         WR4(sc, HC_POWER, 1);
  369 
  370         DELAY(250000);
  371 
  372         sc->sdhci_present_state = SDHCI_CARD_PRESENT | SDHCI_CARD_STABLE |
  373                 SDHCI_WRITE_PROTECT;
  374 
  375         WR4(sc, HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_MAXVAL);
  376         WR4(sc, HC_HOSTCONFIG, HC_HSTCF_INT_BUSY);
  377 }
  378 
  379 static int
  380 bcm_sdhost_probe(device_t dev)
  381 {
  382 
  383         dprintf("%s:\n", __func__);
  384 
  385         if (!ofw_bus_status_okay(dev))
  386                 return (ENXIO);
  387 
  388         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  389                 return (ENXIO);
  390 
  391         device_set_desc(dev, "Broadcom 2708 SDHOST controller");
  392 
  393         return (BUS_PROBE_DEFAULT);
  394 }
  395 
  396 static int
  397 bcm_sdhost_attach(device_t dev)
  398 {
  399         struct bcm_sdhost_softc *sc = device_get_softc(dev);
  400         int rid, err;
  401         u_int default_freq;
  402 
  403         dprintf("%s: dev=%p sc=%p unit=%d\n",
  404             __func__, dev, sc, device_get_unit(dev));
  405 
  406         mtx_init(&sc->mtx, "BCM SDHOST mtx", "bcm_sdhost",
  407             MTX_DEF | MTX_RECURSE);
  408 
  409         sc->sc_dev = dev;
  410         sc->sc_req = NULL;
  411 
  412         sc->cmdbusy = 0;
  413         sc->mmc_app_cmd = 0;
  414         sc->sdhci_int_status = 0;
  415         sc->sdhci_signal_enable = 0;
  416         sc->sdhci_present_state = 0;
  417         sc->sdhci_blocksize = 0;
  418         sc->sdhci_blockcount = 0;
  419 
  420         sc->sdcard_rca = 0;
  421 
  422         default_freq = 50;
  423         err = 0;
  424 
  425         if (bootverbose)
  426                 device_printf(dev, "SDHCI frequency: %dMHz\n", default_freq);
  427 
  428         rid = 0;
  429         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  430             RF_ACTIVE);
  431         if (!sc->sc_mem_res) {
  432                 device_printf(dev, "cannot allocate memory window\n");
  433                 err = ENXIO;
  434                 goto fail;
  435         }
  436 
  437         sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
  438         sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
  439 
  440         bcm_sdhost_reset(dev, &sc->sc_slot);
  441 
  442         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
  443 
  444         rid = 0;
  445         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  446             RF_ACTIVE);
  447         if (!sc->sc_irq_res) {
  448                 device_printf(dev, "cannot allocate interrupt\n");
  449                 err = ENXIO;
  450                 goto fail;
  451         }
  452 
  453         if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
  454             NULL, bcm_sdhost_intr, sc, &sc->sc_intrhand)) {
  455                 device_printf(dev, "cannot setup interrupt handler\n");
  456                 err = ENXIO;
  457                 goto fail;
  458         }
  459 
  460         sc->sc_slot.caps = 0;
  461         sc->sc_slot.caps |= SDHCI_CAN_VDD_330;
  462         sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD;
  463         sc->sc_slot.caps |= (default_freq << SDHCI_CLOCK_BASE_SHIFT);
  464 
  465         sc->sc_slot.quirks = 0;
  466         sc->sc_slot.quirks |= SDHCI_QUIRK_MISSING_CAPS;
  467         sc->sc_slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
  468 
  469         sc->sc_slot.opt = 0;
  470 
  471         /* XXX ?
  472         sc->slot->timeout_clk = ...;
  473         */
  474 
  475         sdhci_init_slot(dev, &sc->sc_slot, 0);
  476 
  477         bus_generic_probe(dev);
  478         bus_generic_attach(dev);
  479 
  480         sdhci_start_slot(&sc->sc_slot);
  481 
  482         return (0);
  483 
  484     fail:
  485         if (sc->sc_intrhand)
  486                 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
  487         if (sc->sc_irq_res)
  488                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
  489         if (sc->sc_mem_res)
  490                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
  491 
  492         return (err);
  493 }
  494 
  495 static int
  496 bcm_sdhost_detach(device_t dev)
  497 {
  498 
  499         dprintf("%s:\n", __func__);
  500 
  501         return (EBUSY);
  502 }
  503 
  504 /*
  505  * rv 0 --> command finished
  506  * rv 1 --> command timed out
  507  */
  508 static inline int
  509 bcm_sdhost_waitcommand(struct bcm_sdhost_softc *sc)
  510 {
  511         int timeout = 1000;
  512 
  513         mtx_assert(&sc->mtx, MA_OWNED);
  514 
  515         while ((RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) && --timeout > 0) {
  516                 DELAY(100);
  517         }
  518 
  519         return ((timeout > 0) ? 0 : 1);
  520 }
  521 
  522 static int
  523 bcm_sdhost_waitcommand_status(struct bcm_sdhost_softc *sc)
  524 {
  525         u_int32_t cdst;
  526         int i;
  527 
  528         /* wait for card to change status from
  529          * ''prg'' to ''trn''
  530          * card status: sd specs p. 103
  531          */
  532         i = 0;
  533         do {
  534                 DELAY(1000);
  535                 WR4(sc, HC_ARGUMENT, sc->sdcard_rca << 16);
  536                 WR4(sc, HC_COMMAND,
  537                     MMC_SEND_STATUS | HC_CMD_ENABLE);
  538                 bcm_sdhost_waitcommand(sc);
  539                 cdst = RD4(sc, HC_RESPONSE_0);
  540                 dprintf("%s: card status %08x (cs %d)\n",
  541                     __func__, cdst, (cdst & 0x0e00) >> 9);
  542                 if (i++ > 100) {
  543                         printf("%s: giving up, "
  544                             "card status %08x (cs %d)\n",
  545                             __func__, cdst,
  546                             (cdst & 0x0e00) >> 9);
  547                         return (1);
  548                         break;
  549                 }
  550         } while (((cdst & 0x0e00) >> 9) != 4);
  551 
  552         return (0);
  553 }
  554 
  555 static void
  556 bcm_sdhost_intr(void *arg)
  557 {
  558         struct bcm_sdhost_softc *sc = arg;
  559         struct sdhci_slot *slot = &sc->sc_slot;
  560         uint32_t hstst;
  561         uint32_t cmd;
  562 
  563         mtx_lock(&sc->mtx);
  564 
  565         hstst = RD4(sc, HC_HOSTSTATUS);
  566         cmd = RD4(sc, HC_COMMAND);
  567         if (hstst & HC_HSTST_HAVEDATA) {
  568                 if (cmd & HC_CMD_READ) {
  569                         sc->sdhci_present_state |= SDHCI_DATA_AVAILABLE;
  570                         sc->sdhci_int_status |= SDHCI_INT_DATA_AVAIL;
  571                 } else if (cmd & HC_CMD_WRITE) {
  572                         sc->sdhci_present_state |= SDHCI_SPACE_AVAILABLE;
  573                         sc->sdhci_int_status |= SDHCI_INT_SPACE_AVAIL;
  574                 } else {
  575                         panic("%s: hstst & HC_HSTST_HAVEDATA but no "
  576                             "HC_CMD_READ or HC_CMD_WRITE: cmd=%0x8 "
  577                             "hstst=%08x\n", __func__, cmd, hstst);
  578                 }
  579         } else {
  580                 sc->sdhci_present_state &=
  581                     ~(SDHCI_DATA_AVAILABLE|SDHCI_SPACE_AVAILABLE);
  582                 sc->sdhci_int_status &=
  583                     ~(SDHCI_INT_DATA_AVAIL|SDHCI_INT_SPACE_AVAIL);
  584         }
  585 
  586         if (hstst & HC_HSTST_MASK_ERROR_ALL) {
  587                 printf("%s: ERROR: HC_HOSTSTATUS: %08x\n", __func__, hstst);
  588                 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
  589                 sc->sdhci_int_status |= SDHCI_INT_ERROR;
  590         } else {
  591                 sc->sdhci_int_status &= ~SDHCI_INT_ERROR;
  592         }
  593 
  594         dprintf("%s: hstst=%08x offset=%08lx sdhci_present_state=%08x "
  595             "sdhci_int_status=%08x\n", __func__, hstst, slot->offset,
  596             sc->sdhci_present_state, sc->sdhci_int_status);
  597 
  598         sdhci_generic_intr(&sc->sc_slot);
  599 
  600         sc->sdhci_int_status &=
  601             ~(SDHCI_INT_ERROR|SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END);
  602         sc->sdhci_present_state &= ~SDHCI_DATA_AVAILABLE;
  603 
  604         if ((hstst & HC_HSTST_HAVEDATA) &&
  605             (sc->sdhci_blocksize * sc->sdhci_blockcount == slot->offset)) {
  606                 dprintf("%s: offset=%08lx sdhci_blocksize=%08x "
  607                     "sdhci_blockcount=%08x\n", __func__, slot->offset,
  608                     sc->sdhci_blocksize, sc->sdhci_blockcount);
  609                 sc->sdhci_int_status &=
  610                     ~(SDHCI_INT_DATA_AVAIL|SDHCI_INT_SPACE_AVAIL);
  611                 sc->sdhci_int_status |= SDHCI_INT_DATA_END;
  612                 sdhci_generic_intr(&sc->sc_slot);
  613                 sc->sdhci_int_status &= ~SDHCI_INT_DATA_END;
  614 
  615                 if ((cmd & HC_CMD_COMMAND_MASK) == MMC_READ_MULTIPLE_BLOCK ||
  616                     (cmd & HC_CMD_COMMAND_MASK) == MMC_WRITE_MULTIPLE_BLOCK) {
  617                         WR4(sc, HC_ARGUMENT, 0x00000000);
  618                         WR4(sc, HC_COMMAND,
  619                             MMC_STOP_TRANSMISSION | HC_CMD_ENABLE);
  620 
  621                         if (bcm_sdhost_waitcommand(sc)) {
  622                                 printf("%s: timeout #1\n", __func__);
  623                                 bcm_sdhost_print_regs(sc, &sc->sc_slot,
  624                                     __LINE__, 1);
  625                         }
  626                 }
  627 
  628                 if (cmd & HC_CMD_WRITE) {
  629                         if (bcm_sdhost_waitcommand_status(sc) != 0)
  630                                 sc->sdhci_int_status |= SDHCI_INT_ERROR;
  631                 }
  632 
  633                 slot->data_done = 1;
  634 
  635                 sc->sdhci_int_status |= SDHCI_INT_RESPONSE;
  636                 sdhci_generic_intr(&sc->sc_slot);
  637                 sc->sdhci_int_status &= ~(SDHCI_INT_RESPONSE|SDHCI_INT_ERROR);
  638         }
  639 
  640         /* this resets the interrupt */
  641         WR4(sc, HC_HOSTSTATUS,
  642             (HC_HSTST_INT_BUSY|HC_HSTST_INT_BLOCK|HC_HSTST_HAVEDATA));
  643 
  644         mtx_unlock(&sc->mtx);
  645 }
  646 
  647 static int
  648 bcm_sdhost_get_ro(device_t bus, device_t child)
  649 {
  650 
  651         dprintf("%s:\n", __func__);
  652 
  653         return (0);
  654 }
  655 
  656 static bool
  657 bcm_sdhost_get_card_present(device_t dev, struct sdhci_slot *slot)
  658 {
  659 
  660         dprintf("%s:\n", __func__);
  661 
  662         return (1);
  663 }
  664 
  665 static void
  666 bcm_sdhost_command(device_t dev, struct sdhci_slot *slot, uint16_t val)
  667 {
  668         struct bcm_sdhost_softc *sc = device_get_softc(dev);
  669         struct mmc_data *data = slot->curcmd->data;
  670         uint16_t val2;
  671         uint8_t opcode;
  672         uint8_t flags;
  673 
  674         mtx_assert(&sc->mtx, MA_OWNED);
  675 
  676         if (RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) {
  677                 panic("%s: HC_CMD_ENABLE on entry\n", __func__);
  678         }
  679 
  680         if (sc->cmdbusy == 1)
  681                 panic("%s: cmdbusy\n", __func__);
  682 
  683         sc->cmdbusy = 1;
  684 
  685         val2 = ((val >> 8) & HC_CMD_COMMAND_MASK) | HC_CMD_ENABLE;
  686 
  687         opcode = val >> 8;
  688         flags = val & 0xff;
  689 
  690         if (opcode == MMC_APP_CMD)
  691                 sc->mmc_app_cmd = 1;
  692 
  693         if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_LONG)
  694                 val2 |= HC_CMD_RESPONSE_LONG;
  695         else if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT_BUSY)
  696                 /* XXX XXX when enabled, cmd 7 (select card) blocks forever */
  697                 ;/*val2 |= HC_CMD_BUSY; */
  698         else if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT)
  699                 ;
  700         else
  701                 val2 |= HC_CMD_RESPONSE_NONE;
  702 
  703         if (val2 & HC_CMD_BUSY)
  704                 sc->sdhci_present_state |=
  705                     SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT;
  706 
  707         if (data != NULL && data->flags & MMC_DATA_READ)
  708                 val2 |= HC_CMD_READ;
  709         else if (data != NULL && data->flags & MMC_DATA_WRITE)
  710                 val2 |= HC_CMD_WRITE;
  711 
  712         dprintf("%s: SDHCI_COMMAND_FLAGS --> HC_COMMAND   %04x --> %04x\n",
  713             __func__, val, val2);
  714 
  715         if (opcode == MMC_READ_MULTIPLE_BLOCK ||
  716             opcode == MMC_WRITE_MULTIPLE_BLOCK) {
  717                 u_int32_t save_sdarg;
  718 
  719                 dprintf("%s: issuing MMC_SET_BLOCK_COUNT: CMD %08x ARG %08x\n",
  720                     __func__, MMC_SET_BLOCK_COUNT | HC_CMD_ENABLE,
  721                     sc->sdhci_blockcount);
  722 
  723                 save_sdarg = RD4(sc, HC_ARGUMENT);
  724                 WR4(sc, HC_ARGUMENT, sc->sdhci_blockcount);
  725                 WR4(sc, HC_COMMAND, MMC_SET_BLOCK_COUNT | HC_CMD_ENABLE);
  726 
  727                 /* Seems to always return timeout */
  728 
  729                 if (bcm_sdhost_waitcommand(sc)) {
  730                         printf("%s: timeout #2\n", __func__);
  731                         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
  732                 } else {
  733                         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
  734                 }
  735                 WR4(sc, HC_ARGUMENT, save_sdarg);
  736 
  737         } else if (opcode == MMC_SELECT_CARD) {
  738                 sc->sdcard_rca = (RD4(sc, HC_ARGUMENT) >> 16);
  739         }
  740 
  741         /* actually issuing the command */
  742         WR4(sc, HC_COMMAND, val2);
  743 
  744         if (val2 & HC_CMD_READ || val2 & HC_CMD_WRITE) {
  745                 u_int8_t hstcfg;
  746 
  747                 hstcfg = RD4(sc, HC_HOSTCONFIG);
  748                 hstcfg |= (HC_HSTCF_INT_BUSY | HC_HSTCF_INT_DATA);
  749                 WR4(sc, HC_HOSTCONFIG, hstcfg);
  750                 slot->data_done = 0;
  751 
  752                 if (bcm_sdhost_waitcommand(sc)) {
  753                         printf("%s: timeout #3\n", __func__);
  754                         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
  755                 }
  756 
  757         } else if (opcode == MMC_ERASE) {
  758                 if (bcm_sdhost_waitcommand_status(sc) != 0) {
  759                         printf("%s: timeout #4\n", __func__);
  760                         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
  761                 }
  762                 slot->data_done = 1;
  763                 sc->sdhci_present_state &=
  764                     ~(SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT);
  765 
  766         } else {
  767                 if (bcm_sdhost_waitcommand(sc)) {
  768                         printf("%s: timeout #5\n", __func__);
  769                         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
  770                 }
  771                 slot->data_done = 1;
  772                 sc->sdhci_present_state &=
  773                     ~(SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT);
  774         }
  775 
  776         bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
  777 
  778         if (RD4(sc, HC_HOSTSTATUS) & HC_HSTST_TIMEOUT_CMD)
  779                 slot->curcmd->error = MMC_ERR_TIMEOUT;
  780         else if (RD4(sc, HC_COMMAND) & HC_CMD_FAILED)
  781                 slot->curcmd->error = MMC_ERR_FAILED;
  782 
  783         dprintf("%s: curcmd->flags=%d data_done=%d\n",
  784             __func__, slot->curcmd->flags, slot->data_done);
  785 
  786         if (val2 & HC_CMD_RESPONSE_NONE)
  787                 slot->curcmd->error = 0;
  788 
  789         if (sc->mmc_app_cmd == 1 && opcode != MMC_APP_CMD)
  790                 sc->mmc_app_cmd = 0;
  791 
  792         if (RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) {
  793                 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
  794                 panic("%s: still HC_CMD_ENABLE on exit\n", __func__);
  795         }
  796 
  797         sc->cmdbusy = 0;
  798 
  799         if (!(val2 & HC_CMD_READ || val2 & HC_CMD_WRITE))
  800                 sc->sdhci_int_status |= SDHCI_INT_RESPONSE;
  801 
  802         /* HACK, so sdhci_finish_command() does not
  803          * have to be exported
  804          */
  805         mtx_unlock(&slot->mtx);
  806         sdhci_generic_intr(slot);
  807         mtx_lock(&slot->mtx);
  808         sc->sdhci_int_status &= ~SDHCI_INT_RESPONSE;
  809 }
  810 
  811 static uint8_t
  812 bcm_sdhost_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
  813 {
  814         struct bcm_sdhost_softc *sc = device_get_softc(dev);
  815         uint32_t val1, val2;
  816 
  817         mtx_lock(&sc->mtx);
  818 
  819         switch (off) {
  820         case SDHCI_HOST_CONTROL:
  821                 val1 = RD4(sc, HC_HOSTCONFIG);
  822                 val2 = 0;
  823                 if (val1 & HC_HSTCF_EXTBUS_4BIT)
  824                         val2 |= SDHCI_CTRL_4BITBUS;
  825                 dprintf("%s: SDHCI_HOST_CONTROL --> HC_HOSTCONFIG val2 %02x\n",
  826                     __func__, val2);
  827                 break;
  828         case SDHCI_POWER_CONTROL:
  829                 val1 = RD1(sc, HC_POWER);
  830                 val2 = (val1 == 1) ? 0x0f : 0;
  831                 dprintf("%s: SDHCI_POWER_CONTROL --> HC_POWER     val2 %02x\n",
  832                     __func__, val2);
  833                 break;
  834         case SDHCI_BLOCK_GAP_CONTROL:
  835                 dprintf("%s: SDHCI_BLOCK_GAP_CONTROL\n", __func__);
  836                 val2 = 0;
  837                 break;
  838         case SDHCI_WAKE_UP_CONTROL:
  839                 dprintf("%s: SDHCI_WAKE_UP_CONTROL\n", __func__);
  840                 val2 = 0;
  841                 break;
  842         case SDHCI_TIMEOUT_CONTROL:
  843                 dprintf("%s: SDHCI_TIMEOUT_CONTROL\n", __func__);
  844                 val2 = 0;
  845                 break;
  846         case SDHCI_SOFTWARE_RESET:
  847                 dprintf("%s: SDHCI_SOFTWARE_RESET\n", __func__);
  848                 val2 = 0;
  849                 break;
  850         case SDHCI_ADMA_ERR:
  851                 dprintf("%s: SDHCI_ADMA_ERR\n", __func__);
  852                 val2 = 0;
  853                 break;
  854         default:
  855                 dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
  856                 val2 = 0;
  857                 break;
  858         }
  859 
  860         mtx_unlock(&sc->mtx);
  861 
  862         return (val2);
  863 }
  864 
  865 static uint16_t
  866 bcm_sdhost_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
  867 {
  868         struct bcm_sdhost_softc *sc = device_get_softc(dev);
  869         uint32_t val2, val; /* = RD4(sc, off & ~3); */
  870 
  871         mtx_lock(&sc->mtx);
  872 
  873         switch (off) {
  874         case SDHCI_BLOCK_SIZE:
  875                 val2 = sc->sdhci_blocksize;
  876                 dprintf("%s: SDHCI_BLOCK_SIZE      --> HC_BLOCKSIZE   %08x\n",
  877                     __func__, val2);
  878                 break;
  879         case SDHCI_BLOCK_COUNT:
  880                 val2 = sc->sdhci_blockcount;
  881                 dprintf("%s: SDHCI_BLOCK_COUNT     --> HC_BLOCKCOUNT  %08x\n",
  882                     __func__, val2);
  883                 break;
  884         case SDHCI_TRANSFER_MODE:
  885                 dprintf("%s: SDHCI_TRANSFER_MODE\n", __func__);
  886                 val2 = 0;
  887                 break;
  888         case SDHCI_CLOCK_CONTROL:
  889                 val = RD4(sc, HC_CLOCKDIVISOR);
  890                 val2 = (val << SDHCI_DIVIDER_SHIFT) |
  891                     SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN |
  892                     SDHCI_CLOCK_INT_STABLE;
  893                 dprintf("%s: SDHCI_CLOCK_CONTROL     %04x --> %04x\n",
  894                     __func__, val, val2);
  895                 break;
  896         case SDHCI_ACMD12_ERR:
  897                 dprintf("%s: SDHCI_ACMD12_ERR\n", __func__);
  898                 val2 = 0;
  899                 break;
  900         case SDHCI_HOST_CONTROL2:
  901                 dprintf("%s: SDHCI_HOST_CONTROL2\n", __func__);
  902                 val2 = 0;
  903                 break;
  904         case SDHCI_SLOT_INT_STATUS:
  905                 dprintf("%s: SDHCI_SLOT_INT_STATUS\n", __func__);
  906                 val2 = 0;
  907                 break;
  908         case SDHCI_HOST_VERSION:
  909                 dprintf("%s: SDHCI_HOST_VERSION\n", __func__);
  910                 val2 = 0;
  911                 break;
  912         default:
  913                 dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
  914                 val2 = 0;
  915                 break;
  916         }
  917 
  918         mtx_unlock(&sc->mtx);
  919 
  920         return (val2);
  921 }
  922 
  923 static uint32_t
  924 bcm_sdhost_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
  925 {
  926         struct bcm_sdhost_softc *sc = device_get_softc(dev);
  927         uint32_t val2;
  928 
  929         mtx_lock(&sc->mtx);
  930 
  931         switch (off) {
  932         case SDHCI_DMA_ADDRESS:
  933                 dprintf("%s: SDHCI_DMA_ADDRESS\n", __func__);
  934                 val2 = 0;
  935                 break;
  936         case SDHCI_ARGUMENT:
  937                 dprintf("%s: SDHCI_ARGUMENT\n", __func__);
  938                 val2 = (RD4(sc, HC_COMMAND) << 16) |
  939                     (RD4(sc, HC_ARGUMENT) & 0x0000ffff);
  940                 break;
  941         case SDHCI_RESPONSE + 0:
  942                 val2 = RD4(sc, HC_RESPONSE_0);
  943                 dprintf("%s: SDHCI_RESPONSE+0       %08x\n", __func__, val2);
  944                 break;
  945         case SDHCI_RESPONSE + 4:
  946                 val2 = RD4(sc, HC_RESPONSE_1);
  947                 dprintf("%s: SDHCI_RESPONSE+4       %08x\n", __func__, val2);
  948                 break;
  949         case SDHCI_RESPONSE + 8:
  950                 val2 = RD4(sc, HC_RESPONSE_2);
  951                 dprintf("%s: SDHCI_RESPONSE+8       %08x\n", __func__, val2);
  952                 break;
  953         case SDHCI_RESPONSE + 12:
  954                 val2 = RD4(sc, HC_RESPONSE_3);
  955                 dprintf("%s: SDHCI_RESPONSE+12      %08x\n", __func__, val2);
  956                 break;
  957         case SDHCI_BUFFER:
  958                 dprintf("%s: SDHCI_BUFFER\n", __func__);
  959                 val2 = 0;
  960                 break;
  961         case SDHCI_PRESENT_STATE:
  962                 dprintf("%s: SDHCI_PRESENT_STATE      %08x\n",
  963                     __func__, sc->sdhci_present_state);
  964                 val2 = sc->sdhci_present_state;
  965                 break;
  966         case SDHCI_INT_STATUS:
  967                 dprintf("%s: SDHCI_INT_STATUS        %08x\n",
  968                     __func__, sc->sdhci_int_status);
  969                 val2 = sc->sdhci_int_status;
  970                 break;
  971         case SDHCI_INT_ENABLE:
  972                 dprintf("%s: SDHCI_INT_ENABLE\n", __func__);
  973                 val2 = 0;
  974                 break;
  975         case SDHCI_SIGNAL_ENABLE:
  976                 dprintf("%s: SDHCI_SIGNAL_ENABLE      %08x\n",
  977                     __func__, sc->sdhci_signal_enable);
  978                 val2 = sc->sdhci_signal_enable;
  979                 break;
  980         case SDHCI_CAPABILITIES:
  981                 val2 = 0;
  982                 break;
  983         case SDHCI_CAPABILITIES2:
  984                 dprintf("%s: SDHCI_CAPABILITIES2\n", __func__);
  985                 val2 = 0;
  986                 break;
  987         case SDHCI_MAX_CURRENT:
  988                 dprintf("%s: SDHCI_MAX_CURRENT\n", __func__);
  989                 val2 = 0;
  990                 break;
  991         case SDHCI_ADMA_ADDRESS_LO:
  992                 dprintf("%s: SDHCI_ADMA_ADDRESS_LO\n", __func__);
  993                 val2 = 0;
  994                 break;
  995         default:
  996                 dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
  997                 val2 = 0;
  998                 break;
  999         }
 1000 
 1001         mtx_unlock(&sc->mtx);
 1002 
 1003         return (val2);
 1004 }
 1005 
 1006 static void
 1007 bcm_sdhost_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
 1008     uint32_t *data, bus_size_t count)
 1009 {
 1010         struct bcm_sdhost_softc *sc = device_get_softc(dev);
 1011         bus_size_t i;
 1012         bus_size_t avail;
 1013         uint32_t edm;
 1014 
 1015         mtx_lock(&sc->mtx);
 1016 
 1017         dprintf("%s: off=%08lx count=%08lx\n", __func__, off, count);
 1018 
 1019         for (i = 0; i < count;) {
 1020                 edm = RD4(sc, HC_DEBUG);
 1021                 avail = ((edm >> 4) & 0x1f);
 1022                 if (i + avail > count)
 1023                         avail = count - i;
 1024                 if (avail > 0)
 1025                         bus_space_read_multi_4(sc->sc_bst, sc->sc_bsh,
 1026                             HC_DATAPORT, data + i, avail);
 1027                 i += avail;
 1028                 DELAY(1);
 1029         }
 1030 
 1031         mtx_unlock(&sc->mtx);
 1032 }
 1033 
 1034 static void
 1035 bcm_sdhost_write_1(device_t dev, struct sdhci_slot *slot,
 1036     bus_size_t off, uint8_t val)
 1037 {
 1038         struct bcm_sdhost_softc *sc = device_get_softc(dev);
 1039         uint32_t val2;
 1040 
 1041         mtx_lock(&sc->mtx);
 1042 
 1043         switch (off) {
 1044         case SDHCI_HOST_CONTROL:
 1045                 val2 = RD4(sc, HC_HOSTCONFIG);
 1046                 val2 |= HC_HSTCF_INT_BUSY;
 1047                 val2 |= HC_HSTCF_INTBUS_WIDE | HC_HSTCF_SLOW_CARD;
 1048                 if (val & SDHCI_CTRL_4BITBUS)
 1049                         val2 |= HC_HSTCF_EXTBUS_4BIT;
 1050                 dprintf("%s: SDHCI_HOST_CONTROL --> HC_HOSTC %04x --> %04x\n",
 1051                     __func__, val, val2);
 1052                 WR4(sc, HC_HOSTCONFIG, val2);
 1053                 break;
 1054         case SDHCI_POWER_CONTROL:
 1055                 val2 = (val != 0) ? 1 : 0;
 1056                 dprintf("%s: SDHCI_POWER_CONTROL --> HC_POWER %02x --> %02x\n",
 1057                     __func__, val, val2);
 1058                 WR1(sc, HC_POWER, val2);
 1059                 break;
 1060         case SDHCI_BLOCK_GAP_CONTROL:
 1061                 dprintf("%s: SDHCI_BLOCK_GAP_CONTROL   val=%02x\n",
 1062                     __func__, val);
 1063                 break;
 1064         case SDHCI_TIMEOUT_CONTROL:
 1065                 dprintf("%s: SDHCI_TIMEOUT_CONTROL     val=%02x\n",
 1066                     __func__, val);
 1067                 break;
 1068         case SDHCI_SOFTWARE_RESET:
 1069                 dprintf("%s: SDHCI_SOFTWARE_RESET      val=%02x\n",
 1070                     __func__, val);
 1071                 break;
 1072         case SDHCI_ADMA_ERR:
 1073                 dprintf("%s: SDHCI_ADMA_ERR            val=%02x\n",
 1074                     __func__, val);
 1075                 break;
 1076         default:
 1077                 dprintf("%s: UNKNOWN off=%08lx val=%08x\n",
 1078                     __func__, off, val);
 1079                 break;
 1080         }
 1081 
 1082         mtx_unlock(&sc->mtx);
 1083 }
 1084 
 1085 static void
 1086 bcm_sdhost_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val)
 1087 {
 1088         struct bcm_sdhost_softc *sc = device_get_softc(dev);
 1089         uint16_t val2;
 1090 
 1091         mtx_lock(&sc->mtx);
 1092 
 1093         switch (off) {
 1094         case SDHCI_BLOCK_SIZE:
 1095                 dprintf("%s: SDHCI_BLOCK_SIZE          val=%04x\n" ,
 1096                     __func__, val);
 1097                 sc->sdhci_blocksize = val;
 1098                 WR2(sc, HC_BLOCKSIZE, val);
 1099                 break;
 1100 
 1101         case SDHCI_BLOCK_COUNT:
 1102                 dprintf("%s: SDHCI_BLOCK_COUNT         val=%04x\n" ,
 1103                     __func__, val);
 1104                 sc->sdhci_blockcount = val;
 1105                 WR2(sc, HC_BLOCKCOUNT, val);
 1106                 break;
 1107 
 1108         case SDHCI_TRANSFER_MODE:
 1109                 dprintf("%s: SDHCI_TRANSFER_MODE       val=%04x\n" ,
 1110                     __func__, val);
 1111                 break;
 1112 
 1113         case SDHCI_COMMAND_FLAGS:
 1114                 bcm_sdhost_command(dev, slot, val);
 1115                 break;
 1116 
 1117         case SDHCI_CLOCK_CONTROL:
 1118                 val2 = (val & ~SDHCI_DIVIDER_MASK) >> SDHCI_DIVIDER_SHIFT;
 1119                 /* get crc16 errors with cdiv=0 */
 1120                 if (val2 == 0)
 1121                         val2 = 1;
 1122                 dprintf("%s: SDHCI_CLOCK_CONTROL       %04x --> SCDIV %04x\n",
 1123                     __func__, val, val2);
 1124                 WR4(sc, HC_CLOCKDIVISOR, val2);
 1125                 break;
 1126 
 1127         case SDHCI_ACMD12_ERR:
 1128                 dprintf("%s: SDHCI_ACMD12_ERR          val=%04x\n" ,
 1129                     __func__, val);
 1130                 break;
 1131 
 1132         case SDHCI_HOST_CONTROL2:
 1133                 dprintf("%s: SDHCI_HOST_CONTROL2       val=%04x\n" ,
 1134                     __func__, val);
 1135                 break;
 1136 
 1137         case SDHCI_SLOT_INT_STATUS:
 1138                 dprintf("%s: SDHCI_SLOT_INT_STATUS     val=%04x\n" ,
 1139                     __func__, val);
 1140                 break;
 1141 
 1142         default:
 1143                 dprintf("%s: UNKNOWN off=%08lx val=%04x\n",
 1144                     __func__, off, val);
 1145                 break;
 1146         }
 1147 
 1148         mtx_unlock(&sc->mtx);
 1149 }
 1150 
 1151 static void
 1152 bcm_sdhost_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val)
 1153 {
 1154         struct bcm_sdhost_softc *sc = device_get_softc(dev);
 1155         uint32_t val2;
 1156         uint32_t hstcfg;
 1157 
 1158         mtx_lock(&sc->mtx);
 1159 
 1160         switch (off) {
 1161         case SDHCI_ARGUMENT:
 1162                 val2 = val;
 1163                 dprintf("%s: SDHCI_ARGUMENT --> HC_ARGUMENT   val=%08x\n",
 1164                     __func__, val);
 1165                 WR4(sc, HC_ARGUMENT, val2);
 1166                 break;
 1167         case SDHCI_INT_STATUS:
 1168                 dprintf("%s: SDHCI_INT_STATUS           val=%08x\n",
 1169                     __func__, val);
 1170                 sc->sdhci_int_status = val;
 1171                 break;
 1172         case SDHCI_INT_ENABLE:
 1173                 dprintf("%s: SDHCI_INT_ENABLE          val=%08x\n" ,
 1174                      __func__, val);
 1175                 break;
 1176         case SDHCI_SIGNAL_ENABLE:
 1177                 sc->sdhci_signal_enable = val;
 1178                 hstcfg = RD4(sc, HC_HOSTCONFIG);
 1179                 if (val != 0)
 1180                         hstcfg &= ~(HC_HSTCF_INT_BLOCK | HC_HSTCF_INT_DATA);
 1181                 else
 1182                         hstcfg |= (HC_HSTCF_INT_BUSY|HC_HSTCF_INT_BLOCK|
 1183                                  HC_HSTCF_INT_DATA);
 1184                 hstcfg |= HC_HSTCF_INT_BUSY;
 1185                 dprintf("%s: SDHCI_SIGNAL_ENABLE --> HC_HOSTC %08x --> %08x\n" ,
 1186                     __func__, val, hstcfg);
 1187                 WR4(sc, HC_HOSTCONFIG, hstcfg);
 1188                 break;
 1189         case SDHCI_CAPABILITIES:
 1190                 dprintf("%s: SDHCI_CAPABILITIES        val=%08x\n",
 1191                     __func__, val);
 1192                 break;
 1193         case SDHCI_CAPABILITIES2:
 1194                 dprintf("%s: SDHCI_CAPABILITIES2       val=%08x\n",
 1195                     __func__, val);
 1196                 break;
 1197         case SDHCI_MAX_CURRENT:
 1198                 dprintf("%s: SDHCI_MAX_CURRENT         val=%08x\n",
 1199                     __func__, val);
 1200                 break;
 1201         case SDHCI_ADMA_ADDRESS_LO:
 1202                 dprintf("%s: SDHCI_ADMA_ADDRESS_LO     val=%08x\n",
 1203                     __func__, val);
 1204                 break;
 1205         default:
 1206                 dprintf("%s: UNKNOWN off=%08lx val=%08x\n",
 1207                     __func__, off, val);
 1208                 break;
 1209         }
 1210 
 1211         mtx_unlock(&sc->mtx);
 1212 }
 1213 
 1214 static void
 1215 bcm_sdhost_write_multi_4(device_t dev, struct sdhci_slot *slot,
 1216     bus_size_t off, uint32_t *data, bus_size_t count)
 1217 {
 1218         struct bcm_sdhost_softc *sc = device_get_softc(dev);
 1219         bus_size_t i;
 1220         bus_size_t space;
 1221         uint32_t edm;
 1222 
 1223         mtx_lock(&sc->mtx);
 1224 
 1225         dprintf("%s: off=%08lx count=%02lx\n", __func__, off, count);
 1226 
 1227         for (i = 0; i < count;) {
 1228                 edm = RD4(sc, HC_DEBUG);
 1229                 space = HC_FIFO_SIZE - ((edm >> 4) & 0x1f);
 1230                 if (i + space > count)
 1231                         space = count - i;
 1232                 if (space > 0)
 1233                         bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh,
 1234                             HC_DATAPORT, data + i, space);
 1235                 i += space;
 1236                 DELAY(1);
 1237         }
 1238 
 1239         /* wait until FIFO is really empty */
 1240         while (((RD4(sc, HC_DEBUG) >> 4) & 0x1f) > 0)
 1241                 DELAY(1);
 1242 
 1243         mtx_unlock(&sc->mtx);
 1244 }
 1245 
 1246 static device_method_t bcm_sdhost_methods[] = {
 1247         /* Device interface */
 1248         DEVMETHOD(device_probe,         bcm_sdhost_probe),
 1249         DEVMETHOD(device_attach,        bcm_sdhost_attach),
 1250         DEVMETHOD(device_detach,        bcm_sdhost_detach),
 1251 
 1252         /* Bus interface */
 1253         DEVMETHOD(bus_read_ivar,        sdhci_generic_read_ivar),
 1254         DEVMETHOD(bus_write_ivar,       sdhci_generic_write_ivar),
 1255 
 1256         /* MMC bridge interface */
 1257         DEVMETHOD(mmcbr_update_ios,     sdhci_generic_update_ios),
 1258         DEVMETHOD(mmcbr_request,        sdhci_generic_request),
 1259         DEVMETHOD(mmcbr_get_ro,         bcm_sdhost_get_ro),
 1260         DEVMETHOD(mmcbr_acquire_host,   sdhci_generic_acquire_host),
 1261         DEVMETHOD(mmcbr_release_host,   sdhci_generic_release_host),
 1262 
 1263         /* SDHCI registers accessors */
 1264         DEVMETHOD(sdhci_read_1,         bcm_sdhost_read_1),
 1265         DEVMETHOD(sdhci_read_2,         bcm_sdhost_read_2),
 1266         DEVMETHOD(sdhci_read_4,         bcm_sdhost_read_4),
 1267         DEVMETHOD(sdhci_read_multi_4,   bcm_sdhost_read_multi_4),
 1268         DEVMETHOD(sdhci_write_1,        bcm_sdhost_write_1),
 1269         DEVMETHOD(sdhci_write_2,        bcm_sdhost_write_2),
 1270         DEVMETHOD(sdhci_write_4,        bcm_sdhost_write_4),
 1271         DEVMETHOD(sdhci_write_multi_4,  bcm_sdhost_write_multi_4),
 1272         DEVMETHOD(sdhci_get_card_present,bcm_sdhost_get_card_present),
 1273 
 1274         DEVMETHOD_END
 1275 };
 1276 
 1277 static driver_t bcm_sdhost_driver = {
 1278         "sdhost_bcm",
 1279         bcm_sdhost_methods,
 1280         sizeof(struct bcm_sdhost_softc),
 1281 };
 1282 
 1283 DRIVER_MODULE(sdhost_bcm, simplebus, bcm_sdhost_driver, NULL, NULL);
 1284 SDHCI_DEPEND(sdhost_bcm);
 1285 #ifndef MMCCAM
 1286 MMC_DECLARE_BRIDGE(sdhost_bcm);
 1287 #endif

Cache object: 5bbdd3e5dbc588bc71bb698abea24a01


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