[BACK]Return to omap3_sdhc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / arm / omap

Annotation of src/sys/arch/arm/omap/omap3_sdhc.c, Revision 1.22

1.22    ! kiyohara    1: /*     $NetBSD: omap3_sdhc.c,v 1.21 2016/07/04 15:45:37 kiyohara Exp $ */
1.1       matt        2: /*-
                      3:  * Copyright (c) 2011 The NetBSD Foundation, Inc.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to The NetBSD Foundation
                      7:  * by Matt Thomas of 3am Software Foundry.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     19:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     20:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     21:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     22:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     23:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     24:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     25:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     26:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     27:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     28:  * POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30:
                     31: #include <sys/cdefs.h>
1.22    ! kiyohara   32: __KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.21 2016/07/04 15:45:37 kiyohara Exp $");
1.1       matt       33:
                     34: #include "opt_omap.h"
1.16      bouyer     35: #include "edma.h"
1.1       matt       36:
                     37: #include <sys/param.h>
                     38: #include <sys/systm.h>
                     39: #include <sys/device.h>
                     40: #include <sys/kernel.h>
                     41: #include <sys/proc.h>
                     42: #include <sys/queue.h>
1.16      bouyer     43: #include <sys/mutex.h>
                     44: #include <sys/condvar.h>
1.1       matt       45: #include <sys/bus.h>
                     46:
                     47: #include <arm/omap/omap2_obiovar.h>
1.5       matt       48: #include <arm/omap/omap2_reg.h>
1.1       matt       49: #include <arm/omap/omap3_sdmmcreg.h>
                     50:
1.4       riastrad   51: #ifdef TI_AM335X
                     52: #  include <arm/omap/am335x_prcm.h>
                     53: #  include <arm/omap/omap2_prcm.h>
1.19      jmcneill   54: #  include <arm/omap/sitara_cm.h>
                     55: #  include <arm/omap/sitara_cmreg.h>
1.4       riastrad   56: #endif
                     57:
1.16      bouyer     58: #if NEDMA > 0
                     59: #  include <arm/omap/omap_edma.h>
                     60: #endif
                     61:
1.1       matt       62: #include <dev/sdmmc/sdhcreg.h>
                     63: #include <dev/sdmmc/sdhcvar.h>
1.16      bouyer     64: #include <dev/sdmmc/sdmmcvar.h>
                     65:
                     66: #ifdef TI_AM335X
                     67: #define EDMA_MAX_PARAMS                32
                     68: #endif
                     69:
                     70: #ifdef OM3SDHC_DEBUG
                     71: int om3sdhcdebug = 1;
                     72: #define DPRINTF(n,s)    do { if ((n) <= om3sdhcdebug) device_printf s; } while (0)
                     73: #else
                     74: #define DPRINTF(n,s)    do {} while (0)
                     75: #endif
                     76:
1.1       matt       77:
1.2       kiyohara   78: #define CLKD(kz)       (sc->sc.sc_clkbase / (kz))
                     79:
                     80: #define SDHC_READ(sc, reg) \
                     81:        bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg))
                     82: #define SDHC_WRITE(sc, reg, val) \
                     83:        bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val))
                     84:
1.1       matt       85: static int obiosdhc_match(device_t, cfdata_t, void *);
                     86: static void obiosdhc_attach(device_t, device_t, void *);
1.2       kiyohara   87: static int obiosdhc_detach(device_t, int);
                     88:
1.19      jmcneill   89: static int obiosdhc_bus_width(struct sdhc_softc *, int);
1.2       kiyohara   90: static int obiosdhc_rod(struct sdhc_softc *, int);
                     91: static int obiosdhc_write_protect(struct sdhc_softc *);
                     92: static int obiosdhc_card_detect(struct sdhc_softc *);
1.1       matt       93:
                     94: struct obiosdhc_softc {
                     95:        struct sdhc_softc       sc;
                     96:        bus_space_tag_t         sc_bst;
                     97:        bus_space_handle_t      sc_bsh;
1.22    ! kiyohara   98:        bus_space_handle_t      sc_hl_bsh;
1.1       matt       99:        bus_space_handle_t      sc_sdhc_bsh;
                    100:        struct sdhc_host        *sc_hosts[1];
                    101:        void                    *sc_ih;         /* interrupt vectoring */
1.16      bouyer    102:
                    103: #if NEDMA > 0
                    104:        struct edma_channel     *sc_edma_tx;
                    105:        struct edma_channel     *sc_edma_rx;
                    106:        uint16_t                sc_edma_param_tx[EDMA_MAX_PARAMS];
                    107:        uint16_t                sc_edma_param_rx[EDMA_MAX_PARAMS];
                    108:        kcondvar_t              sc_edma_cv;
                    109:        bus_addr_t              sc_edma_fifo;
                    110:        bool                    sc_edma_pending;
1.18      jmcneill  111:        bus_dmamap_t            sc_edma_dmamap;
                    112:        bus_dma_segment_t       sc_edma_segs[1];
                    113:        void                    *sc_edma_bbuf;
