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>