Tue Apr 14 18:45:25 2015 UTC ()
Add support for DMA transfers. From Jared D. McNeill, with final debug by me.
With this I can get nearly 20MB/s from my sdcard on the BB black at 1Ghz
(not bad for a 50Mhz 4-bits bus), and still 15MB/s on the BB white at
low speed (275Mhz).


(bouyer)
diff -r1.15 -r1.16 src/sys/arch/arm/omap/omap3_sdhc.c

cvs diff -r1.15 -r1.16 src/sys/arch/arm/omap/Attic/omap3_sdhc.c (switch to unified diff)

--- src/sys/arch/arm/omap/Attic/omap3_sdhc.c 2015/01/12 01:02:35 1.15
+++ src/sys/arch/arm/omap/Attic/omap3_sdhc.c 2015/04/14 18:45:25 1.16
@@ -1,382 +1,576 @@ @@ -1,382 +1,576 @@
1/* $NetBSD: omap3_sdhc.c,v 1.15 2015/01/12 01:02:35 jakllsch Exp $ */ 1/* $NetBSD: omap3_sdhc.c,v 1.16 2015/04/14 18:45:25 bouyer Exp $ */
2/*- 2/*-
3 * Copyright (c) 2011 The NetBSD Foundation, Inc. 3 * Copyright (c) 2011 The NetBSD Foundation, Inc.
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Matt Thomas of 3am Software Foundry. 7 * by Matt Thomas of 3am Software Foundry.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE. 28 * POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.15 2015/01/12 01:02:35 jakllsch Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: omap3_sdhc.c,v 1.16 2015/04/14 18:45:25 bouyer Exp $");
33 33
34#include "opt_omap.h" 34#include "opt_omap.h"
 35#include "edma.h"
35 36
36#include <sys/param.h> 37#include <sys/param.h>
37#include <sys/systm.h> 38#include <sys/systm.h>
38#include <sys/device.h> 39#include <sys/device.h>
39#include <sys/kernel.h> 40#include <sys/kernel.h>
40#include <sys/proc.h> 41#include <sys/proc.h>
41#include <sys/queue.h> 42#include <sys/queue.h>
42 43#include <sys/mutex.h>
 44#include <sys/condvar.h>
43#include <sys/bus.h> 45#include <sys/bus.h>
44 46
45#include <arm/omap/omap2_obiovar.h> 47#include <arm/omap/omap2_obiovar.h>
46#include <arm/omap/omap2_reg.h> 48#include <arm/omap/omap2_reg.h>
47#include <arm/omap/omap3_sdmmcreg.h> 49#include <arm/omap/omap3_sdmmcreg.h>
48 50
49#ifdef TI_AM335X 51#ifdef TI_AM335X
50# include <arm/omap/am335x_prcm.h> 52# include <arm/omap/am335x_prcm.h>
51# include <arm/omap/omap2_prcm.h> 53# include <arm/omap/omap2_prcm.h>
52#endif 54#endif
53 55
 56#if NEDMA > 0
 57# include <arm/omap/omap_edma.h>
 58#endif
 59
54#include <dev/sdmmc/sdhcreg.h> 60#include <dev/sdmmc/sdhcreg.h>
55#include <dev/sdmmc/sdhcvar.h> 61#include <dev/sdmmc/sdhcvar.h>
 62#include <dev/sdmmc/sdmmcvar.h>
 63
 64#ifdef TI_AM335X
 65#define EDMA_MAX_PARAMS 32
 66#endif
 67
 68#ifdef OM3SDHC_DEBUG
 69int om3sdhcdebug = 1;
 70#define DPRINTF(n,s) do { if ((n) <= om3sdhcdebug) device_printf s; } while (0)
 71#else
 72#define DPRINTF(n,s) do {} while (0)
 73#endif
 74
56 75
57#define CLKD(kz) (sc->sc.sc_clkbase / (kz)) 76#define CLKD(kz) (sc->sc.sc_clkbase / (kz))
58 77
59#define SDHC_READ(sc, reg) \ 78#define SDHC_READ(sc, reg) \
60 bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg)) 79 bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg))
61#define SDHC_WRITE(sc, reg, val) \ 80#define SDHC_WRITE(sc, reg, val) \
62 bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val)) 81 bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val))
63 82
64static int obiosdhc_match(device_t, cfdata_t, void *); 83static int obiosdhc_match(device_t, cfdata_t, void *);
65static void obiosdhc_attach(device_t, device_t, void *); 84static void obiosdhc_attach(device_t, device_t, void *);
66static int obiosdhc_detach(device_t, int); 85static int obiosdhc_detach(device_t, int);
67 86
68static int obiosdhc_bus_clock(struct sdhc_softc *, int); 87static int obiosdhc_bus_clock(struct sdhc_softc *, int);
69static int obiosdhc_rod(struct sdhc_softc *, int); 88static int obiosdhc_rod(struct sdhc_softc *, int);
70static int obiosdhc_write_protect(struct sdhc_softc *); 89static int obiosdhc_write_protect(struct sdhc_softc *);
71static int obiosdhc_card_detect(struct sdhc_softc *); 90static int obiosdhc_card_detect(struct sdhc_softc *);
72 91
73struct obiosdhc_softc { 92struct obiosdhc_softc {
74 struct sdhc_softc sc; 93 struct sdhc_softc sc;
75 bus_space_tag_t sc_bst; 94 bus_space_tag_t sc_bst;
76 bus_space_handle_t sc_bsh; 95 bus_space_handle_t sc_bsh;
77 bus_space_handle_t sc_sdhc_bsh; 96 bus_space_handle_t sc_sdhc_bsh;
78 struct sdhc_host *sc_hosts[1]; 97 struct sdhc_host *sc_hosts[1];
79 void *sc_ih; /* interrupt vectoring */ 98 void *sc_ih; /* interrupt vectoring */
 99
 100#if NEDMA > 0
 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 kmutex_t sc_edma_lock;
 106 kcondvar_t sc_edma_cv;
 107 bus_addr_t sc_edma_fifo;
 108 bool sc_edma_pending;
 109#endif