1.16      bouyer    114: #endif
1.1       matt      115: };
                    116:
1.16      bouyer    117: #if NEDMA > 0
1.18      jmcneill  118: static int obiosdhc_edma_init(struct obiosdhc_softc *, unsigned int);
1.16      bouyer    119: static int obiosdhc_edma_xfer_data(struct sdhc_softc *, struct sdmmc_command *);
                    120: static void obiosdhc_edma_done(void *);
1.18      jmcneill  121: static int obiosdhc_edma_transfer(struct sdhc_softc *, struct sdmmc_command *);
1.16      bouyer    122: #endif
                    123:
1.4       riastrad  124: #ifdef TI_AM335X
                    125: struct am335x_sdhc {
                    126:        const char *as_name;
                    127:        bus_addr_t as_base_addr;
                    128:        int as_intr;
                    129:        struct omap_module as_module;
                    130: };
                    131:
                    132: static const struct am335x_sdhc am335x_sdhc[] = {
                    133:        /* XXX All offset by 0x100 because of the am335x's mmc registers.  */
1.12      matt      134:        { "MMCHS0", SDMMC1_BASE_TIAM335X, 64, { AM335X_PRCM_CM_PER, 0x3c } },
                    135:        { "MMC1",   SDMMC2_BASE_TIAM335X, 28, { AM335X_PRCM_CM_PER, 0xf4 } },
                    136:        { "MMCHS2", SDMMC3_BASE_TIAM335X, 29, { AM335X_PRCM_CM_WKUP, 0xf8 } },
1.4       riastrad  137: };
1.19      jmcneill  138:
                    139: struct am335x_padconf {
                    140:        const char *padname;
                    141:        const char *padmode;
                    142: };
                    143: const struct am335x_padconf am335x_padconf_mmc1[] = {
                    144:        { "GPMC_CSn1", "mmc1_clk" },
                    145:        { "GPMC_CSn2", "mmc1_cmd" },
                    146:        { "GPMC_AD0", "mmc1_dat0" },
                    147:        { "GPMC_AD1", "mmc1_dat1" },
                    148:        { "GPMC_AD2", "mmc1_dat2" },
                    149:        { "GPMC_AD3", "mmc1_dat3" },
                    150:        { "GPMC_AD4", "mmc1_dat4" },
                    151:        { "GPMC_AD5", "mmc1_dat5" },
                    152:        { "GPMC_AD6", "mmc1_dat6" },
                    153:        { "GPMC_AD7", "mmc1_dat7" },
                    154:        { NULL, NULL }
                    155: };
1.4       riastrad  156: #endif
                    157:
1.1       matt      158: CFATTACH_DECL_NEW(obiosdhc, sizeof(struct obiosdhc_softc),
1.2       kiyohara  159:     obiosdhc_match, obiosdhc_attach, obiosdhc_detach, NULL);
1.1       matt      160:
                    161: static int
                    162: obiosdhc_match(device_t parent, cfdata_t cf, void *aux)
                    163: {
1.11      matt      164: #if defined(OMAP_3430) || defined(OMAP_3530) || defined(OMAP4)
1.1       matt      165:        struct obio_attach_args * const oa = aux;
                    166: #endif
1.4       riastrad  167: #ifdef TI_AM335X
                    168:        struct obio_attach_args * const oa = aux;
                    169:        size_t i;
                    170: #endif
1.1       matt      171:
1.3       khorben   172: #if defined(OMAP_3430)
                    173:        if (oa->obio_addr == SDMMC1_BASE_3430
                    174:            || oa->obio_addr == SDMMC2_BASE_3430
                    175:            || oa->obio_addr == SDMMC3_BASE_3430)
1.22    ! kiyohara  176:                return 1;
1.3       khorben   177: #elif defined(OMAP_3530)
1.1       matt      178:        if (oa->obio_addr == SDMMC1_BASE_3530
                    179:            || oa->obio_addr == SDMMC2_BASE_3530
                    180:            || oa->obio_addr == SDMMC3_BASE_3530)
1.22    ! kiyohara  181:                return 1;
1.14      matt      182: #elif defined(OMAP4) || defined(OMAP5)
1.11      matt      183:        if (oa->obio_addr == SDMMC1_BASE_4430
                    184:            || oa->obio_addr == SDMMC2_BASE_4430
                    185:            || oa->obio_addr == SDMMC3_BASE_4430
                    186:            || oa->obio_addr == SDMMC4_BASE_4430
                    187:            || oa->obio_addr == SDMMC5_BASE_4430)
1.22    ! kiyohara  188:                return 1;
1.1       matt      189: #endif
                    190:
1.4       riastrad  191: #ifdef TI_AM335X
                    192:        for (i = 0; i < __arraycount(am335x_sdhc); i++)
                    193:                if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) &&
                    194:                    (oa->obio_intr == am335x_sdhc[i].as_intr))
                    195:                        return 1;
                    196: #endif
                    197:
1.22    ! kiyohara  198:        return 0;
1.1       matt      199: }
                    200:
                    201: static void
                    202: obiosdhc_attach(device_t parent, device_t self, void *aux)
                    203: {
                    204:        struct obiosdhc_softc * const sc = device_private(self);
                    205:        struct obio_attach_args * const oa = aux;
1.5       matt      206:        prop_dictionary_t prop = device_properties(self);
1.2       kiyohara  207:        uint32_t clkd, stat;
                    208:        int error, timo, clksft, n;
1.10      jmcneill  209:        bool support8bit = false;
1.16      bouyer    210:        const char *transfer_mode = "PIO";
1.22    ! kiyohara  211: #if defined(OMAP4)
        !           212:        uint32_t v;
        !           213:        int x, y;
        !           214: #endif
1.4       riastrad  215: #ifdef TI_AM335X
                    216:        size_t i;
                    217: #endif
1.1       matt      218:
1.10      jmcneill  219:        prop_dictionary_get_bool(prop, "8bit", &support8bit);
                    220:
1.1       matt      221:        sc->sc.sc_dmat = oa->obio_dmat;
                    222:        sc->sc.sc_dev = self;
                    223:        sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS;
                    224:        sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
1.2       kiyohara  225:        sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
1.10      jmcneill  226:        if (support8bit)
                    227:                sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE;
1.22    ! kiyohara  228: #if defined(OMAP_3430)
        !           229:        sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
        !           230: #elif defined(OMAP_3530) || defined(TI_DM37XX)
        !           231:        /*
        !           232:         * Advisory 2.1.1.128: MMC: Multiple Block Read Operation Issue
        !           233:         * from "OMAP3530/25/15/03 Applications Processor Silicon Revisions
        !           234:         * 3.1.2, 3.1, 3.0, 2.1, and 2.0".
        !           235:         */
        !           236:        switch (omap_devid()) {
        !           237:        case DEVID_OMAP35X_ES10:
        !           238:        case DEVID_OMAP35X_ES20:
        !           239:        case DEVID_OMAP35X_ES21:
        !           240:        case DEVID_AMDM37X_ES10:        /* XXXX ? */
        !           241:        case DEVID_AMDM37X_ES11:        /* XXXX ? */
        !           242:        case DEVID_AMDM37X_ES12:        /* XXXX ? */
        !           243:                sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
        !           244:                break;
        !           245:        default:
        !           246:                break;
        !           247:        }
        !           248:        sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT;
        !           249: #elif defined(TI_AM335X)
1.6       riastrad  250:        sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET;
1.22    ! kiyohara  251: #elif defined(OMAP_4430)
        !           252:        /*
        !           253:         * MMCHS_HCTL.HSPE Is Not Functional
        !           254:         * Errata ID: i626
        !           255:         *
        !           256:         * Due to design issue MMCHS_HCTL.HSPE bit does not work as intended.
        !           257:         * This means that the configuration must always be the normal speed
        !           258:         * mode configuration (MMCHS_HCTL.HSPE=0).
        !           259:         */
        !           260:        sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT;
        !           261:
        !           262: //     sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
        !           263: //     sc->sc.sc_flags |= SDHC_FLAG_USE_ADMA2;
1.8       jmcneill  264: #endif
1.1       matt      265:        sc->sc.sc_host = sc->sc_hosts;
                    266:        sc->sc.sc_clkbase = 96000;      /* 96MHZ */
1.5       matt      267:        if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk))
                    268:                sc->sc.sc_clkmsk = 0x0000ffc0;
1.2       kiyohara  269:        sc->sc.sc_vendor_rod = obiosdhc_rod;
                    270:        sc->sc.sc_vendor_write_protect = obiosdhc_write_protect;
                    271:        sc->sc.sc_vendor_card_detect = obiosdhc_card_detect;
1.19      jmcneill  272:        sc->sc.sc_vendor_bus_width = obiosdhc_bus_width;
1.1       matt      273:        sc->sc_bst = oa->obio_iot;
                    274:
1.2       kiyohara  275:        clksft = ffs(sc->sc.sc_clkmsk) - 1;
                    276:
1.21      kiyohara  277: #if defined(TI_AM335X)
                    278:        error = bus_space_map(sc->sc_bst, oa->obio_addr + OMAP4_SDMMC_HL_SIZE,
                    279:            oa->obio_size - OMAP4_SDMMC_HL_SIZE, 0, &sc->sc_bsh);
1.22    ! kiyohara  280: #elif defined(OMAP4)
        !           281:        error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0,
        !           282:            &sc->sc_hl_bsh);
        !           283:        if (!error)
        !           284:                bus_space_subregion(sc->sc_bst, sc->sc_hl_bsh,
        !           285:                    OMAP4_SDMMC_HL_SIZE, oa->obio_size - OMAP4_SDMMC_HL_SIZE,
        !           286:                    &sc->sc_bsh);
