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