80}; 110};
81 111
 112#if NEDMA > 0
 113static void obiosdhc_edma_init(struct obiosdhc_softc *, unsigned int);
 114static int obiosdhc_edma_xfer_data(struct sdhc_softc *, struct sdmmc_command *);
 115static void obiosdhc_edma_done(void *);
 116#endif
 117
82#ifdef TI_AM335X 118#ifdef TI_AM335X
83struct am335x_sdhc { 119struct am335x_sdhc {
84 const char *as_name; 120 const char *as_name;
85 bus_addr_t as_base_addr; 121 bus_addr_t as_base_addr;
86 int as_intr; 122 int as_intr;
87 struct omap_module as_module; 123 struct omap_module as_module;
88}; 124};
89 125
90static const struct am335x_sdhc am335x_sdhc[] = { 126static const struct am335x_sdhc am335x_sdhc[] = {
91 /* XXX All offset by 0x100 because of the am335x's mmc registers. */ 127 /* XXX All offset by 0x100 because of the am335x's mmc registers. */
92 { "MMCHS0", SDMMC1_BASE_TIAM335X, 64, { AM335X_PRCM_CM_PER, 0x3c } }, 128 { "MMCHS0", SDMMC1_BASE_TIAM335X, 64, { AM335X_PRCM_CM_PER, 0x3c } },
93 { "MMC1", SDMMC2_BASE_TIAM335X, 28, { AM335X_PRCM_CM_PER, 0xf4 } }, 129 { "MMC1", SDMMC2_BASE_TIAM335X, 28, { AM335X_PRCM_CM_PER, 0xf4 } },
94 { "MMCHS2", SDMMC3_BASE_TIAM335X, 29, { AM335X_PRCM_CM_WKUP, 0xf8 } }, 130 { "MMCHS2", SDMMC3_BASE_TIAM335X, 29, { AM335X_PRCM_CM_WKUP, 0xf8 } },
95}; 131};
96#endif 132#endif
97 133
98CFATTACH_DECL_NEW(obiosdhc, sizeof(struct obiosdhc_softc), 134CFATTACH_DECL_NEW(obiosdhc, sizeof(struct obiosdhc_softc),
99 obiosdhc_match, obiosdhc_attach, obiosdhc_detach, NULL); 135 obiosdhc_match, obiosdhc_attach, obiosdhc_detach, NULL);
100 136
101static int 137static int
102obiosdhc_match(device_t parent, cfdata_t cf, void *aux) 138obiosdhc_match(device_t parent, cfdata_t cf, void *aux)
103{ 139{
104#if defined(OMAP_3430) || defined(OMAP_3530) || defined(OMAP4) 140#if defined(OMAP_3430) || defined(OMAP_3530) || defined(OMAP4)
105 struct obio_attach_args * const oa = aux; 141 struct obio_attach_args * const oa = aux;
106#endif 142#endif
107#ifdef TI_AM335X 143#ifdef TI_AM335X
108 struct obio_attach_args * const oa = aux; 144 struct obio_attach_args * const oa = aux;
109 size_t i; 145 size_t i;
110#endif 146#endif
111 147
112#if defined(OMAP_3430) 148#if defined(OMAP_3430)
113 if (oa->obio_addr == SDMMC1_BASE_3430 149 if (oa->obio_addr == SDMMC1_BASE_3430
114 || oa->obio_addr == SDMMC2_BASE_3430 150 || oa->obio_addr == SDMMC2_BASE_3430
115 || oa->obio_addr == SDMMC3_BASE_3430) 151 || oa->obio_addr == SDMMC3_BASE_3430)
116 return 1; 152 return 1;
117#elif defined(OMAP_3530) 153#elif defined(OMAP_3530)
118 if (oa->obio_addr == SDMMC1_BASE_3530 154 if (oa->obio_addr == SDMMC1_BASE_3530
119 || oa->obio_addr == SDMMC2_BASE_3530 155 || oa->obio_addr == SDMMC2_BASE_3530
120 || oa->obio_addr == SDMMC3_BASE_3530) 156 || oa->obio_addr == SDMMC3_BASE_3530)
121 return 1; 157 return 1;
122#elif defined(OMAP4) || defined(OMAP5) 158#elif defined(OMAP4) || defined(OMAP5)
123 if (oa->obio_addr == SDMMC1_BASE_4430 159 if (oa->obio_addr == SDMMC1_BASE_4430
124 || oa->obio_addr == SDMMC2_BASE_4430 160 || oa->obio_addr == SDMMC2_BASE_4430
125 || oa->obio_addr == SDMMC3_BASE_4430 161 || oa->obio_addr == SDMMC3_BASE_4430
126 || oa->obio_addr == SDMMC4_BASE_4430 162 || oa->obio_addr == SDMMC4_BASE_4430
127 || oa->obio_addr == SDMMC5_BASE_4430) 163 || oa->obio_addr == SDMMC5_BASE_4430)
128 return 1; 164 return 1;
129#endif 165#endif
130 166
131#ifdef TI_AM335X 167#ifdef TI_AM335X
132 for (i = 0; i < __arraycount(am335x_sdhc); i++) 168 for (i = 0; i < __arraycount(am335x_sdhc); i++)
133 if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) && 169 if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) &&
134 (oa->obio_intr == am335x_sdhc[i].as_intr)) 170 (oa->obio_intr == am335x_sdhc[i].as_intr))
135 return 1; 171 return 1;
136#endif 172#endif
137 173
138 return 0; 174 return 0;
139} 175}
140 176
141static void 177static void
142obiosdhc_attach(device_t parent, device_t self, void *aux) 178obiosdhc_attach(device_t parent, device_t self, void *aux)
143{ 179{
144 struct obiosdhc_softc * const sc = device_private(self); 180 struct obiosdhc_softc * const sc = device_private(self);
145 struct obio_attach_args * const oa = aux; 181 struct obio_attach_args * const oa = aux;
146 prop_dictionary_t prop = device_properties(self); 182 prop_dictionary_t prop = device_properties(self);
147 uint32_t clkd, stat; 183 uint32_t clkd, stat;
148 int error, timo, clksft, n; 184 int error, timo, clksft, n;
149 bool support8bit = false; 185 bool support8bit = false;
 186 const char *transfer_mode = "PIO";
150#ifdef TI_AM335X 187#ifdef TI_AM335X
151 size_t i; 188 size_t i;
152#endif 189#endif
153 190
154 prop_dictionary_get_bool(prop, "8bit", &support8bit); 191 prop_dictionary_get_bool(prop, "8bit", &support8bit);
155 192
156 sc->sc.sc_dmat = oa->obio_dmat; 193 sc->sc.sc_dmat = oa->obio_dmat;
157 sc->sc.sc_dev = self; 194 sc->sc.sc_dev = self;
158 //sc->sc.sc_flags |= SDHC_FLAG_USE_DMA; 
159 sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS; 195 sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS;
160 sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON; 196 sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
161 sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC; 197 sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
162 sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY; 198 sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
163 if (support8bit) 199 if (support8bit)
164 sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE; 200 sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE;
165#ifdef TI_AM335X 201#ifdef TI_AM335X
166 sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET; 202 sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET;
167 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY; 203 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
168#endif 204#endif
169#if defined(OMAP_3530) 205#if defined(OMAP_3530)
170 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY; 206 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
171#endif 207#endif
172 sc->sc.sc_host = sc->sc_hosts; 208 sc->sc.sc_host = sc->sc_hosts;
173 sc->sc.sc_clkbase = 96000; /* 96MHZ */ 209 sc->sc.sc_clkbase = 96000; /* 96MHZ */
174 if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk)) 210 if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk))
175 sc->sc.sc_clkmsk = 0x0000ffc0; 211 sc->sc.sc_clkmsk = 0x0000ffc0;
176 sc->sc.sc_vendor_rod = obiosdhc_rod; 212 sc->sc.sc_vendor_rod = obiosdhc_rod;
177 sc->sc.sc_vendor_write_protect = obiosdhc_write_protect; 213 sc->sc.sc_vendor_write_protect = obiosdhc_write_protect;
178 sc->sc.sc_vendor_card_detect = obiosdhc_card_detect; 214 sc->sc.sc_vendor_card_detect = obiosdhc_card_detect;
179 sc->sc.sc_vendor_bus_clock = obiosdhc_bus_clock; 215 sc->sc.sc_vendor_bus_clock = obiosdhc_bus_clock;
180 sc->sc_bst = oa->obio_iot; 216 sc->sc_bst = oa->obio_iot;
181 217
182 clksft = ffs(sc->sc.sc_clkmsk) - 1; 218 clksft = ffs(sc->sc.sc_clkmsk) - 1;
183 219
184 error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0, 220 error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0,
185 &sc->sc_bsh); 221 &sc->sc_bsh);
186 if (error) { 222 if (error) {
187 aprint_error_dev(self, 223 aprint_error_dev(self,
188 "can't map registers: %d\n", error); 224 "can't map registers: %d\n", error);
189 return; 225 return;
190 } 226 }
191 227
192 bus_space_subregion(sc->sc_bst, sc->sc_bsh, OMAP3_SDMMC_SDHC_OFFSET, 228 bus_space_subregion(sc->sc_bst, sc->sc_bsh, OMAP3_SDMMC_SDHC_OFFSET,
193 OMAP3_SDMMC_SDHC_SIZE, &sc->sc_sdhc_bsh); 229 OMAP3_SDMMC_SDHC_SIZE, &sc->sc_sdhc_bsh);
194 230
195 aprint_naive(": SDHC controller\n"); 231#if NEDMA > 0
196 aprint_normal(": SDHC controller\n"); 232 if (oa->obio_edmabase != -1) {
 233 mutex_init(&sc->sc_edma_lock, MUTEX_DEFAULT, IPL_SCHED);
 234 cv_init(&sc->sc_edma_cv, "sdhcedma");
 235 sc->sc_edma_fifo = oa->obio_addr +
 236 OMAP3_SDMMC_SDHC_OFFSET + SDHC_DATA;
 237 obiosdhc_edma_init(sc, oa->obio_edmabase);
 238 sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
 239 sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA;
 240 sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN;
 241 sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
 242 sc->sc.sc_vendor_transfer_data_dma = obiosdhc_edma_xfer_data;
 243 transfer_mode = "EDMA";
 244 }
 245#endif
 246
 247 aprint_naive("\n");
 248 aprint_normal(": SDHC controller (%s)\n", transfer_mode);