1.21      kiyohara  287: #else
1.1       matt      288:        error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0,
                    289:            &sc->sc_bsh);
1.21      kiyohara  290: #endif
1.1       matt      291:        if (error) {
                    292:                aprint_error_dev(self,
                    293:                    "can't map registers: %d\n", error);
                    294:                return;
                    295:        }
                    296:
                    297:        bus_space_subregion(sc->sc_bst, sc->sc_bsh, OMAP3_SDMMC_SDHC_OFFSET,
                    298:            OMAP3_SDMMC_SDHC_SIZE, &sc->sc_sdhc_bsh);
                    299:
1.16      bouyer    300: #if NEDMA > 0
                    301:        if (oa->obio_edmabase != -1) {
1.18      jmcneill  302:                if (obiosdhc_edma_init(sc, oa->obio_edmabase) != 0)
                    303:                        goto no_dma;
                    304:
1.16      bouyer    305:                cv_init(&sc->sc_edma_cv, "sdhcedma");
                    306:                sc->sc_edma_fifo = oa->obio_addr +
1.22    ! kiyohara  307: #ifdef TI_AM335X
        !           308:                    OMAP4_SDMMC_HL_SIZE +
        !           309: #endif
        !           310:                    OMAP3_SDMMC_SDHC_OFFSET + SDHC_DATA;
1.16      bouyer    311:                sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
                    312:                sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA;
                    313:                sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN;
                    314:                sc->sc.sc_vendor_transfer_data_dma = obiosdhc_edma_xfer_data;
                    315:                transfer_mode = "EDMA";
                    316:        }
1.18      jmcneill  317: no_dma:
1.16      bouyer    318: #endif
1.22    ! kiyohara  319:        if (sc->sc.sc_flags & SDHC_FLAG_USE_ADMA2)
        !           320:                transfer_mode = "ADMA2";
1.16      bouyer    321:
                    322:        aprint_naive("\n");
                    323:        aprint_normal(": SDHC controller (%s)\n", transfer_mode);
1.1       matt      324:
1.22    ! kiyohara  325: #if defined(OMAP4)
        !           326:        v = bus_space_read_4(sc->sc_bst, sc->sc_hl_bsh, MMCHS_HL_REV);
        !           327:        aprint_normal_dev(sc->sc.sc_dev, "IP Rev 0x%08x", v);
        !           328:        v = bus_space_read_4(sc->sc_bst, sc->sc_hl_bsh, MMCHS_HL_HWINFO);
        !           329:        aprint_normal("%s", v & HL_HWINFO_RETMODE ? ", Retention Mode" : "");
        !           330:        x = 0;
        !           331:        switch (v & HL_HWINFO_MEM_SIZE_MASK) {
        !           332:        case HL_HWINFO_MEM_SIZE_512:    x = 512;        y = 512;        break;
        !           333:        case HL_HWINFO_MEM_SIZE_1024:   x = 1024;       y = 1024;       break;
        !           334:        case HL_HWINFO_MEM_SIZE_2048:   x = 2048;       y = 2048;       break;
        !           335:        case HL_HWINFO_MEM_SIZE_4096:   x = 4096;       y = 2048;       break;
        !           336:        }
        !           337:        if (x != 0)
        !           338:                aprint_normal(", %d byte FIFO, max block length %d bytes",
        !           339:                    x, y);
        !           340:        aprint_normal("\n");
        !           341: #endif
        !           342:
        !           343: #if NEDMA > 0
        !           344:        if (strcmp(transfer_mode, "EDMA") == 0)
        !           345:                aprint_normal_dev(sc->sc.sc_dev,
        !           346:                    "EDMA tx channel %d, rx channel %d\n",
        !           347:                    edma_channel_index(sc->sc_edma_tx),
        !           348:                    edma_channel_index(sc->sc_edma_rx));
        !           349: #endif
        !           350:
1.4       riastrad  351: #ifdef TI_AM335X
                    352:        /* XXX Not really AM335X-specific.  */
                    353:        for (i = 0; i < __arraycount(am335x_sdhc); i++)
                    354:                if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) &&
                    355:                    (oa->obio_intr == am335x_sdhc[i].as_intr)) {
                    356:                        prcm_module_enable(&am335x_sdhc[i].as_module);
                    357:                        break;
                    358:                }
                    359:        KASSERT(i < __arraycount(am335x_sdhc));
1.19      jmcneill  360:
                    361:        if (oa->obio_addr == SDMMC2_BASE_TIAM335X) {
                    362:                const char *mode;
                    363:                u_int state;
1.22    ! kiyohara  364:
1.19      jmcneill  365:                const struct am335x_padconf *padconf = am335x_padconf_mmc1;
                    366:                for (i = 0; padconf[i].padname; i++) {
                    367:                        const char *padname = padconf[i].padname;
                    368:                        const char *padmode = padconf[i].padmode;
                    369:                        if (sitara_cm_padconf_get(padname, &mode, &state) == 0) {
                    370:                                aprint_debug_dev(self, "%s mode %s state %d\n",
                    371:                                    padname, mode, state);
                    372:                        }
                    373:                        if (sitara_cm_padconf_set(padname, padmode,
                    374:                            (1 << 4) | (1 << 5)) != 0) {
                    375:                                aprint_error_dev(self, "can't switch %s pad from %s to %s\n",
                    376:                                    padname, mode, padmode);
                    377:                                return;
                    378:                        }
                    379:                }
                    380:        }
