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

          Line data    Source code
       1             : /*      $OpenBSD: sdmmc_io.c,v 1.40 2018/08/09 13:52:36 patrick Exp $   */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /* Routines for SD I/O cards. */
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/device.h>
      23             : #include <sys/kernel.h>
      24             : #include <sys/malloc.h>
      25             : #include <sys/systm.h>
      26             : 
      27             : #include <dev/sdmmc/sdmmc_ioreg.h>
      28             : #include <dev/sdmmc/sdmmcchip.h>
      29             : #include <dev/sdmmc/sdmmcvar.h>
      30             : 
      31             : struct sdmmc_intr_handler {
      32             :         struct sdmmc_softc *ih_softc;
      33             :         const char *ih_name;
      34             :         int (*ih_fun)(void *);
      35             :         void *ih_arg;
      36             :         TAILQ_ENTRY(sdmmc_intr_handler) entry;
      37             : };
      38             : 
      39             : int     sdmmc_submatch(struct device *, void *, void *);
      40             : int     sdmmc_print(void *, const char *);
      41             : int     sdmmc_io_rw_direct(struct sdmmc_softc *, struct sdmmc_function *,
      42             :             int, u_char *, int);
      43             : int     sdmmc_io_rw_extended_subr(struct sdmmc_softc *, struct sdmmc_function *,
      44             :             bus_dmamap_t, int, u_char *, int, int);
      45             : int     sdmmc_io_rw_extended(struct sdmmc_softc *, struct sdmmc_function *,
      46             :             int, u_char *, int, int);
      47             : int     sdmmc_io_xchg(struct sdmmc_softc *, struct sdmmc_function *,
      48             :             int, u_char *);
      49             : void    sdmmc_io_reset(struct sdmmc_softc *);
      50             : int     sdmmc_io_send_op_cond(struct sdmmc_softc *, u_int32_t, u_int32_t *);
      51             : void    sdmmc_io_set_blocklen(struct sdmmc_function *, unsigned int);
      52             : void    sdmmc_io_set_bus_width(struct sdmmc_function *, int);
      53             : int     sdmmc_io_set_highspeed(struct sdmmc_function *sf, int);
      54             : 
      55             : #ifdef SDMMC_DEBUG
      56             : #define DPRINTF(s)      printf s
      57             : #else
      58             : #define DPRINTF(s)      /**/
      59             : #endif
      60             : 
      61             : #ifdef SDMMC_DEBUG
      62             : int     sdmmc_verbose = 1;
      63             : #else
      64             : int     sdmmc_verbose = 0;
      65             : #endif
      66             : 
      67             : /*
      68             :  * Initialize SD I/O card functions (before memory cards).  The host
      69             :  * system and controller must support card interrupts in order to use
      70             :  * I/O functions.
      71             :  */
      72             : int
      73           0 : sdmmc_io_enable(struct sdmmc_softc *sc)
      74             : {
      75             :         u_int32_t host_ocr;
      76           0 :         u_int32_t card_ocr;
      77             : 
      78           0 :         rw_assert_wrlock(&sc->sc_lock);
      79             : 
      80             :         /* Set host mode to SD "combo" card. */
      81           0 :         SET(sc->sc_flags, SMF_SD_MODE|SMF_IO_MODE|SMF_MEM_MODE);
      82             : 
      83             :         /* Reset I/O functions. */
      84           0 :         sdmmc_io_reset(sc);
      85             : 
      86             :         /*
      87             :          * Read the I/O OCR value, determine the number of I/O
      88             :          * functions and whether memory is also present (a "combo
      89             :          * card") by issuing CMD5.  SD memory-only and MMC cards
      90             :          * do not respond to CMD5.
      91             :          */
      92           0 :         if (sdmmc_io_send_op_cond(sc, 0, &card_ocr) != 0) {
      93             :                 /* No SDIO card; switch to SD memory-only mode. */
      94           0 :                 CLR(sc->sc_flags, SMF_IO_MODE);
      95           0 :                 return 0;
      96             :         }
      97             : 
      98             :         /* Parse the additional bits in the I/O OCR value. */
      99           0 :         if (!ISSET(card_ocr, SD_IO_OCR_MEM_PRESENT)) {
     100             :                 /* SDIO card without memory (not a "combo card"). */
     101             :                 DPRINTF(("%s: no memory present\n", DEVNAME(sc)));
     102           0 :                 CLR(sc->sc_flags, SMF_MEM_MODE);
     103           0 :         }
     104           0 :         sc->sc_function_count = SD_IO_OCR_NUM_FUNCTIONS(card_ocr);
     105           0 :         if (sc->sc_function_count == 0) {
     106             :                 /* Useless SDIO card without any I/O functions. */
     107             :                 DPRINTF(("%s: no I/O functions\n", DEVNAME(sc)));
     108           0 :                 CLR(sc->sc_flags, SMF_IO_MODE);
     109           0 :                 return 0;
     110             :         }
     111           0 :         card_ocr &= SD_IO_OCR_MASK;
     112             : 
     113             :         /* Set the lowest voltage supported by the card and host. */
     114           0 :         host_ocr = sdmmc_chip_host_ocr(sc->sct, sc->sch);
     115           0 :         if (sdmmc_set_bus_power(sc, host_ocr, card_ocr) != 0) {
     116           0 :                 printf("%s: can't supply voltage requested by card\n",
     117           0 :                     DEVNAME(sc));
     118           0 :                 return 1;
     119             :         }
     120             : 
     121             :         /* Send the new OCR value until all cards are ready. */
     122           0 :         if (sdmmc_io_send_op_cond(sc, host_ocr, NULL) != 0) {
     123           0 :                 printf("%s: can't send I/O OCR\n", DEVNAME(sc));
     124           0 :                 return 1;
     125             :         }
     126           0 :         return 0;
     127           0 : }
     128             : 
     129             : /*
     130             :  * Allocate sdmmc_function structures for SD card I/O function
     131             :  * (including function 0).
     132             :  */
     133             : void
     134           0 : sdmmc_io_scan(struct sdmmc_softc *sc)
     135             : {
     136             :         struct sdmmc_function *sf0, *sf;
     137             :         int i;
     138             : 
     139           0 :         rw_assert_wrlock(&sc->sc_lock);
     140             : 
     141           0 :         sf0 = sdmmc_function_alloc(sc);
     142           0 :         sf0->number = 0;
     143           0 :         if (sdmmc_set_relative_addr(sc, sf0) != 0) {
     144           0 :                 printf("%s: can't set I/O RCA\n", DEVNAME(sc));
     145           0 :                 sdmmc_function_free(sf0);
     146           0 :                 return;
     147             :         }
     148           0 :         sc->sc_fn0 = sf0;
     149           0 :         SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf0, sf_list);
     150             : 
     151             :         /* Verify that the RCA has been set by selecting the card. */
     152           0 :         if (sdmmc_select_card(sc, sf0) != 0) {
     153           0 :                 printf("%s: can't select I/O RCA %d\n", DEVNAME(sc),
     154           0 :                     sf0->rca);
     155           0 :                 SET(sf0->flags, SFF_ERROR);
     156           0 :                 return;
     157             :         }
     158             : 
     159           0 :         for (i = 1; i <= sc->sc_function_count; i++) {
     160           0 :                 sf = sdmmc_function_alloc(sc);
     161           0 :                 sf->number = i;
     162           0 :                 sf->rca = sf0->rca;
     163           0 :                 sf->cookie = sc->sc_cookies[i];
     164             : 
     165           0 :                 SIMPLEQ_INSERT_TAIL(&sc->sf_head, sf, sf_list);
     166             :         }
     167           0 : }
     168             : 
     169             : /*
     170             :  * Initialize SDIO card functions.
     171             :  */
     172             : int
     173           0 : sdmmc_io_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
     174             : {
     175           0 :         rw_assert_wrlock(&sc->sc_lock);
     176             : 
     177           0 :         if (sdmmc_read_cis(sf, &sf->cis) != 0) {
     178           0 :                 printf("%s: can't read CIS\n", DEVNAME(sc));
     179           0 :                 SET(sf->flags, SFF_ERROR);
     180           0 :                 return 1;
     181             :         }
     182             : 
     183           0 :         sdmmc_check_cis_quirks(sf);
     184             : 
     185           0 :         if (sdmmc_verbose)
     186           0 :                 sdmmc_print_cis(sf);
     187             : 
     188           0 :         if (sf->number == 0) {
     189           0 :                 if (ISSET(sc->sc_caps, SMC_CAPS_SD_HIGHSPEED) &&
     190           0 :                     sdmmc_io_set_highspeed(sf, 1) == 0) {
     191           0 :                         (void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
     192             :                             SDMMC_SDCLK_50MHZ, SDMMC_TIMING_HIGHSPEED);
     193           0 :                         if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
     194           0 :                                 sdmmc_io_set_bus_width(sf, 4);
     195           0 :                                 sdmmc_chip_bus_width(sc->sct, sc->sch, 4);
     196           0 :                         }
     197             :                 } else
     198           0 :                         (void)sdmmc_chip_bus_clock(sc->sct, sc->sch,
     199             :                             SDMMC_SDCLK_25MHZ, SDMMC_TIMING_LEGACY);
     200             :         }
     201             : 
     202           0 :         return 0;
     203           0 : }
     204             : 
     205             : /*
     206             :  * Indicate whether the function is ready to operate.
     207             :  */
     208             : int
     209           0 : sdmmc_io_function_ready(struct sdmmc_function *sf)
     210             : {
     211           0 :         struct sdmmc_softc *sc = sf->sc;
     212           0 :         struct sdmmc_function *sf0 = sc->sc_fn0;
     213             :         u_int8_t rv;
     214             : 
     215           0 :         rw_assert_wrlock(&sc->sc_lock);
     216             : 
     217           0 :         if (sf->number == 0)
     218           0 :                 return 1;       /* FN0 is always ready */
     219             : 
     220           0 :         rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_READY);
     221             : 
     222           0 :         return (rv & (1 << sf->number)) != 0;
     223           0 : }
     224             : 
     225             : /*
     226             :  * Enable the I/O function.  Return zero if the function was
     227             :  * enabled successfully.
     228             :  */
     229             : int
     230           0 : sdmmc_io_function_enable(struct sdmmc_function *sf)
     231             : {
     232           0 :         struct sdmmc_softc *sc = sf->sc;
     233           0 :         struct sdmmc_function *sf0 = sc->sc_fn0;
     234             :         u_int8_t rv;
     235             :         int retry = 5;
     236             : 
     237           0 :         rw_assert_wrlock(&sc->sc_lock);
     238             : 
     239           0 :         if (sf->number == 0)
     240           0 :                 return 0;       /* FN0 is always enabled */
     241             : 
     242           0 :         rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
     243           0 :         rv |= (1<<sf->number);
     244           0 :         sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
     245             : 
     246           0 :         while (!sdmmc_io_function_ready(sf) && retry-- > 0)
     247           0 :                 tsleep(&lbolt, PPAUSE, "pause", 0);
     248           0 :         return (retry >= 0) ? 0 : ETIMEDOUT;
     249           0 : }
     250             : 
     251             : /*
     252             :  * Disable the I/O function.  Return zero if the function was
     253             :  * disabled successfully.
     254             :  */
     255             : void
     256           0 : sdmmc_io_function_disable(struct sdmmc_function *sf)
     257             : {
     258           0 :         struct sdmmc_softc *sc = sf->sc;
     259           0 :         struct sdmmc_function *sf0 = sc->sc_fn0;
     260             :         u_int8_t rv;
     261             : 
     262           0 :         rw_assert_wrlock(&sc->sc_lock);
     263             : 
     264           0 :         if (sf->number == 0)
     265           0 :                 return;         /* FN0 is always enabled */
     266             : 
     267           0 :         rv = sdmmc_io_read_1(sf0, SD_IO_CCCR_FN_ENABLE);
     268           0 :         rv &= ~(1<<sf->number);
     269           0 :         sdmmc_io_write_1(sf0, SD_IO_CCCR_FN_ENABLE, rv);
     270           0 : }
     271             : 
     272             : void
     273           0 : sdmmc_io_attach(struct sdmmc_softc *sc)
     274             : {
     275             :         struct sdmmc_function *sf;
     276           0 :         struct sdmmc_attach_args saa;
     277             : 
     278           0 :         rw_assert_wrlock(&sc->sc_lock);
     279             : 
     280           0 :         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
     281           0 :                 if (sf->number < 1)
     282             :                         continue;
     283             : 
     284           0 :                 bzero(&saa, sizeof saa);
     285           0 :                 saa.sf = sf;
     286             : 
     287           0 :                 sf->child = config_found_sm(&sc->sc_dev, &saa, sdmmc_print,
     288             :                     sdmmc_submatch);
     289           0 :         }
     290           0 : }
     291             : 
     292             : int
     293           0 : sdmmc_submatch(struct device *parent, void *match, void *aux)
     294             : {
     295           0 :         struct cfdata *cf = match;
     296             : 
     297             :         /* Skip the scsibus, it is configured directly. */
     298           0 :         if (strcmp(cf->cf_driver->cd_name, "scsibus") == 0)
     299           0 :                 return 0;
     300             : 
     301           0 :         return cf->cf_attach->ca_match(parent, cf, aux);
     302           0 : }
     303             : 
     304             : int
     305           0 : sdmmc_print(void *aux, const char *pnp)
     306             : {
     307           0 :         struct sdmmc_attach_args *sa = aux;
     308           0 :         struct sdmmc_function *sf = sa->sf;
     309           0 :         struct sdmmc_cis *cis = &sf->sc->sc_fn0->cis;
     310             :         int i;
     311             : 
     312           0 :         if (pnp) {
     313           0 :                 if (sf->number == 0)
     314           0 :                         return QUIET;
     315             : 
     316           0 :                 for (i = 0; i < 4 && cis->cis1_info[i]; i++)
     317           0 :                         printf("%s%s", i ? ", " : "\"", cis->cis1_info[i]);
     318           0 :                 if (i != 0)
     319           0 :                         printf("\"");
     320             : 
     321           0 :                 if (cis->manufacturer != SDMMC_VENDOR_INVALID ||
     322           0 :                     cis->product != SDMMC_PRODUCT_INVALID) {
     323           0 :                         printf("%s", i ? " " : "");
     324           0 :                         if (cis->manufacturer != SDMMC_VENDOR_INVALID)
     325           0 :                                 printf("manufacturer 0x%04x%s",
     326             :                                     cis->manufacturer,
     327           0 :                                     cis->product == SDMMC_PRODUCT_INVALID ?
     328             :                                     "" : ", ");
     329           0 :                         if (cis->product != SDMMC_PRODUCT_INVALID)
     330           0 :                                 printf("product 0x%04x", cis->product);
     331             :                 }
     332           0 :                 printf(" at %s", pnp);
     333           0 :         }
     334           0 :         printf(" function %d", sf->number);
     335             : 
     336           0 :         if (!pnp) {
     337           0 :                 for (i = 0; i < 3 && cis->cis1_info[i]; i++)
     338           0 :                         printf("%s%s", i ? ", " : " \"", cis->cis1_info[i]);
     339           0 :                 if (i != 0)
     340           0 :                         printf("\"");
     341             :         }
     342           0 :         return UNCONF;
     343           0 : }
     344             : 
     345             : void
     346           0 : sdmmc_io_detach(struct sdmmc_softc *sc)
     347             : {
     348             :         struct sdmmc_function *sf;
     349             : 
     350           0 :         rw_assert_wrlock(&sc->sc_lock);
     351             : 
     352           0 :         SIMPLEQ_FOREACH(sf, &sc->sf_head, sf_list) {
     353           0 :                 if (sf->child != NULL) {
     354           0 :                         config_detach(sf->child, DETACH_FORCE);
     355           0 :                         sf->child = NULL;
     356           0 :                 }
     357             :         }
     358             : 
     359           0 :         KASSERT(TAILQ_EMPTY(&sc->sc_intrq));
     360           0 : }
     361             : 
     362             : int
     363           0 : sdmmc_io_rw_direct(struct sdmmc_softc *sc, struct sdmmc_function *sf,
     364             :     int reg, u_char *datap, int arg)
     365             : {
     366           0 :         struct sdmmc_command cmd;
     367             :         int error;
     368             : 
     369           0 :         rw_assert_wrlock(&sc->sc_lock);
     370             : 
     371             :         /* Make sure the card is selected. */
     372           0 :         if ((error = sdmmc_select_card(sc, sf)) != 0) {
     373           0 :                 rw_exit(&sc->sc_lock);
     374           0 :                 return error;
     375             :         }
     376             : 
     377           0 :         arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD52_FUNC_MASK) <<
     378             :             SD_ARG_CMD52_FUNC_SHIFT;
     379           0 :         arg |= (reg & SD_ARG_CMD52_REG_MASK) <<
     380             :             SD_ARG_CMD52_REG_SHIFT;
     381           0 :         arg |= (*datap & SD_ARG_CMD52_DATA_MASK) <<
     382             :             SD_ARG_CMD52_DATA_SHIFT;
     383             : 
     384           0 :         bzero(&cmd, sizeof cmd);
     385           0 :         cmd.c_opcode = SD_IO_RW_DIRECT;
     386           0 :         cmd.c_arg = arg;
     387           0 :         cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
     388             : 
     389           0 :         error = sdmmc_mmc_command(sc, &cmd);
     390           0 :         *datap = SD_R5_DATA(cmd.c_resp);
     391             : 
     392           0 :         return error;
     393           0 : }
     394             : 
     395             : /*
     396             :  * Useful values of `arg' to pass in are either SD_ARG_CMD53_READ or
     397             :  * SD_ARG_CMD53_WRITE.  SD_ARG_CMD53_INCREMENT may be ORed into `arg'
     398             :  * to access successive register locations instead of accessing the
     399             :  * same register many times.  SD_ARG_CMD53_BLOCK_MODE may be ORed
     400             :  * into `arg' to indicate that the length is a number of blocks.
     401             :  */
     402             : int
     403           0 : sdmmc_io_rw_extended_subr(struct sdmmc_softc *sc, struct sdmmc_function *sf,
     404             :     bus_dmamap_t dmap, int reg, u_char *datap, int len, int arg)
     405             : {
     406           0 :         struct sdmmc_command cmd;
     407             :         int error;
     408             : 
     409           0 :         rw_assert_wrlock(&sc->sc_lock);
     410             : 
     411             : #if 0
     412             :         /* Make sure the card is selected. */
     413             :         if ((error = sdmmc_select_card(sc, sf)) != 0) {
     414             :                 rw_exit(&sc->sc_lock);
     415             :                 return error;
     416             :         }
     417             : #endif
     418             : 
     419           0 :         arg |= ((sf == NULL ? 0 : sf->number) & SD_ARG_CMD53_FUNC_MASK) <<
     420             :             SD_ARG_CMD53_FUNC_SHIFT;
     421           0 :         arg |= (reg & SD_ARG_CMD53_REG_MASK) <<
     422             :             SD_ARG_CMD53_REG_SHIFT;
     423           0 :         arg |= (len & SD_ARG_CMD53_LENGTH_MASK) <<
     424             :             SD_ARG_CMD53_LENGTH_SHIFT;
     425             : 
     426           0 :         bzero(&cmd, sizeof cmd);
     427           0 :         cmd.c_opcode = SD_IO_RW_EXTENDED;
     428           0 :         cmd.c_arg = arg;
     429           0 :         cmd.c_flags = SCF_CMD_AC | SCF_RSP_R5;
     430           0 :         cmd.c_dmamap = dmap;
     431           0 :         cmd.c_data = datap;
     432           0 :         if (ISSET(arg, SD_ARG_CMD53_BLOCK_MODE)) {
     433           0 :                 cmd.c_datalen = len * sf->cur_blklen;
     434           0 :                 cmd.c_blklen = sf->cur_blklen;
     435           0 :         } else {
     436           0 :                 cmd.c_datalen = len;
     437           0 :                 cmd.c_blklen = MIN(len, sf->cur_blklen);
     438             :         }
     439             : 
     440           0 :         if (!ISSET(arg, SD_ARG_CMD53_WRITE))
     441           0 :                 cmd.c_flags |= SCF_CMD_READ;
     442             : 
     443           0 :         error = sdmmc_mmc_command(sc, &cmd);
     444             : 
     445           0 :         return error;
     446           0 : }
     447             : 
     448             : int
     449           0 : sdmmc_io_rw_extended(struct sdmmc_softc *sc, struct sdmmc_function *sf,
     450             :     int reg, u_char *datap, int len, int arg)
     451             : {
     452             :         int datalen = len, error, read = 0;
     453             : 
     454           0 :         if (!ISSET(sc->sc_caps, SMC_CAPS_DMA))
     455           0 :                 return sdmmc_io_rw_extended_subr(sc, sf, NULL, reg,
     456             :                     datap, len, arg);
     457             : 
     458           0 :         if (ISSET(arg, SD_ARG_CMD53_BLOCK_MODE))
     459           0 :                 datalen = len * sf->cur_blklen;
     460             : 
     461           0 :         if (!ISSET(arg, SD_ARG_CMD53_WRITE))
     462           0 :                 read = 1;
     463             : 
     464           0 :         error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap, datap, datalen,
     465             :             NULL, BUS_DMA_NOWAIT | (read ? BUS_DMA_READ : BUS_DMA_WRITE));
     466           0 :         if (error)
     467             :                 goto out;
     468             : 
     469           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
     470             :             read ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
     471             : 
     472           0 :         error = sdmmc_io_rw_extended_subr(sc, sf, sc->sc_dmap, reg,
     473             :             datap, len, arg);
     474           0 :         if (error)
     475             :                 goto unload;
     476             : 
     477           0 :         bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap, 0, datalen,
     478             :             read ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
     479             : 
     480             : unload:
     481           0 :         bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap);
     482             : 
     483             : out:
     484           0 :         return error;
     485           0 : }
     486             : 
     487             : u_int8_t
     488           0 : sdmmc_io_read_1(struct sdmmc_function *sf, int reg)
     489             : {
     490           0 :         u_int8_t data = 0;
     491             : 
     492           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     493             :         
     494           0 :         (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
     495             :             SD_ARG_CMD52_READ);
     496           0 :         return data;
     497           0 : }
     498             : 
     499             : void
     500           0 : sdmmc_io_write_1(struct sdmmc_function *sf, int reg, u_int8_t data)
     501             : {
     502           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     503             : 
     504           0 :         (void)sdmmc_io_rw_direct(sf->sc, sf, reg, (u_char *)&data,
     505             :             SD_ARG_CMD52_WRITE);
     506           0 : }
     507             : 
     508             : u_int16_t
     509           0 : sdmmc_io_read_2(struct sdmmc_function *sf, int reg)
     510             : {
     511           0 :         u_int16_t data = 0;
     512             :         
     513           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     514             : 
     515           0 :         (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
     516             :             (u_char *)&data, 2, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
     517           0 :         return data;
     518           0 : }
     519             : 
     520             : void
     521           0 : sdmmc_io_write_2(struct sdmmc_function *sf, int reg, u_int16_t data)
     522             : {
     523           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     524             : 
     525           0 :         (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
     526           0 :             (u_char *)&data, 2, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
     527           0 : }
     528             : 
     529             : u_int32_t
     530           0 : sdmmc_io_read_4(struct sdmmc_function *sf, int reg)
     531             : {
     532           0 :         u_int32_t data = 0;
     533             :         
     534           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     535             : 
     536           0 :         (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
     537             :             (u_char *)&data, 4, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
     538           0 :         return data;
     539           0 : }
     540             : 
     541             : void
     542           0 : sdmmc_io_write_4(struct sdmmc_function *sf, int reg, u_int32_t data)
     543             : {
     544           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     545             : 
     546           0 :         (void)sdmmc_io_rw_extended_subr(sf->sc, sf, NULL, reg,
     547           0 :             (u_char *)&data, 4, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
     548           0 : }
     549             : 
     550             : int
     551           0 : sdmmc_io_read_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
     552             :     int datalen)
     553             : {
     554             :         int blocks, error = 0;
     555             : 
     556           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     557             : 
     558           0 :         while (datalen >= sf->cur_blklen) {
     559           0 :                 blocks = MIN(datalen / sf->cur_blklen,
     560             :                     SD_ARG_CMD53_LENGTH_MAX);
     561           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
     562             :                     blocks, SD_ARG_CMD53_READ | SD_ARG_CMD53_BLOCK_MODE);
     563           0 :                 if (error)
     564           0 :                         return error;
     565           0 :                 data += blocks * sf->cur_blklen;
     566           0 :                 datalen -= blocks * sf->cur_blklen;
     567             :         }
     568             : 
     569           0 :         if (datalen)
     570           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
     571             :                     SD_ARG_CMD53_READ);
     572             : 
     573           0 :         return error;
     574           0 : }
     575             : 
     576             : int
     577           0 : sdmmc_io_write_multi_1(struct sdmmc_function *sf, int reg, u_char *data,
     578             :     int datalen)
     579             : {
     580             :         int blocks, error = 0;
     581             : 
     582           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     583             : 
     584           0 :         while (datalen >= sf->cur_blklen) {
     585           0 :                 blocks = MIN(datalen / sf->cur_blklen,
     586             :                     SD_ARG_CMD53_LENGTH_MAX);
     587           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
     588             :                     blocks, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_BLOCK_MODE);
     589           0 :                 if (error)
     590           0 :                         return error;
     591           0 :                 data += blocks * sf->cur_blklen;
     592           0 :                 datalen -= blocks * sf->cur_blklen;
     593             :         }
     594             : 
     595           0 :         if (datalen)
     596           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
     597             :                     SD_ARG_CMD53_WRITE);
     598             : 
     599           0 :         return error;
     600           0 : }
     601             : 
     602             : int
     603           0 : sdmmc_io_read_region_1(struct sdmmc_function *sf, int reg, u_char *data,
     604             :     int datalen)
     605             : {
     606             :         int blocks, error = 0;
     607             : 
     608           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     609             : 
     610           0 :         while (datalen >= sf->cur_blklen) {
     611           0 :                 blocks = MIN(datalen / sf->cur_blklen,
     612             :                     SD_ARG_CMD53_LENGTH_MAX);
     613           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
     614             :                     blocks, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT |
     615             :                     SD_ARG_CMD53_BLOCK_MODE);
     616           0 :                 if (error)
     617           0 :                         return error;
     618           0 :                 reg += blocks * sf->cur_blklen;
     619           0 :                 data += blocks * sf->cur_blklen;
     620           0 :                 datalen -= blocks * sf->cur_blklen;
     621             :         }
     622             : 
     623           0 :         if (datalen)
     624           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
     625             :                     SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT);
     626             : 
     627           0 :         return error;
     628           0 : }
     629             : 
     630             : int
     631           0 : sdmmc_io_write_region_1(struct sdmmc_function *sf, int reg, u_char *data,
     632             :     int datalen)
     633             : {
     634             :         int blocks, error = 0;
     635             : 
     636           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     637             : 
     638           0 :         while (datalen >= sf->cur_blklen) {
     639           0 :                 blocks = MIN(datalen / sf->cur_blklen,
     640             :                     SD_ARG_CMD53_LENGTH_MAX);
     641           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data,
     642             :                     blocks, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT |
     643             :                     SD_ARG_CMD53_BLOCK_MODE);
     644           0 :                 if (error)
     645           0 :                         return error;
     646           0 :                 reg += blocks * sf->cur_blklen;
     647           0 :                 data += blocks * sf->cur_blklen;
     648           0 :                 datalen -= blocks * sf->cur_blklen;
     649             :         }
     650             : 
     651           0 :         if (datalen)
     652           0 :                 error = sdmmc_io_rw_extended(sf->sc, sf, reg, data, datalen,
     653             :                     SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT);
     654             : 
     655           0 :         return error;
     656           0 : }
     657             : 
     658             : int
     659           0 : sdmmc_io_xchg(struct sdmmc_softc *sc, struct sdmmc_function *sf,
     660             :     int reg, u_char *datap)
     661             : {
     662             : 
     663           0 :         rw_assert_wrlock(&sc->sc_lock);
     664             : 
     665           0 :         return sdmmc_io_rw_direct(sc, sf, reg, datap,
     666             :             SD_ARG_CMD52_WRITE|SD_ARG_CMD52_EXCHANGE);
     667             : }
     668             : 
     669             : /*
     670             :  * Reset the I/O functions of the card.
     671             :  */
     672             : void
     673           0 : sdmmc_io_reset(struct sdmmc_softc *sc)
     674             : {
     675           0 :         u_int8_t data = CCCR_CTL_RES;
     676             : 
     677           0 :         rw_assert_wrlock(&sc->sc_lock);
     678             : 
     679           0 :         if (sdmmc_io_rw_direct(sc, NULL, SD_IO_CCCR_CTL, (u_char *)&data,
     680           0 :             SD_ARG_CMD52_WRITE) == 0)
     681           0 :                 sdmmc_delay(100000);
     682           0 : }
     683             : 
     684             : /*
     685             :  * Get or set the card's I/O OCR value (SDIO).
     686             :  */
     687             : int
     688           0 : sdmmc_io_send_op_cond(struct sdmmc_softc *sc, u_int32_t ocr, u_int32_t *ocrp)
     689             : {
     690           0 :         struct sdmmc_command cmd;
     691             :         int error;
     692             :         int i;
     693             : 
     694           0 :         rw_assert_wrlock(&sc->sc_lock);
     695             : 
     696             :         /*
     697             :          * If we change the OCR value, retry the command until the OCR
     698             :          * we receive in response has the "CARD BUSY" bit set, meaning
     699             :          * that all cards are ready for identification.
     700             :          */
     701           0 :         for (i = 0; i < 100; i++) {
     702           0 :                 bzero(&cmd, sizeof cmd);
     703           0 :                 cmd.c_opcode = SD_IO_SEND_OP_COND;
     704           0 :                 cmd.c_arg = ocr;
     705           0 :                 cmd.c_flags = SCF_CMD_BCR | SCF_RSP_R4;
     706             : 
     707           0 :                 error = sdmmc_mmc_command(sc, &cmd);
     708           0 :                 if (error != 0)
     709             :                         break;
     710           0 :                 if (ISSET(MMC_R4(cmd.c_resp), SD_IO_OCR_MEM_READY) ||
     711           0 :                     ocr == 0)
     712             :                         break;
     713             :                 error = ETIMEDOUT;
     714           0 :                 sdmmc_delay(10000);
     715             :         }
     716           0 :         if (error == 0 && ocrp != NULL)
     717           0 :                 *ocrp = MMC_R4(cmd.c_resp);
     718             : 
     719           0 :         return error;
     720           0 : }
     721             : 
     722             : /*
     723             :  * Card interrupt handling
     724             :  */
     725             : 
     726             : void
     727           0 : sdmmc_intr_enable(struct sdmmc_function *sf)
     728             : {
     729           0 :         struct sdmmc_softc *sc = sf->sc;
     730           0 :         struct sdmmc_function *sf0 = sc->sc_fn0;
     731             :         u_int8_t imask;
     732             : 
     733           0 :         rw_assert_wrlock(&sc->sc_lock);
     734             : 
     735           0 :         imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
     736           0 :         imask |= 1 << sf->number;
     737           0 :         sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
     738           0 : }
     739             : 
     740             : void
     741           0 : sdmmc_intr_disable(struct sdmmc_function *sf)
     742             : {
     743           0 :         struct sdmmc_softc *sc = sf->sc;
     744           0 :         struct sdmmc_function *sf0 = sc->sc_fn0;
     745             :         u_int8_t imask;
     746             : 
     747           0 :         rw_assert_wrlock(&sc->sc_lock);
     748             : 
     749           0 :         imask = sdmmc_io_read_1(sf0, SD_IO_CCCR_INT_ENABLE);
     750           0 :         imask &= ~(1 << sf->number);
     751           0 :         sdmmc_io_write_1(sf0, SD_IO_CCCR_INT_ENABLE, imask);
     752           0 : }
     753             : 
     754             : /*
     755             :  * Establish a handler for the SDIO card interrupt.  Because the
     756             :  * interrupt may be shared with different SDIO functions, multiple
     757             :  * handlers can be established.
     758             :  */
     759             : void *
     760           0 : sdmmc_intr_establish(struct device *sdmmc, int (*fun)(void *),
     761             :     void *arg, const char *name)
     762             : {
     763           0 :         struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
     764             :         struct sdmmc_intr_handler *ih;
     765             :         int s;
     766             : 
     767           0 :         if (sc->sct->card_intr_mask == NULL)
     768           0 :                 return NULL;
     769             : 
     770           0 :         ih = malloc(sizeof *ih, M_DEVBUF, M_WAITOK | M_CANFAIL | M_ZERO);
     771           0 :         if (ih == NULL)
     772           0 :                 return NULL;
     773             : 
     774           0 :         ih->ih_name = name;
     775           0 :         ih->ih_softc = sc;
     776           0 :         ih->ih_fun = fun;
     777           0 :         ih->ih_arg = arg;
     778             : 
     779           0 :         s = splhigh();
     780           0 :         if (TAILQ_EMPTY(&sc->sc_intrq)) {
     781           0 :                 sdmmc_intr_enable(sc->sc_fn0);
     782           0 :                 sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 1);
     783           0 :         }
     784           0 :         TAILQ_INSERT_TAIL(&sc->sc_intrq, ih, entry);
     785           0 :         splx(s);
     786           0 :         return ih;
     787           0 : }
     788             : 
     789             : /*
     790             :  * Disestablish the given handler.
     791             :  */
     792             : void
     793           0 : sdmmc_intr_disestablish(void *cookie)
     794             : {
     795           0 :         struct sdmmc_intr_handler *ih = cookie;
     796           0 :         struct sdmmc_softc *sc = ih->ih_softc;
     797             :         int s;
     798             : 
     799           0 :         if (sc->sct->card_intr_mask == NULL)
     800           0 :                 return;
     801             : 
     802           0 :         s = splhigh();
     803           0 :         TAILQ_REMOVE(&sc->sc_intrq, ih, entry);
     804           0 :         if (TAILQ_EMPTY(&sc->sc_intrq)) {
     805           0 :                 sdmmc_chip_card_intr_mask(sc->sct, sc->sch, 0);
     806           0 :                 sdmmc_intr_disable(sc->sc_fn0);
     807           0 :         }
     808           0 :         splx(s);
     809             : 
     810           0 :         free(ih, M_DEVBUF, sizeof *ih);
     811           0 : }
     812             : 
     813             : /*
     814             :  * Call established SDIO card interrupt handlers.  The host controller
     815             :  * must call this function from its own interrupt handler to handle an
     816             :  * SDIO interrupt from the card.
     817             :  */
     818             : void
     819           0 : sdmmc_card_intr(struct device *sdmmc)
     820             : {
     821           0 :         struct sdmmc_softc *sc = (struct sdmmc_softc *)sdmmc;
     822             : 
     823           0 :         if (sc->sct->card_intr_mask == NULL)
     824           0 :                 return;
     825             : 
     826           0 :         if (!sdmmc_task_pending(&sc->sc_intr_task))
     827           0 :                 sdmmc_add_task(sc, &sc->sc_intr_task);
     828           0 : }
     829             : 
     830             : void
     831           0 : sdmmc_intr_task(void *arg)
     832             : {
     833           0 :         struct sdmmc_softc *sc = arg;
     834             :         struct sdmmc_intr_handler *ih;
     835             :         int s;
     836             : 
     837           0 :         s = splhigh();
     838           0 :         TAILQ_FOREACH(ih, &sc->sc_intrq, entry) {
     839           0 :                 splx(s);
     840             : 
     841             :                 /* XXX examine return value and do evcount stuff*/
     842           0 :                 (void)ih->ih_fun(ih->ih_arg);
     843             : 
     844           0 :                 s = splhigh();
     845             :         }
     846           0 :         sdmmc_chip_card_intr_ack(sc->sct, sc->sch);
     847           0 :         splx(s);
     848           0 : }
     849             : 
     850             : void
     851           0 : sdmmc_io_set_blocklen(struct sdmmc_function *sf, unsigned int blklen)
     852             : {
     853           0 :         struct sdmmc_softc *sc = sf->sc;
     854           0 :         struct sdmmc_function *sf0 = sc->sc_fn0;
     855             : 
     856           0 :         rw_assert_wrlock(&sc->sc_lock);
     857             : 
     858           0 :         if (blklen > sdmmc_chip_host_maxblklen(sc->sct, sc->sch))
     859           0 :                 return;
     860             : 
     861           0 :         if (blklen == 0) {
     862           0 :                 blklen = min(512, sdmmc_chip_host_maxblklen(sc->sct, sc->sch));
     863           0 :         }
     864             : 
     865           0 :         sdmmc_io_write_1(sf0, SD_IO_FBR_BASE(sf->number) +
     866           0 :             SD_IO_FBR_BLOCKLEN, blklen & 0xff);
     867           0 :         sdmmc_io_write_1(sf0, SD_IO_FBR_BASE(sf->number) +
     868           0 :             SD_IO_FBR_BLOCKLEN+ 1, (blklen >> 8) & 0xff);
     869           0 :         sf->cur_blklen = blklen;
     870           0 : }
     871             : 
     872             : void
     873           0 : sdmmc_io_set_bus_width(struct sdmmc_function *sf, int width)
     874             : {
     875             :         u_int8_t rv;
     876             : 
     877           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     878           0 :         rv = sdmmc_io_read_1(sf, SD_IO_CCCR_BUS_WIDTH);
     879           0 :         rv &= ~CCCR_BUS_WIDTH_MASK;
     880           0 :         if (width == 4)
     881           0 :                 rv |= CCCR_BUS_WIDTH_4;
     882             :         else
     883             :                 rv |= CCCR_BUS_WIDTH_1;
     884           0 :         sdmmc_io_write_1(sf, SD_IO_CCCR_BUS_WIDTH, rv);
     885           0 : }
     886             : 
     887             : int
     888           0 : sdmmc_io_set_highspeed(struct sdmmc_function *sf, int enable)
     889             : {
     890             :         u_int8_t rv;
     891             : 
     892           0 :         rw_assert_wrlock(&sf->sc->sc_lock);
     893             : 
     894           0 :         rv = sdmmc_io_read_1(sf, SD_IO_CCCR_SPEED);
     895           0 :         if (enable && !(rv & CCCR_SPEED_SHS))
     896           0 :                 return 1;
     897           0 :         rv &= ~CCCR_SPEED_MASK;
     898           0 :         if (enable)
     899           0 :                 rv |= CCCR_SPEED_EHS;
     900           0 :         sdmmc_io_write_1(sf, SD_IO_CCCR_SPEED, rv);
     901           0 :         return 0;
     902           0 : }

Generated by: LCOV version 1.13