197 249
198#ifdef TI_AM335X 250#ifdef TI_AM335X
199 /* XXX Not really AM335X-specific. */ 251 /* XXX Not really AM335X-specific. */
200 for (i = 0; i < __arraycount(am335x_sdhc); i++) 252 for (i = 0; i < __arraycount(am335x_sdhc); i++)
201 if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) && 253 if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) &&
202 (oa->obio_intr == am335x_sdhc[i].as_intr)) { 254 (oa->obio_intr == am335x_sdhc[i].as_intr)) {
203 prcm_module_enable(&am335x_sdhc[i].as_module); 255 prcm_module_enable(&am335x_sdhc[i].as_module);
204 break; 256 break;
205 } 257 }
206 KASSERT(i < __arraycount(am335x_sdhc)); 258 KASSERT(i < __arraycount(am335x_sdhc));
207#endif 259#endif
208 260
209 /* XXXXXX: Turn-on regulator via I2C. */ 261 /* XXXXXX: Turn-on regulator via I2C. */
210 /* XXXXXX: And enable ICLOCK/FCLOCK. */ 262 /* XXXXXX: And enable ICLOCK/FCLOCK. */
211 263
212 /* MMCHS Soft reset */ 264 /* MMCHS Soft reset */
213 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG, 265 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
214 SYSCONFIG_SOFTRESET); 266 SYSCONFIG_SOFTRESET);
215 timo = 3000000; /* XXXX 3 sec. */ 267 timo = 3000000; /* XXXX 3 sec. */
216 while (timo--) { 268 while (timo--) {
217 if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) & 269 if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) &
218 SYSSTATUS_RESETDONE) 270 SYSSTATUS_RESETDONE)
219 break; 271 break;
220 delay(1); 272 delay(1);
221 } 273 }
222 if (timo == 0) 274 if (timo == 0)
223 aprint_error_dev(self, "Soft reset timeout\n"); 275 aprint_error_dev(self, "Soft reset timeout\n");
224 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG, 276 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
225 SYSCONFIG_ENAWAKEUP | SYSCONFIG_AUTOIDLE | SYSCONFIG_SIDLEMODE_AUTO | 277 SYSCONFIG_ENAWAKEUP | SYSCONFIG_AUTOIDLE | SYSCONFIG_SIDLEMODE_AUTO |
226 SYSCONFIG_CLOCKACTIVITY_FCLK | SYSCONFIG_CLOCKACTIVITY_ICLK); 278 SYSCONFIG_CLOCKACTIVITY_FCLK | SYSCONFIG_CLOCKACTIVITY_ICLK);
227 279
228 sc->sc_ih = intr_establish(oa->obio_intr, IPL_VM, IST_LEVEL, 280 sc->sc_ih = intr_establish(oa->obio_intr, IPL_VM, IST_LEVEL,
229 sdhc_intr, &sc->sc); 281 sdhc_intr, &sc->sc);
230 if (sc->sc_ih == NULL) { 282 if (sc->sc_ih == NULL) {
231 aprint_error_dev(self, "failed to establish interrupt %d\n", 283 aprint_error_dev(self, "failed to establish interrupt %d\n",
232 oa->obio_intr); 284 oa->obio_intr);
233 goto fail; 285 goto fail;
234 } 286 }
235 287
236 error = sdhc_host_found(&sc->sc, sc->sc_bst, sc->sc_sdhc_bsh, 288 error = sdhc_host_found(&sc->sc, sc->sc_bst, sc->sc_sdhc_bsh,
237 oa->obio_size - OMAP3_SDMMC_SDHC_OFFSET); 289 oa->obio_size - OMAP3_SDMMC_SDHC_OFFSET);
238 if (error != 0) { 290 if (error != 0) {
239 aprint_error_dev(self, "couldn't initialize host, error=%d\n", 291 aprint_error_dev(self, "couldn't initialize host, error=%d\n",
240 error); 292 error);
241 goto fail; 293 goto fail;
242 } 294 }
243 295
244 /* Set SDVS 1.8v and DTW 1bit mode */ 296 /* Set SDVS 1.8v and DTW 1bit mode */
245 SDHC_WRITE(sc, SDHC_HOST_CTL, 297 SDHC_WRITE(sc, SDHC_HOST_CTL,
246 SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8)); 298 SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8));
247 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 299 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
248 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_OD); 300 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_OD);
249 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 301 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
250 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE | 302 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE |
251 SDHC_SDCLK_ENABLE); 303 SDHC_SDCLK_ENABLE);
252 SDHC_WRITE(sc, SDHC_HOST_CTL, 304 SDHC_WRITE(sc, SDHC_HOST_CTL,
253 SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8); 305 SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8);
254 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 306 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
255 SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft); 307 SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
256 308
257 /* 309 /*
258 * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start 310 * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start
259 * from 'OMAP35x Applications Processor Technical Reference Manual'. 311 * from 'OMAP35x Applications Processor Technical Reference Manual'.
260 * 312 *
261 * During the INIT procedure, the MMCHS controller generates 80 clock 313 * During the INIT procedure, the MMCHS controller generates 80 clock
262 * periods. In order to keep the 1ms gap, the MMCHS controller should 314 * periods. In order to keep the 1ms gap, the MMCHS controller should
263 * be configured to generate a clock whose frequency is smaller or 315 * be configured to generate a clock whose frequency is smaller or
264 * equal to 80 KHz. 316 * equal to 80 KHz.
265 */ 317 */
266 318
267 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 319 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
268 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE); 320 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
269 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 321 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
270 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk); 322 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
271 clkd = CLKD(80); 323 clkd = CLKD(80);
272 n = 1; 324 n = 1;
273 while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) { 325 while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) {
274 clkd >>= 1; 326 clkd >>= 1;
275 n <<= 1; 327 n <<= 1;
276 } 328 }
277 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 329 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
278 SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft)); 330 SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft));
279 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 331 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
280 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE); 332 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);
281 333
282 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 334 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
283 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT); 335 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT);
284 for (; n > 0; n--) { 336 for (; n > 0; n--) {
285 SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000); 337 SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000);
286 timo = 3000000; /* XXXX 3 sec. */ 338 timo = 3000000; /* XXXX 3 sec. */
287 stat = 0; 339 stat = 0;
288 while (!(stat & SDHC_COMMAND_COMPLETE)) { 340 while (!(stat & SDHC_COMMAND_COMPLETE)) {
289 stat = SDHC_READ(sc, SDHC_NINTR_STATUS); 341 stat = SDHC_READ(sc, SDHC_NINTR_STATUS);
290 if (--timo == 0) 342 if (--timo == 0)
291 break; 343 break;
292 delay(1); 344 delay(1);
293 } 345 }
294 if (timo == 0) { 346 if (timo == 0) {
295 aprint_error_dev(self, "INIT Procedure timeout\n"); 347 aprint_error_dev(self, "INIT Procedure timeout\n");
296 break; 348 break;
297 } 349 }
298 SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat); 350 SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat);
299 } 351 }
300 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON, 352 bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
301 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT); 353 bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT);
302 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 354 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
303 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE); 355 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
304 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 356 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
305 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk); 357 SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
306 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 358 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
307 SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft); 359 SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
308 SDHC_WRITE(sc, SDHC_CLOCK_CTL, 360 SDHC_WRITE(sc, SDHC_CLOCK_CTL,
309 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE); 361 SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);
310 362
311 return; 363 return;
312 364
313fail: 365fail:
314 if (sc->sc_ih) { 366 if (sc->sc_ih) {
315 intr_disestablish(sc->sc_ih); 367 intr_disestablish(sc->sc_ih);
316 sc->sc_ih = NULL; 368 sc->sc_ih = NULL;
317 } 369 }
318 bus_space_unmap(sc->sc_bst, sc->sc_bsh, oa->obio_size); 370 bus_space_unmap(sc->sc_bst, sc->sc_bsh, oa->obio_size);
319} 371}
320 372
321static int 373static int
322obiosdhc_detach(device_t self, int flags) 374obiosdhc_detach(device_t self, int flags)
323{ 375{
324// struct obiosdhc_softc *sc = device_private(self); 376// struct obiosdhc_softc *sc = device_private(self);
325 int error; 377 int error;
326 378
327 error = config_detach_children(self, flags); 379 error = config_detach_children(self, flags);
328 380
329 /* XXXXXX: Regurator turn-off via I2C. */ 381 /* XXXXXX: Regurator turn-off via I2C. */
330 /* XXXXXX: And disable ICLOCK/FCLOCK. */ 382 /* XXXXXX: And disable ICLOCK/FCLOCK. */
331 383
332 return error; 384 return error;
333} 385}
334 386
335static int 387static int
336obiosdhc_rod(struct sdhc_softc *sc, int on) 388obiosdhc_rod(struct sdhc_softc *sc, int on)
337{ 389{
338 struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc; 390 struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc;
339 uint32_t con; 391 uint32_t con;
340 392
341 con = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON); 393 con = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON);
342 if (on) 394 if (on)
343 con |= CON_OD; 395 con |= CON_OD;
344 else 396 else
345 con &= ~CON_OD; 397 con &= ~CON_OD;
346 bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON, con); 398 bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_CON, con);
347 399
348 return 0; 400 return 0;
349} 401}
350 402
351static int 403static int
352obiosdhc_write_protect(struct sdhc_softc *sc) 404obiosdhc_write_protect(struct sdhc_softc *sc)
353{ 405{
354 406
355 /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */ 407 /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */
356 return 0; /* XXXXXXX */ 408 return 0; /* XXXXXXX */
357} 409}
358 410
359static int 411static int
360obiosdhc_card_detect(struct sdhc_softc *sc) 412obiosdhc_card_detect(struct sdhc_softc *sc)
361{ 413{
362 414
363 /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */ 415 /* Maybe board dependent, using GPIO. Get GPIO-pin from prop? */
364 return 1; /* XXXXXXXX */ 416 return 1; /* XXXXXXXX */
365} 417}
366 418
367static int 419static int
368obiosdhc_bus_clock(struct sdhc_softc *sc, int clk) 420obiosdhc_bus_clock(struct sdhc_softc *sc, int clk)
369{ 421{
370 struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc; 422 struct obiosdhc_softc *osc = (struct obiosdhc_softc *)sc;
371 uint32_t ctl; 423 uint32_t ctl;
372 424
373 ctl = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL); 425 ctl = bus_space_read_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL);
374 if (clk == 0) { 426 if (clk == 0) {
375 ctl &= ~SYSCTL_CEN; 427 ctl &= ~SYSCTL_CEN;
376 } else { 428 } else {
377 ctl |= SYSCTL_CEN; 429 ctl |= SYSCTL_CEN;
378 } 430 }
379 bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL, ctl); 431 bus_space_write_4(osc->sc_bst, osc->sc_bsh, MMCHS_SYSCTL, ctl);
380 432
381 return 0; 433 return 0;
382} 434}
 435
 436#if NEDMA > 0
 437static void
 438obiosdhc_edma_init(struct obiosdhc_softc *sc, unsigned int edmabase)
 439{
 440 int i;
 441
 442 /* Request tx and rx DMA channels */
 443 sc->sc_edma_tx = edma_channel_alloc(EDMA_TYPE_DMA, edmabase + 0,
 444 obiosdhc_edma_done, sc);
 445 KASSERT(sc->sc_edma_tx != NULL);
 446 sc->sc_edma_rx = edma_channel_alloc(EDMA_TYPE_DMA, edmabase + 1,
 447 obiosdhc_edma_done, sc);
 448 KASSERT(sc->sc_edma_rx != NULL);
 449
 450 device_printf(sc->sc.sc_dev, "EDMA tx channel %d, rx channel %d\n",
 451 edma_channel_index(sc->sc_edma_tx),
 452 edma_channel_index(sc->sc_edma_rx));
 453
 454 /* Allocate some PaRAM pages */
 455 for (i = 0; i < __arraycount(sc->sc_edma_param_tx); i++) {
 456 sc->sc_edma_param_tx[i] = edma_param_alloc(sc->sc_edma_tx);
 457 KASSERT(sc->sc_edma_param_tx[i] != 0xffff);
 458 }
 459 for (i = 0; i < __arraycount(sc->sc_edma_param_rx); i++) {
 460 sc->sc_edma_param_rx[i] = edma_param_alloc(sc->sc_edma_rx);
 461 KASSERT(sc->sc_edma_param_rx[i] != 0xffff);
 462 }
 463
 464 return;
 465}
 466
 467static int
 468obiosdhc_edma_xfer_data(struct sdhc_softc *sdhc_sc, struct sdmmc_command *cmd)
 469{
 470 struct obiosdhc_softc *sc = device_private(sdhc_sc->sc_dev);
 471 struct edma_channel *edma;
 472 uint16_t *edma_param;
 473 struct edma_param ep;
 474 size_t seg;
 475 int error;
 476 int blksize = MIN(cmd->c_datalen, cmd->c_blklen);
 477
 478 edma = ISSET(cmd->c_flags, SCF_CMD_READ) ?
 479 sc->sc_edma_rx : sc->sc_edma_tx;
 480 edma_param = ISSET(cmd->c_flags, SCF_CMD_READ) ?
 481 sc->sc_edma_param_rx : sc->sc_edma_param_tx;
 482
 483 DPRINTF(1, (sc->sc.sc_dev, "edma xfer: nsegs=%d ch# %d\n",
 484 cmd->c_dmamap->dm_nsegs, edma_channel_index(edma)));
 485
 486 if (cmd->c_dmamap->dm_nsegs > EDMA_MAX_PARAMS) {
 487 return ENOMEM;
 488 }
 489
 490 for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
 491 ep.ep_opt = __SHIFTIN(2, EDMA_PARAM_OPT_FWID) /* 32-bit */;
 492 ep.ep_opt |= __SHIFTIN(edma_channel_index(edma),
 493 EDMA_PARAM_OPT_TCC);
 494 if (seg == cmd->c_dmamap->dm_nsegs - 1) {
 495 ep.ep_opt |= EDMA_PARAM_OPT_TCINTEN;
 496 ep.ep_link = 0xffff;
 497 } else {
 498 ep.ep_link = EDMA_PARAM_BASE(edma_param[seg+1]);
 499 }
 500 if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
 501 ep.ep_opt |= EDMA_PARAM_OPT_SAM;
 502 ep.ep_src = sc->sc_edma_fifo;
 503 ep.ep_dst = cmd->c_dmamap->dm_segs[seg].ds_addr;
 504 } else {
 505 ep.ep_opt |= EDMA_PARAM_OPT_DAM;
 506 ep.ep_src = cmd->c_dmamap->dm_segs[seg].ds_addr;
 507 ep.ep_dst = sc->sc_edma_fifo;
 508 }
 509
 510 KASSERT(cmd->c_dmamap->dm_segs[seg].ds_len <= 65536 * 4);
 511
 512 /*
 513 * For unknown reason, the A-DMA transfers never completes for
 514 * transfers larger than 64 butes. So use a AB transfer,
 515 * with a 64 bytes A len
 516 */
 517 ep.ep_bcntrld = 0; /* not used for AB-synchronous mode */
 518 ep.ep_opt |= EDMA_PARAM_OPT_SYNCDIM;
 519 ep.ep_acnt = min(cmd->c_dmamap->dm_segs[seg].ds_len, 64);
 520 ep.ep_bcnt = min(cmd->c_dmamap->dm_segs[seg].ds_len, blksize) /
 521 ep.ep_acnt;
 522 ep.ep_ccnt = cmd->c_dmamap->dm_segs[seg].ds_len /
 523 (ep.ep_acnt * ep.ep_bcnt);
 524 ep.ep_srcbidx = ep.ep_dstbidx = 0;
 525 ep.ep_srccidx = ep.ep_dstcidx = 0;
 526 if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
 527 ep.ep_dstbidx = ep.ep_acnt;
 528 ep.ep_dstcidx = ep.ep_acnt * ep.ep_bcnt;
 529 } else {
 530 ep.ep_srcbidx = ep.ep_acnt;
 531 ep.ep_srccidx = ep.ep_acnt * ep.ep_bcnt;
 532 }
 533
 534 edma_set_param(edma, edma_param[seg], &ep);
 535#ifdef OM3SDHC_DEBUG
 536 if (om3sdhcdebug >= 1) {
 537 printf("target OPT: %08x\n", ep.ep_opt);
 538 edma_dump_param(edma, edma_param[seg]);
 539 }
 540#endif
 541 }
 542
 543 mutex_enter(&sc->sc_edma_lock);
 544 error = 0;
 545 sc->sc_edma_pending = true;
 546 edma_transfer_enable(edma, edma_param[0]);
 547 while (sc->sc_edma_pending) {
 548 error = cv_timedwait(&sc->sc_edma_cv, &sc->sc_edma_lock, hz*10);
 549 if (error == EWOULDBLOCK) {
 550 device_printf(sc->sc.sc_dev, "transfer timeout!\n");
 551 edma_dump(edma);
 552 edma_dump_param(edma, edma_param[0]);
 553 edma_halt(edma);
 554 sc->sc_edma_pending = false;
 555 error = ETIMEDOUT;
 556 break;
 557 }
 558 }
 559 edma_halt(edma);
 560 mutex_exit(&sc->sc_edma_lock);
 561
 562 return error;
 563}
 564
 565static void
 566obiosdhc_edma_done(void *priv)
 567{
 568 struct obiosdhc_softc *sc = priv;
 569
 570 mutex_enter(&sc->sc_edma_lock);
 571 KASSERT(sc->sc_edma_pending == true);
 572 sc->sc_edma_pending = false;
 573 cv_broadcast(&sc->sc_edma_cv);
 574 mutex_exit(&sc->sc_edma_lock);
 575}
 576#endif