1.4       riastrad  381: #endif
                    382:
1.15      jakllsch  383:        /* XXXXXX: Turn-on regulator via I2C. */
1.2       kiyohara  384:        /* XXXXXX: And enable ICLOCK/FCLOCK. */
                    385:
                    386:        /* MMCHS Soft reset */
                    387:        bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
                    388:            SYSCONFIG_SOFTRESET);
                    389:        timo = 3000000; /* XXXX 3 sec. */
                    390:        while (timo--) {
                    391:                if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) &
                    392:                    SYSSTATUS_RESETDONE)
                    393:                        break;
                    394:                delay(1);
                    395:        }
                    396:        if (timo == 0)
                    397:                aprint_error_dev(self, "Soft reset timeout\n");
                    398:        bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
1.5       matt      399:            SYSCONFIG_ENAWAKEUP | SYSCONFIG_AUTOIDLE | SYSCONFIG_SIDLEMODE_AUTO |
                    400:            SYSCONFIG_CLOCKACTIVITY_FCLK | SYSCONFIG_CLOCKACTIVITY_ICLK);
1.2       kiyohara  401:
                    402:        sc->sc_ih = intr_establish(oa->obio_intr, IPL_VM, IST_LEVEL,
1.1       matt      403:            sdhc_intr, &sc->sc);
                    404:        if (sc->sc_ih == NULL) {
                    405:                aprint_error_dev(self, "failed to establish interrupt %d\n",
                    406:                     oa->obio_intr);
                    407:                goto fail;
                    408:        }
                    409:
                    410:        error = sdhc_host_found(&sc->sc, sc->sc_bst, sc->sc_sdhc_bsh,
                    411:            oa->obio_size - OMAP3_SDMMC_SDHC_OFFSET);
                    412:        if (error != 0) {
                    413:                aprint_error_dev(self, "couldn't initialize host, error=%d\n",
                    414:                    error);
                    415:                goto fail;
                    416:        }
1.2       kiyohara  417:
                    418:        /* Set SDVS 1.8v and DTW 1bit mode */
                    419:        SDHC_WRITE(sc, SDHC_HOST_CTL,
                    420:            SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8));
                    421:        bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
                    422:            bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_OD);
                    423:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    424:            SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE |
                    425:                                                        SDHC_SDCLK_ENABLE);
                    426:        SDHC_WRITE(sc, SDHC_HOST_CTL,
                    427:            SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8);
                    428:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    429:            SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
                    430:
                    431:        /*
                    432:         * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start
                    433:         * from 'OMAP35x Applications Processor  Technical Reference Manual'.
                    434:         *
                    435:         * During the INIT procedure, the MMCHS controller generates 80 clock
                    436:         * periods. In order to keep the 1ms gap, the MMCHS controller should
                    437:         * be configured to generate a clock whose frequency is smaller or
                    438:         * equal to 80 KHz.
                    439:         */
                    440:
                    441:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    442:            SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
                    443:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    444:            SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
                    445:        clkd = CLKD(80);
                    446:        n = 1;
                    447:        while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) {
                    448:                clkd >>= 1;
                    449:                n <<= 1;
                    450:        }
                    451:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    452:            SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft));
                    453:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    454:            SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);
                    455:
                    456:        bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
                    457:            bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT);
1.22    ! kiyohara  458:        SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000);
        !           459:        delay(1000);
        !           460:        stat = SDHC_READ(sc, SDHC_NINTR_STATUS);
        !           461:        SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat | SDHC_COMMAND_COMPLETE);
1.2       kiyohara  462:        bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
                    463:            bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT);
1.22    ! kiyohara  464:        SDHC_WRITE(sc, SDHC_NINTR_STATUS, 0xffffffff);
        !           465:
1.2       kiyohara  466:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    467:            SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
                    468:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    469:            SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
                    470:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    471:            SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
1.22    ! kiyohara  472:        timo = 3000000; /* XXXX 3 sec. */
        !           473:        while (--timo) {
        !           474:                if (SDHC_READ(sc, SDHC_CLOCK_CTL) & SDHC_INTCLK_STABLE)
        !           475:                        break;
        !           476:                delay(1);
        !           477:        }
        !           478:        if (timo == 0)
        !           479:                aprint_error_dev(self, "ICS timeout(2)\n");
1.2       kiyohara  480:        SDHC_WRITE(sc, SDHC_CLOCK_CTL,
                    481:            SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);
                    482:
1.1       matt      483:        return;
                    484:
                    485: fail:
                    486:        if (sc->sc_ih) {
                    487:                intr_disestablish(sc->sc_ih);
                    488:                sc->sc_ih = NULL;
                    489:        }
                    490:        bus_space_unmap(sc->sc_bst, sc->sc_bsh, oa->obio_size);
                    491: }
1.2       kiyohara  492:
                    493: static int
                    494: obiosdhc_detach(device_t self, int flags)
                    495: {
                    496: //     struct obiosdhc_softc *sc = device_private(self);
                    497:        int error;
                    498:
                    499:        error = config_detach_children(self, flags);
                    500:
                    501:        /* XXXXXX: Regurator turn-off via I2C. */
                    502:        /* XXXXXX: And disable ICLOCK/FCLOCK. */
                    503:
                    504:        return error;
                    505: }
                    506:
                    507: static int
                    508: obiosdhc_rod(struct sdhc_softc *sc, int on)
                    509: {
                    510:        struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc;
                    511:        uint32_t con;
                    512:
                    513:        con = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON);
                    514:        if (on)
                    515:                con |= CON_OD;
                    516:        else
                    517:                con &= ~CON_OD;
                    518:        bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON, con);
                    519:
                    520:        return 0;
                    521: }
                    522:
                    523: static int
                    524: obiosdhc_write_protect(struct sdhc_softc *sc)
                    525: {
                    526:
                    527:        /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */
                    528:        return 0;       /* XXXXXXX */
                    529: }
                    530:
                    531: static int
                    532: obiosdhc_card_detect(struct sdhc_softc *sc)
                    533: {
                    534:
                    535:        /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */
                    536:        return 1;       /* XXXXXXXX */
                    537: }
1.5       matt      538:
                    539: static int
1.19      jmcneill  540: obiosdhc_bus_width(struct sdhc_softc *sc, int width)
                    541: {
                    542:        struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc;
                    543:        uint32_t con;
                    544:
                    545:        con = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON);
                    546:        if (width == 8) {
                    547:                con |= CON_DW8;
                    548:        } else {
                    549:                con &= ~CON_DW8;
                    550:        }
                    551:        bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON, con);
                    552:
                    553:        return 0;
                    554: }
                    555:
1.16      bouyer    556: #if NEDMA > 0
1.18      jmcneill  557: static int
1.16      bouyer    558: obiosdhc_edma_init(struct obiosdhc_softc *sc, unsigned int edmabase)
                    559: {
1.18      jmcneill  560:        int i, error, rseg;
1.16      bouyer    561:
                    562:        /* Request tx and rx DMA channels */
                    563:        sc->sc_edma_tx = edma_channel_alloc(EDMA_TYPE_DMA, edmabase + 0,
                    564:            obiosdhc_edma_done, sc);
                    565:        KASSERT(sc->sc_edma_tx != NULL);
                    566:        sc->sc_edma_rx = edma_channel_alloc(EDMA_TYPE_DMA, edmabase + 1,
                    567:            obiosdhc_edma_done, sc);
                    568:        KASSERT(sc->sc_edma_rx != NULL);
                    569:
                    570:        /* Allocate some PaRAM pages */
                    571:        for (i = 0; i < __arraycount(sc->sc_edma_param_tx); i++) {
                    572:                sc->sc_edma_param_tx[i] = edma_param_alloc(sc->sc_edma_tx);
                    573:                KASSERT(sc->sc_edma_param_tx[i] != 0xffff);
                    574:        }
                    575:        for (i = 0; i < __arraycount(sc->sc_edma_param_rx); i++) {
                    576:                sc->sc_edma_param_rx[i] = edma_param_alloc(sc->sc_edma_rx);
                    577:                KASSERT(sc->sc_edma_param_rx[i] != 0xffff);
                    578:        }
                    579:
1.18      jmcneill  580:        /* Setup bounce buffer */
                    581:        error = bus_dmamem_alloc(sc->sc.sc_dmat, MAXPHYS, 32, MAXPHYS,
                    582:            sc->sc_edma_segs, 1, &rseg, BUS_DMA_WAITOK);
                    583:        if (error) {
                    584:                aprint_error_dev(sc->sc.sc_dev,
                    585:                    "couldn't allocate dmamem: %d\n", error);
                    586:                return error;
                    587:        }
                    588:        KASSERT(rseg == 1);
                    589:        error = bus_dmamem_map(sc->sc.sc_dmat, sc->sc_edma_segs, rseg, MAXPHYS,
                    590:            &sc->sc_edma_bbuf, BUS_DMA_WAITOK);
                    591:        if (error) {
                    592:                aprint_error_dev(sc->sc.sc_dev, "couldn't map dmamem: %d\n",
                    593:                    error);
                    594:                return error;
                    595:        }
                    596:        error = bus_dmamap_create(sc->sc.sc_dmat, MAXPHYS, 1, MAXPHYS, 0,
                    597:            BUS_DMA_WAITOK, &sc->sc_edma_dmamap);
                    598:        if (error) {
                    599:                aprint_error_dev(sc->sc.sc_dev, "couldn't create dmamap: %d\n",
                    600:                    error);
                    601:                return error;
                    602:        }
                    603:
                    604:        return error;
1.16      bouyer    605: }
                    606:
                    607: static int
                    608: obiosdhc_edma_xfer_data(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd)
                    609: {
                    610:        struct obiosdhc_softc *sc = device_private(sdhc_sc->sc_dev);
1.18      jmcneill  611:        const bus_dmamap_t map = cmd->c_dmamap;
                    612:        int seg, error;
                    613:        bool bounce;
                    614:
                    615:        for (bounce = false, seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
                    616:                if ((cmd->c_dmamap->dm_segs[seg].ds_addr & 0x1f) != 0) {
                    617:                        bounce = true;
                    618:                        break;
                    619:                }
                    620:        }
                    621:
                    622:        if (bounce) {
                    623:                error = bus_dmamap_load(sc->sc.sc_dmat, sc->sc_edma_dmamap,
                    624:                    sc->sc_edma_bbuf, MAXPHYS, NULL, BUS_DMA_WAITOK);
                    625:                if (error) {
                    626:                        device_printf(sc->sc.sc_dev,
                    627:                            "[bounce] bus_dmamap_load failed: %d\n", error);
                    628:                        return error;
                    629:                }
                    630:                if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
                    631:                        bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0,
                    632:                            MAXPHYS, BUS_DMASYNC_PREREAD);
                    633:                } else {
                    634:                        memcpy(sc->sc_edma_bbuf, cmd->c_data, cmd->c_datalen);
                    635:                        bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0,
                    636:                            MAXPHYS, BUS_DMASYNC_PREWRITE);
                    637:                }
                    638:
                    639:                cmd->c_dmamap = sc->sc_edma_dmamap;
                    640:        }
                    641:
                    642:        error = obiosdhc_edma_transfer(sdhc_sc, cmd);
                    643:
                    644:        if (bounce) {
                    645:                if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
                    646:                        bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0,
                    647:                            MAXPHYS, BUS_DMASYNC_POSTREAD);
                    648:                } else {
                    649:                        bus_dmamap_sync(sc->sc.sc_dmat, sc->sc_edma_dmamap, 0,
                    650:                            MAXPHYS, BUS_DMASYNC_POSTWRITE);
                    651:                }
                    652:                bus_dmamap_unload(sc->sc.sc_dmat, sc->sc_edma_dmamap);
                    653:                if (ISSET(cmd->c_flags, SCF_CMD_READ) && error == 0) {
                    654:                        memcpy(cmd->c_data, sc->sc_edma_bbuf, cmd->c_datalen);
                    655:                }
                    656:
                    657:                cmd->c_dmamap = map;
                    658:        }
                    659:
                    660:        return error;
                    661: }
                    662:
                    663: static int
                    664: obiosdhc_edma_transfer(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd)
                    665: {
                    666:        struct obiosdhc_softc *sc = device_private(sdhc_sc->sc_dev);
1.17      jmcneill  667:        kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]);
1.16      bouyer    668:        struct edma_channel *edma;
                    669:        uint16_t *edma_param;
                    670:        struct edma_param ep;
                    671:        size_t seg;
1.18      jmcneill  672:        int error, resid = cmd->c_datalen;
1.16      bouyer    673:        int blksize = MIN(cmd->c_datalen, cmd->c_blklen);
                    674:
1.17      jmcneill  675:        KASSERT(mutex_owned(plock));
                    676:
1.16      bouyer    677:        edma = ISSET(cmd->c_flags, SCF_CMD_READ) ?
                    678:            sc->sc_edma_rx : sc->sc_edma_tx;
                    679:        edma_param = ISSET(cmd->c_flags, SCF_CMD_READ) ?
                    680:            sc->sc_edma_param_rx : sc->sc_edma_param_tx;
                    681:
                    682:        DPRINTF(1, (sc->sc.sc_dev, "edma xfer: nsegs=%d ch# %d\n",
                    683:            cmd->c_dmamap->dm_nsegs, edma_channel_index(edma)));
                    684:
                    685:        if (cmd->c_dmamap->dm_nsegs > EDMA_MAX_PARAMS) {
                    686:                return ENOMEM;
                    687:        }
                    688:
                    689:        for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
1.18      jmcneill  690:                KASSERT(resid > 0);
                    691:                const int xferlen = min(resid,
                    692:                    cmd->c_dmamap->dm_segs[seg].ds_len);
                    693:                KASSERT(xferlen == cmd->c_dmamap->dm_segs[seg].ds_len ||
                    694:                        seg == cmd->c_dmamap->dm_nsegs - 1);
                    695:                resid -= xferlen;
                    696:                KASSERT((xferlen & 0x3) == 0);
1.16      bouyer    697:                ep.ep_opt = __SHIFTIN(2, EDMA_PARAM_OPT_FWID) /* 32-bit */;
                    698:                ep.ep_opt |= __SHIFTIN(edma_channel_index(edma),
                    699:                                       EDMA_PARAM_OPT_TCC);
                    700:                if (seg == cmd->c_dmamap->dm_nsegs - 1) {
                    701:                        ep.ep_opt |= EDMA_PARAM_OPT_TCINTEN;
                    702:                        ep.ep_link = 0xffff;
                    703:                } else {
                    704:                        ep.ep_link = EDMA_PARAM_BASE(edma_param[seg+1]);
                    705:                }
                    706:                if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
                    707:                        ep.ep_opt |= EDMA_PARAM_OPT_SAM;
                    708:                        ep.ep_src = sc->sc_edma_fifo;
                    709:                        ep.ep_dst = cmd->c_dmamap->dm_segs[seg].ds_addr;
                    710:                } else {
                    711:                        ep.ep_opt |= EDMA_PARAM_OPT_DAM;
                    712:                        ep.ep_src = cmd->c_dmamap->dm_segs[seg].ds_addr;
                    713:                        ep.ep_dst = sc->sc_edma_fifo;
                    714:                }
                    715:
1.18      jmcneill  716:                KASSERT(xferlen <= 65536 * 4);
                    717:
                    718:                /*
                    719:                 * In constant addressing mode, the address must be aligned
                    720:                 * to 256-bits.
                    721:                 */
                    722:                KASSERT((cmd->c_dmamap->dm_segs[seg].ds_addr & 0x1f) == 0);
1.16      bouyer    723:
1.22    ! kiyohara  724:                /*
1.16      bouyer    725:                 * For unknown reason, the A-DMA transfers never completes for
                    726:                 * transfers larger than 64 butes. So use a AB transfer,
                    727:                 * with a 64 bytes A len
                    728:                 */
                    729:                ep.ep_bcntrld = 0;      /* not used for AB-synchronous mode */
                    730:                ep.ep_opt |= EDMA_PARAM_OPT_SYNCDIM;
1.18      jmcneill  731:                ep.ep_acnt = min(xferlen, 64);
                    732:                ep.ep_bcnt = min(xferlen, blksize) / ep.ep_acnt;
                    733:                ep.ep_ccnt = xferlen / (ep.ep_acnt * ep.ep_bcnt);
1.16      bouyer    734:                ep.ep_srcbidx = ep.ep_dstbidx = 0;
                    735:                ep.ep_srccidx = ep.ep_dstcidx = 0;
                    736:                if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
                    737:                        ep.ep_dstbidx = ep.ep_acnt;
                    738:                        ep.ep_dstcidx = ep.ep_acnt * ep.ep_bcnt;
                    739:                } else {
                    740:                        ep.ep_srcbidx = ep.ep_acnt;
                    741:                        ep.ep_srccidx = ep.ep_acnt * ep.ep_bcnt;
                    742:                }
                    743:
                    744:                edma_set_param(edma, edma_param[seg], &ep);
                    745: #ifdef OM3SDHC_DEBUG
                    746:                if (om3sdhcdebug >= 1) {
                    747:                        printf("target OPT: %08x\n", ep.ep_opt);
                    748:                        edma_dump_param(edma, edma_param[seg]);
                    749:                }
                    750: #endif
                    751:        }
                    752:
                    753:        error = 0;
                    754:        sc->sc_edma_pending = true;
                    755:        edma_transfer_enable(edma, edma_param[0]);
                    756:        while (sc->sc_edma_pending) {
1.17      jmcneill  757:                error = cv_timedwait(&sc->sc_edma_cv, plock, hz*10);
1.16      bouyer    758:                if (error == EWOULDBLOCK) {
                    759:                        device_printf(sc->sc.sc_dev, "transfer timeout!\n");
                    760:                        edma_dump(edma);
                    761:                        edma_dump_param(edma, edma_param[0]);
                    762:                        edma_halt(edma);
                    763:                        sc->sc_edma_pending = false;
                    764:                        error = ETIMEDOUT;
                    765:                        break;
                    766:                }
                    767:        }
                    768:        edma_halt(edma);
                    769:
                    770:        return error;
                    771: }
                    772:
                    773: static void
                    774: obiosdhc_edma_done(void *priv)
                    775: {
                    776:        struct obiosdhc_softc *sc = priv;
1.17      jmcneill  777:        kmutex_t *plock = sdhc_host_lock(sc->sc_hosts[0]);
1.16      bouyer    778:
1.17      jmcneill  779:        mutex_enter(plock);
1.16      bouyer    780:        KASSERT(sc->sc_edma_pending == true);
                    781:        sc->sc_edma_pending = false;
                    782:        cv_broadcast(&sc->sc_edma_cv);
1.17      jmcneill  783:        mutex_exit(plock);
1.16      bouyer    784: }
                    785: #endif

CVSweb <webmaster@jp.NetBSD.org>