Fri Oct 16 14:22:25 2015 UTC ()
Avoid a divide by 0 when unplugging a sd card.


(bouyer)
diff -r1.21 -r1.22 src/sys/arch/arm/allwinner/awin_mmc.c

cvs diff -r1.21 -r1.22 src/sys/arch/arm/allwinner/Attic/awin_mmc.c (switch to unified diff)

--- src/sys/arch/arm/allwinner/Attic/awin_mmc.c 2015/08/08 17:21:19 1.21
+++ src/sys/arch/arm/allwinner/Attic/awin_mmc.c 2015/10/16 14:22:25 1.22
@@ -1,1004 +1,1007 @@ @@ -1,1004 +1,1007 @@
1/* $NetBSD: awin_mmc.c,v 1.21 2015/08/08 17:21:19 jmcneill Exp $ */ 1/* $NetBSD: awin_mmc.c,v 1.22 2015/10/16 14:22:25 bouyer Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "locators.h" 29#include "locators.h"
30 30
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.21 2015/08/08 17:21:19 jmcneill Exp $"); 32__KERNEL_RCSID(0, "$NetBSD: awin_mmc.c,v 1.22 2015/10/16 14:22:25 bouyer Exp $");
33 33
34#include <sys/param.h> 34#include <sys/param.h>
35#include <sys/bus.h> 35#include <sys/bus.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/intr.h> 37#include <sys/intr.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39#include <sys/kernel.h> 39#include <sys/kernel.h>
40 40
41#include <dev/sdmmc/sdmmcvar.h> 41#include <dev/sdmmc/sdmmcvar.h>
42#include <dev/sdmmc/sdmmcchip.h> 42#include <dev/sdmmc/sdmmcchip.h>
43#include <dev/sdmmc/sdmmc_ioreg.h> 43#include <dev/sdmmc/sdmmc_ioreg.h>
44 44
45#include <arm/allwinner/awin_reg.h> 45#include <arm/allwinner/awin_reg.h>
46#include <arm/allwinner/awin_var.h> 46#include <arm/allwinner/awin_var.h>
47 47
48#define AWIN_MMC_NDESC 16 48#define AWIN_MMC_NDESC 16
49#define AWIN_MMC_DMA_FTRGLEVEL_A20 0x20070008 49#define AWIN_MMC_DMA_FTRGLEVEL_A20 0x20070008
50#define AWIN_MMC_DMA_FTRGLEVEL_A80 0x200f0010 50#define AWIN_MMC_DMA_FTRGLEVEL_A80 0x200f0010
51 51
52static const struct awin_gpio_pinset awin_mmc_pinsets_a80[4] = { 52static const struct awin_gpio_pinset awin_mmc_pinsets_a80[4] = {
53 [0] = { 'F', AWIN_A80_PIO_PF_SDMMC0_FUNC, AWIN_A80_PIO_PF_SDMMC0_PINS, 53 [0] = { 'F', AWIN_A80_PIO_PF_SDMMC0_FUNC, AWIN_A80_PIO_PF_SDMMC0_PINS,
54 GPIO_PIN_PULLUP, 2 }, 54 GPIO_PIN_PULLUP, 2 },
55 [1] = { 'G', AWIN_A80_PIO_PG_SDMMC1_FUNC, AWIN_A80_PIO_PG_SDMMC1_PINS, 55 [1] = { 'G', AWIN_A80_PIO_PG_SDMMC1_FUNC, AWIN_A80_PIO_PG_SDMMC1_PINS,
56 GPIO_PIN_PULLUP, 2 }, 56 GPIO_PIN_PULLUP, 2 },
57 [2] = { 'C', AWIN_A80_PIO_PC_SDMMC2_FUNC, AWIN_A80_PIO_PC_SDMMC2_PINS, 57 [2] = { 'C', AWIN_A80_PIO_PC_SDMMC2_FUNC, AWIN_A80_PIO_PC_SDMMC2_PINS,
58 GPIO_PIN_PULLUP, 2 }, 58 GPIO_PIN_PULLUP, 2 },
59}; 59};
60 60
61static int awin_mmc_match(device_t, cfdata_t, void *); 61static int awin_mmc_match(device_t, cfdata_t, void *);
62static void awin_mmc_attach(device_t, device_t, void *); 62static void awin_mmc_attach(device_t, device_t, void *);
63static void awin_mmc_attach_i(device_t); 63static void awin_mmc_attach_i(device_t);
64 64
65static int awin_mmc_intr(void *); 65static int awin_mmc_intr(void *);
66 66
67static int awin_mmc_host_reset(sdmmc_chipset_handle_t); 67static int awin_mmc_host_reset(sdmmc_chipset_handle_t);
68static uint32_t awin_mmc_host_ocr(sdmmc_chipset_handle_t); 68static uint32_t awin_mmc_host_ocr(sdmmc_chipset_handle_t);
69static int awin_mmc_host_maxblklen(sdmmc_chipset_handle_t); 69static int awin_mmc_host_maxblklen(sdmmc_chipset_handle_t);
70static int awin_mmc_card_detect(sdmmc_chipset_handle_t); 70static int awin_mmc_card_detect(sdmmc_chipset_handle_t);
71static int awin_mmc_write_protect(sdmmc_chipset_handle_t); 71static int awin_mmc_write_protect(sdmmc_chipset_handle_t);
72static int awin_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t); 72static int awin_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
73static int awin_mmc_bus_clock(sdmmc_chipset_handle_t, int); 73static int awin_mmc_bus_clock(sdmmc_chipset_handle_t, int);
74static int awin_mmc_bus_width(sdmmc_chipset_handle_t, int); 74static int awin_mmc_bus_width(sdmmc_chipset_handle_t, int);
75static int awin_mmc_bus_rod(sdmmc_chipset_handle_t, int); 75static int awin_mmc_bus_rod(sdmmc_chipset_handle_t, int);
76static void awin_mmc_exec_command(sdmmc_chipset_handle_t, 76static void awin_mmc_exec_command(sdmmc_chipset_handle_t,
77 struct sdmmc_command *); 77 struct sdmmc_command *);
78static void awin_mmc_card_enable_intr(sdmmc_chipset_handle_t, int); 78static void awin_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
79static void awin_mmc_card_intr_ack(sdmmc_chipset_handle_t); 79static void awin_mmc_card_intr_ack(sdmmc_chipset_handle_t);
80 80
81static struct sdmmc_chip_functions awin_mmc_chip_functions = { 81static struct sdmmc_chip_functions awin_mmc_chip_functions = {
82 .host_reset = awin_mmc_host_reset, 82 .host_reset = awin_mmc_host_reset,
83 .host_ocr = awin_mmc_host_ocr, 83 .host_ocr = awin_mmc_host_ocr,
84 .host_maxblklen = awin_mmc_host_maxblklen, 84 .host_maxblklen = awin_mmc_host_maxblklen,
85 .card_detect = awin_mmc_card_detect, 85 .card_detect = awin_mmc_card_detect,
86 .write_protect = awin_mmc_write_protect, 86 .write_protect = awin_mmc_write_protect,
87 .bus_power = awin_mmc_bus_power, 87 .bus_power = awin_mmc_bus_power,
88 .bus_clock = awin_mmc_bus_clock, 88 .bus_clock = awin_mmc_bus_clock,
89 .bus_width = awin_mmc_bus_width, 89 .bus_width = awin_mmc_bus_width,
90 .bus_rod = awin_mmc_bus_rod, 90 .bus_rod = awin_mmc_bus_rod,
91 .exec_command = awin_mmc_exec_command, 91 .exec_command = awin_mmc_exec_command,
92 .card_enable_intr = awin_mmc_card_enable_intr, 92 .card_enable_intr = awin_mmc_card_enable_intr,
93 .card_intr_ack = awin_mmc_card_intr_ack, 93 .card_intr_ack = awin_mmc_card_intr_ack,
94}; 94};
95 95
96struct awin_mmc_softc { 96struct awin_mmc_softc {
97 device_t sc_dev; 97 device_t sc_dev;
98 bus_space_tag_t sc_bst; 98 bus_space_tag_t sc_bst;
99 bus_space_handle_t sc_bsh; 99 bus_space_handle_t sc_bsh;
100 bus_space_handle_t sc_clk_bsh; 100 bus_space_handle_t sc_clk_bsh;
101 bus_dma_tag_t sc_dmat; 101 bus_dma_tag_t sc_dmat;
102 102
103 bool sc_use_dma; 103 bool sc_use_dma;
104 104
105 void *sc_ih; 105 void *sc_ih;
106 kmutex_t sc_intr_lock; 106 kmutex_t sc_intr_lock;
107 kcondvar_t sc_intr_cv; 107 kcondvar_t sc_intr_cv;
108 kcondvar_t sc_idst_cv; 108 kcondvar_t sc_idst_cv;
109 109
110 int sc_mmc_width; 110 int sc_mmc_width;
111 int sc_mmc_present; 111 int sc_mmc_present;
112 int sc_mmc_port; 112 int sc_mmc_port;
113 113
114 device_t sc_sdmmc_dev; 114 device_t sc_sdmmc_dev;
115 115
116 uint32_t sc_fifo_reg; 116 uint32_t sc_fifo_reg;
117 uint32_t sc_dma_ftrglevel; 117 uint32_t sc_dma_ftrglevel;
118 118
119 uint32_t sc_idma_xferlen; 119 uint32_t sc_idma_xferlen;
120 bus_dma_segment_t sc_idma_segs[1]; 120 bus_dma_segment_t sc_idma_segs[1];
121 int sc_idma_nsegs; 121 int sc_idma_nsegs;
122 bus_size_t sc_idma_size; 122 bus_size_t sc_idma_size;
123 bus_dmamap_t sc_idma_map; 123 bus_dmamap_t sc_idma_map;
124 int sc_idma_ndesc; 124 int sc_idma_ndesc;
125 void *sc_idma_desc; 125 void *sc_idma_desc;
126 126
127 uint32_t sc_intr_rint; 127 uint32_t sc_intr_rint;
128 uint32_t sc_intr_mint; 128 uint32_t sc_intr_mint;
129 uint32_t sc_idma_idst; 129 uint32_t sc_idma_idst;
130 130
131 bool sc_has_gpio_detect; 131 bool sc_has_gpio_detect;
132 struct awin_gpio_pindata sc_gpio_detect; /* card detect */ 132 struct awin_gpio_pindata sc_gpio_detect; /* card detect */
133 bool sc_has_gpio_wp; 133 bool sc_has_gpio_wp;
134 struct awin_gpio_pindata sc_gpio_wp; /* write protect */ 134 struct awin_gpio_pindata sc_gpio_wp; /* write protect */
135 bool sc_has_gpio_led; 135 bool sc_has_gpio_led;
136 struct awin_gpio_pindata sc_gpio_led; /* LED */ 136 struct awin_gpio_pindata sc_gpio_led; /* LED */
137}; 137};
138 138
139CFATTACH_DECL_NEW(awin_mmc, sizeof(struct awin_mmc_softc), 139CFATTACH_DECL_NEW(awin_mmc, sizeof(struct awin_mmc_softc),
140 awin_mmc_match, awin_mmc_attach, NULL, NULL); 140 awin_mmc_match, awin_mmc_attach, NULL, NULL);
141 141
142#define MMC_WRITE(sc, reg, val) \ 142#define MMC_WRITE(sc, reg, val) \
143 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 143 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
144#define MMC_READ(sc, reg) \ 144#define MMC_READ(sc, reg) \
145 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 145 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
146 146
147static int 147static int
148awin_mmc_match(device_t parent, cfdata_t cf, void *aux) 148awin_mmc_match(device_t parent, cfdata_t cf, void *aux)
149{ 149{
150 struct awinio_attach_args * const aio = aux; 150 struct awinio_attach_args * const aio = aux;
151 const struct awin_locators * const loc = &aio->aio_loc; 151 const struct awin_locators * const loc = &aio->aio_loc;
152 const int port = cf->cf_loc[AWINIOCF_PORT]; 152 const int port = cf->cf_loc[AWINIOCF_PORT];
153 153
154 if (strcmp(cf->cf_name, loc->loc_name)) 154 if (strcmp(cf->cf_name, loc->loc_name))
155 return 0; 155 return 0;
156 156
157 if (port != AWINIOCF_PORT_DEFAULT && port != loc->loc_port) 157 if (port != AWINIOCF_PORT_DEFAULT && port != loc->loc_port)
158 return 0; 158 return 0;
159 159
160 return 1; 160 return 1;
161} 161}
162 162
163static int 163static int
164awin_mmc_idma_setup(struct awin_mmc_softc *sc) 164awin_mmc_idma_setup(struct awin_mmc_softc *sc)
165{ 165{
166 int error; 166 int error;
167 167
168 if (awin_chip_id() == AWIN_CHIP_ID_A10) { 168 if (awin_chip_id() == AWIN_CHIP_ID_A10) {
169 sc->sc_idma_xferlen = 0x2000; 169 sc->sc_idma_xferlen = 0x2000;
170 } else { 170 } else {
171 sc->sc_idma_xferlen = 0x10000; 171 sc->sc_idma_xferlen = 0x10000;
172 } 172 }
173 173
174 sc->sc_idma_ndesc = AWIN_MMC_NDESC; 174 sc->sc_idma_ndesc = AWIN_MMC_NDESC;
175 sc->sc_idma_size = sizeof(struct awin_mmc_idma_descriptor) * 175 sc->sc_idma_size = sizeof(struct awin_mmc_idma_descriptor) *
176 sc->sc_idma_ndesc; 176 sc->sc_idma_ndesc;
177 error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0, 177 error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0,
178 sc->sc_idma_size, sc->sc_idma_segs, 1, 178 sc->sc_idma_size, sc->sc_idma_segs, 1,
179 &sc->sc_idma_nsegs, BUS_DMA_WAITOK); 179 &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
180 if (error) 180 if (error)
181 return error; 181 return error;
182 error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs, 182 error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
183 sc->sc_idma_nsegs, sc->sc_idma_size, 183 sc->sc_idma_nsegs, sc->sc_idma_size,
184 &sc->sc_idma_desc, BUS_DMA_WAITOK); 184 &sc->sc_idma_desc, BUS_DMA_WAITOK);
185 if (error) 185 if (error)
186 goto free; 186 goto free;
187 error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1, 187 error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
188 sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map); 188 sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
189 if (error) 189 if (error)
190 goto unmap; 190 goto unmap;
191 error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map, 191 error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
192 sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK); 192 sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
193 if (error) 193 if (error)
194 goto destroy; 194 goto destroy;
195 return 0; 195 return 0;
196 196
197destroy: 197destroy:
198 bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map); 198 bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
199unmap: 199unmap:
200 bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size); 200 bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
201free: 201free:
202 bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs); 202 bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
203 return error; 203 return error;
204} 204}
205 205
206static void 206static void
207awin_mmc_attach(device_t parent, device_t self, void *aux) 207awin_mmc_attach(device_t parent, device_t self, void *aux)
208{ 208{
209 struct awin_mmc_softc * const sc = device_private(self); 209 struct awin_mmc_softc * const sc = device_private(self);
210 struct awinio_attach_args * const aio = aux; 210 struct awinio_attach_args * const aio = aux;
211 const struct awin_locators * const loc = &aio->aio_loc; 211 const struct awin_locators * const loc = &aio->aio_loc;
212 prop_dictionary_t cfg = device_properties(self); 212 prop_dictionary_t cfg = device_properties(self);
213 const char *pin_name; 213 const char *pin_name;
214 214
215 sc->sc_dev = self; 215 sc->sc_dev = self;
216 sc->sc_bst = aio->aio_core_bst; 216 sc->sc_bst = aio->aio_core_bst;
217 sc->sc_dmat = aio->aio_dmat; 217 sc->sc_dmat = aio->aio_dmat;
218 sc->sc_mmc_port = loc->loc_port; 218 sc->sc_mmc_port = loc->loc_port;
219 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO); 219 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
220 cv_init(&sc->sc_intr_cv, "awinmmcirq"); 220 cv_init(&sc->sc_intr_cv, "awinmmcirq");
221 cv_init(&sc->sc_idst_cv, "awinmmcdma"); 221 cv_init(&sc->sc_idst_cv, "awinmmcdma");
222 bus_space_subregion(sc->sc_bst, aio->aio_core_bsh, 222 bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
223 loc->loc_offset, loc->loc_size, &sc->sc_bsh); 223 loc->loc_offset, loc->loc_size, &sc->sc_bsh);
224 224
225 sc->sc_use_dma = true; 225 sc->sc_use_dma = true;
226 prop_dictionary_get_bool(cfg, "dma", &sc->sc_use_dma); 226 prop_dictionary_get_bool(cfg, "dma", &sc->sc_use_dma);
227 227
228 aprint_naive("\n"); 228 aprint_naive("\n");
229 aprint_normal(": SD3.0 (%s)\n", sc->sc_use_dma ? "DMA" : "PIO"); 229 aprint_normal(": SD3.0 (%s)\n", sc->sc_use_dma ? "DMA" : "PIO");
230 230
231 if (awin_chip_id() == AWIN_CHIP_ID_A80) { 231 if (awin_chip_id() == AWIN_CHIP_ID_A80) {
232 if (awin_mmc_pinsets_a80[loc->loc_port].pinset_group) { 232 if (awin_mmc_pinsets_a80[loc->loc_port].pinset_group) {
233 awin_gpio_pinset_acquire( 233 awin_gpio_pinset_acquire(
234 &awin_mmc_pinsets_a80[loc->loc_port]); 234 &awin_mmc_pinsets_a80[loc->loc_port]);
235 } 235 }
236 236
237 bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh, 237 bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh,
238 AWIN_A80_CCU_SCLK_SDMMC0_CLK_REG + (loc->loc_port * 4), 4, 238 AWIN_A80_CCU_SCLK_SDMMC0_CLK_REG + (loc->loc_port * 4), 4,
239 &sc->sc_clk_bsh); 239 &sc->sc_clk_bsh);
240 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, 240 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
241 AWIN_A80_CCU_SCLK_BUS_CLK_GATING0_REG, 241 AWIN_A80_CCU_SCLK_BUS_CLK_GATING0_REG,
242 AWIN_A80_CCU_SCLK_BUS_CLK_GATING0_SD, 0); 242 AWIN_A80_CCU_SCLK_BUS_CLK_GATING0_SD, 0);
243 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, 243 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
244 AWIN_A80_CCU_SCLK_BUS_SOFT_RST0_REG, 244 AWIN_A80_CCU_SCLK_BUS_SOFT_RST0_REG,
245 AWIN_A80_CCU_SCLK_BUS_SOFT_RST0_SD, 0); 245 AWIN_A80_CCU_SCLK_BUS_SOFT_RST0_SD, 0);
246 awin_reg_set_clear(aio->aio_core_bst, aio->aio_core_bsh, 246 awin_reg_set_clear(aio->aio_core_bst, aio->aio_core_bsh,
247 AWIN_A80_SDMMC_COMM_OFFSET + (loc->loc_port * 4), 247 AWIN_A80_SDMMC_COMM_OFFSET + (loc->loc_port * 4),
248 AWIN_A80_SDMMC_COMM_SDC_RESET_SW | 248 AWIN_A80_SDMMC_COMM_SDC_RESET_SW |
249 AWIN_A80_SDMMC_COMM_SDC_CLOCK_SW, 0); 249 AWIN_A80_SDMMC_COMM_SDC_CLOCK_SW, 0);
250 delay(1000); 250 delay(1000);
251 } else { 251 } else {
252 bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh, 252 bus_space_subregion(sc->sc_bst, aio->aio_ccm_bsh,
253 AWIN_SD0_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_clk_bsh); 253 AWIN_SD0_CLK_REG + (loc->loc_port * 4), 4, &sc->sc_clk_bsh);
254 254
255 awin_pll6_enable(); 255 awin_pll6_enable();
256 256
257 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, 257 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
258 AWIN_AHB_GATING0_REG, 258 AWIN_AHB_GATING0_REG,
259 AWIN_AHB_GATING0_SDMMC0 << loc->loc_port, 0); 259 AWIN_AHB_GATING0_SDMMC0 << loc->loc_port, 0);
260 if (awin_chip_id() == AWIN_CHIP_ID_A31) { 260 if (awin_chip_id() == AWIN_CHIP_ID_A31) {
261 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh, 261 awin_reg_set_clear(aio->aio_core_bst, aio->aio_ccm_bsh,
262 AWIN_A31_AHB_RESET0_REG, 262 AWIN_A31_AHB_RESET0_REG,
263 AWIN_A31_AHB_RESET0_SD0_RST << loc->loc_port, 0); 263 AWIN_A31_AHB_RESET0_SD0_RST << loc->loc_port, 0);
264 } 264 }
265 } 265 }
266 266
267 if (prop_dictionary_get_cstring_nocopy(cfg, "detect-gpio", &pin_name)) { 267 if (prop_dictionary_get_cstring_nocopy(cfg, "detect-gpio", &pin_name)) {
268 if (!awin_gpio_pin_reserve(pin_name, &sc->sc_gpio_detect)) { 268 if (!awin_gpio_pin_reserve(pin_name, &sc->sc_gpio_detect)) {
269 aprint_error_dev(self, 269 aprint_error_dev(self,
270 "failed to reserve GPIO \"%s\"\n", pin_name); 270 "failed to reserve GPIO \"%s\"\n", pin_name);
271 } else { 271 } else {
272 sc->sc_has_gpio_detect = true; 272 sc->sc_has_gpio_detect = true;
273 } 273 }
274 } 274 }
275 if (prop_dictionary_get_cstring_nocopy(cfg, "wp-gpio", &pin_name)) { 275 if (prop_dictionary_get_cstring_nocopy(cfg, "wp-gpio", &pin_name)) {
276 if (!awin_gpio_pin_reserve(pin_name, &sc->sc_gpio_wp)) { 276 if (!awin_gpio_pin_reserve(pin_name, &sc->sc_gpio_wp)) {
277 aprint_error_dev(self, 277 aprint_error_dev(self,
278 "failed to reserve GPIO \"%s\"\n", pin_name); 278 "failed to reserve GPIO \"%s\"\n", pin_name);
279 } else { 279 } else {
280 sc->sc_has_gpio_wp = true; 280 sc->sc_has_gpio_wp = true;
281 } 281 }
282 } 282 }
283 if (prop_dictionary_get_cstring_nocopy(cfg, "led-gpio", &pin_name)) { 283 if (prop_dictionary_get_cstring_nocopy(cfg, "led-gpio", &pin_name)) {
284 if (!awin_gpio_pin_reserve(pin_name, &sc->sc_gpio_led)) { 284 if (!awin_gpio_pin_reserve(pin_name, &sc->sc_gpio_led)) {
285 aprint_error_dev(self, 285 aprint_error_dev(self,
286 "failed to reserve GPIO \"%s\"\n", pin_name); 286 "failed to reserve GPIO \"%s\"\n", pin_name);
287 } else { 287 } else {
288 sc->sc_has_gpio_led = true; 288 sc->sc_has_gpio_led = true;
289 } 289 }
290 } 290 }
291 291
292 switch (awin_chip_id()) { 292 switch (awin_chip_id()) {
293 case AWIN_CHIP_ID_A80: 293 case AWIN_CHIP_ID_A80:
294 sc->sc_fifo_reg = AWIN_A31_MMC_FIFO; 294 sc->sc_fifo_reg = AWIN_A31_MMC_FIFO;
295 sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A80; 295 sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A80;
296 break; 296 break;
297 case AWIN_CHIP_ID_A31: 297 case AWIN_CHIP_ID_A31:
298 sc->sc_fifo_reg = AWIN_A31_MMC_FIFO; 298 sc->sc_fifo_reg = AWIN_A31_MMC_FIFO;
299 sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A20; 299 sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A20;
300 break; 300 break;
301 default: 301 default:
302 sc->sc_fifo_reg = AWIN_MMC_FIFO; 302 sc->sc_fifo_reg = AWIN_MMC_FIFO;
303 sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A20; 303 sc->sc_dma_ftrglevel = AWIN_MMC_DMA_FTRGLEVEL_A20;
304 break; 304 break;
305 } 305 }
306 306
307 if (sc->sc_use_dma) { 307 if (sc->sc_use_dma) {
308 if (awin_mmc_idma_setup(sc) != 0) { 308 if (awin_mmc_idma_setup(sc) != 0) {
309 aprint_error_dev(self, "failed to setup DMA\n"); 309 aprint_error_dev(self, "failed to setup DMA\n");
310 return; 310 return;
311 } 311 }
312 } 312 }
313 313
314 sc->sc_ih = intr_establish(loc->loc_intr, IPL_BIO, IST_LEVEL, 314 sc->sc_ih = intr_establish(loc->loc_intr, IPL_BIO, IST_LEVEL,
315 awin_mmc_intr, sc); 315 awin_mmc_intr, sc);
316 if (sc->sc_ih == NULL) { 316 if (sc->sc_ih == NULL) {
317 aprint_error_dev(self, "couldn't establish interrupt %d\n", 317 aprint_error_dev(self, "couldn't establish interrupt %d\n",
318 loc->loc_intr); 318 loc->loc_intr);
319 return; 319 return;
320 } 320 }
321 aprint_normal_dev(self, "interrupting at irq %d\n", loc->loc_intr); 321 aprint_normal_dev(self, "interrupting at irq %d\n", loc->loc_intr);
322 322
323 config_interrupts(self, awin_mmc_attach_i); 323 config_interrupts(self, awin_mmc_attach_i);
324} 324}
325 325
326static int 326static int
327awin_mmc_set_clock(struct awin_mmc_softc *sc, u_int freq) 327awin_mmc_set_clock(struct awin_mmc_softc *sc, u_int freq)
328{ 328{
329 uint32_t odly, sdly, clksrc, n, m, clk; 329 uint32_t odly, sdly, clksrc, n, m, clk;
330 u_int osc24m_freq = AWIN_REF_FREQ / 1000; 330 u_int osc24m_freq = AWIN_REF_FREQ / 1000;
331 u_int pll_freq; 331 u_int pll_freq;
332 332
333 if (awin_chip_id() == AWIN_CHIP_ID_A80) { 333 if (awin_chip_id() == AWIN_CHIP_ID_A80) {
334 pll_freq = awin_periph0_get_rate() / 1000; 334 pll_freq = awin_periph0_get_rate() / 1000;
335 } else { 335 } else {
336 pll_freq = awin_pll6_get_rate() / 1000; 336 pll_freq = awin_pll6_get_rate() / 1000;
337 } 337 }
338 338
339#ifdef AWIN_MMC_DEBUG 339#ifdef AWIN_MMC_DEBUG
340 aprint_normal_dev(sc->sc_dev, "freq = %d, pll_freq = %d\n", 340 aprint_normal_dev(sc->sc_dev, "freq = %d, pll_freq = %d\n",
341 freq, pll_freq); 341 freq, pll_freq);
342#endif 342#endif
343 343
344 if (freq <= 400) { 344 if (freq <= 400) {
345 odly = 0; 345 odly = 0;
346 sdly = 0; 346 sdly = 0;
347 clksrc = AWIN_SD_CLK_SRC_SEL_OSC24M; 347 clksrc = AWIN_SD_CLK_SRC_SEL_OSC24M;
348 n = 2; 348 n = 2;
349 m = ((osc24m_freq / (1 << n)) / freq) - 1; 349 if (freq > 0)
 350 m = ((osc24m_freq / (1 << n)) / freq) - 1;
 351 else
 352 m = 15;
350 } else if (freq <= 25000) { 353 } else if (freq <= 25000) {
351 odly = 0; 354 odly = 0;
352 sdly = 5; 355 sdly = 5;
353 clksrc = AWIN_SD_CLK_SRC_SEL_PLL6; 356 clksrc = AWIN_SD_CLK_SRC_SEL_PLL6;
354 n = awin_chip_id() == AWIN_CHIP_ID_A80 ? 2 : 0; 357 n = awin_chip_id() == AWIN_CHIP_ID_A80 ? 2 : 0;
355 m = ((pll_freq / freq) / (1 << n)) - 1; 358 m = ((pll_freq / freq) / (1 << n)) - 1;
356 } else if (freq <= 50000) { 359 } else if (freq <= 50000) {
357 odly = awin_chip_id() == AWIN_CHIP_ID_A80 ? 5 : 3; 360 odly = awin_chip_id() == AWIN_CHIP_ID_A80 ? 5 : 3;
358 sdly = awin_chip_id() == AWIN_CHIP_ID_A80 ? 4 : 5; 361 sdly = awin_chip_id() == AWIN_CHIP_ID_A80 ? 4 : 5;
359 clksrc = AWIN_SD_CLK_SRC_SEL_PLL6; 362 clksrc = AWIN_SD_CLK_SRC_SEL_PLL6;
360 n = awin_chip_id() == AWIN_CHIP_ID_A80 ? 2 : 0; 363 n = awin_chip_id() == AWIN_CHIP_ID_A80 ? 2 : 0;
361 m = ((pll_freq / freq) / (1 << n)) - 1; 364 m = ((pll_freq / freq) / (1 << n)) - 1;
362 } else { 365 } else {
363 /* UHS speeds not implemented yet */ 366 /* UHS speeds not implemented yet */
364 return EIO; 367 return EIO;
365 } 368 }
366 369
367 clk = bus_space_read_4(sc->sc_bst, sc->sc_clk_bsh, 0); 370 clk = bus_space_read_4(sc->sc_bst, sc->sc_clk_bsh, 0);
368 clk &= ~AWIN_SD_CLK_SRC_SEL; 371 clk &= ~AWIN_SD_CLK_SRC_SEL;
369 clk |= __SHIFTIN(clksrc, AWIN_SD_CLK_SRC_SEL); 372 clk |= __SHIFTIN(clksrc, AWIN_SD_CLK_SRC_SEL);
370 clk &= ~AWIN_SD_CLK_DIV_RATIO_N; 373 clk &= ~AWIN_SD_CLK_DIV_RATIO_N;
371 clk |= __SHIFTIN(n, AWIN_SD_CLK_DIV_RATIO_N); 374 clk |= __SHIFTIN(n, AWIN_SD_CLK_DIV_RATIO_N);
372 clk &= ~AWIN_SD_CLK_DIV_RATIO_M; 375 clk &= ~AWIN_SD_CLK_DIV_RATIO_M;
373 clk |= __SHIFTIN(m, AWIN_SD_CLK_DIV_RATIO_M); 376 clk |= __SHIFTIN(m, AWIN_SD_CLK_DIV_RATIO_M);
374 clk &= ~AWIN_SD_CLK_OUTPUT_PHASE_CTR; 377 clk &= ~AWIN_SD_CLK_OUTPUT_PHASE_CTR;
375 clk |= __SHIFTIN(odly, AWIN_SD_CLK_OUTPUT_PHASE_CTR); 378 clk |= __SHIFTIN(odly, AWIN_SD_CLK_OUTPUT_PHASE_CTR);
376 clk &= ~AWIN_SD_CLK_PHASE_CTR; 379 clk &= ~AWIN_SD_CLK_PHASE_CTR;
377 clk |= __SHIFTIN(sdly, AWIN_SD_CLK_PHASE_CTR); 380 clk |= __SHIFTIN(sdly, AWIN_SD_CLK_PHASE_CTR);
378 clk |= AWIN_PLL_CFG_ENABLE; 381 clk |= AWIN_PLL_CFG_ENABLE;
379 bus_space_write_4(sc->sc_bst, sc->sc_clk_bsh, 0, clk); 382 bus_space_write_4(sc->sc_bst, sc->sc_clk_bsh, 0, clk);
380 383
381 return 0; 384 return 0;
382} 385}
383 386
384static void 387static void
385awin_mmc_attach_i(device_t self) 388awin_mmc_attach_i(device_t self)
386{ 389{
387 struct awin_mmc_softc *sc = device_private(self); 390 struct awin_mmc_softc *sc = device_private(self);
388 struct sdmmcbus_attach_args saa; 391 struct sdmmcbus_attach_args saa;
389 392
390 awin_mmc_host_reset(sc); 393 awin_mmc_host_reset(sc);
391 awin_mmc_bus_width(sc, 1); 394 awin_mmc_bus_width(sc, 1);
392 awin_mmc_set_clock(sc, 400); 395 awin_mmc_set_clock(sc, 400);
393 396
394 memset(&saa, 0, sizeof(saa)); 397 memset(&saa, 0, sizeof(saa));
395 saa.saa_busname = "sdmmc"; 398 saa.saa_busname = "sdmmc";
396 saa.saa_sct = &awin_mmc_chip_functions; 399 saa.saa_sct = &awin_mmc_chip_functions;
397 saa.saa_sch = sc; 400 saa.saa_sch = sc;
398 saa.saa_clkmin = 400; 401 saa.saa_clkmin = 400;
399 saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000; 402 saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000;
400 saa.saa_caps = SMC_CAPS_4BIT_MODE| 403 saa.saa_caps = SMC_CAPS_4BIT_MODE|
401 SMC_CAPS_8BIT_MODE| 404 SMC_CAPS_8BIT_MODE|
402 SMC_CAPS_SD_HIGHSPEED| 405 SMC_CAPS_SD_HIGHSPEED|
403 SMC_CAPS_MMC_HIGHSPEED| 406 SMC_CAPS_MMC_HIGHSPEED|
404 SMC_CAPS_AUTO_STOP; 407 SMC_CAPS_AUTO_STOP;
405 if (sc->sc_use_dma) { 408 if (sc->sc_use_dma) {
406 saa.saa_dmat = sc->sc_dmat; 409 saa.saa_dmat = sc->sc_dmat;
407 saa.saa_caps |= SMC_CAPS_DMA| 410 saa.saa_caps |= SMC_CAPS_DMA|
408 SMC_CAPS_MULTI_SEG_DMA; 411 SMC_CAPS_MULTI_SEG_DMA;
409 } 412 }
410 if (sc->sc_has_gpio_detect) { 413 if (sc->sc_has_gpio_detect) {
411 saa.saa_caps |= SMC_CAPS_POLL_CARD_DET; 414 saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
412 } 415 }
413 416
414 sc->sc_sdmmc_dev = config_found(self, &saa, NULL); 417 sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
415} 418}
416 419
417static int 420static int
418awin_mmc_intr(void *priv) 421awin_mmc_intr(void *priv)
419{ 422{
420 struct awin_mmc_softc *sc = priv; 423 struct awin_mmc_softc *sc = priv;
421 uint32_t idst, rint, mint; 424 uint32_t idst, rint, mint;
422 425
423 mutex_enter(&sc->sc_intr_lock); 426 mutex_enter(&sc->sc_intr_lock);
424 idst = MMC_READ(sc, AWIN_MMC_IDST); 427 idst = MMC_READ(sc, AWIN_MMC_IDST);
425 rint = MMC_READ(sc, AWIN_MMC_RINT); 428 rint = MMC_READ(sc, AWIN_MMC_RINT);
426 mint = MMC_READ(sc, AWIN_MMC_MINT); 429 mint = MMC_READ(sc, AWIN_MMC_MINT);
427 if (!idst && !rint && !mint) { 430 if (!idst && !rint && !mint) {
428 mutex_exit(&sc->sc_intr_lock); 431 mutex_exit(&sc->sc_intr_lock);
429 return 0; 432 return 0;
430 } 433 }
431 MMC_WRITE(sc, AWIN_MMC_IDST, idst); 434 MMC_WRITE(sc, AWIN_MMC_IDST, idst);
432 MMC_WRITE(sc, AWIN_MMC_RINT, rint); 435 MMC_WRITE(sc, AWIN_MMC_RINT, rint);
433 MMC_WRITE(sc, AWIN_MMC_MINT, mint); 436 MMC_WRITE(sc, AWIN_MMC_MINT, mint);
434 437
435#ifdef AWIN_MMC_DEBUG 438#ifdef AWIN_MMC_DEBUG
436 device_printf(sc->sc_dev, "mmc intr idst=%08X rint=%08X mint=%08X\n", 439 device_printf(sc->sc_dev, "mmc intr idst=%08X rint=%08X mint=%08X\n",
437 idst, rint, mint); 440 idst, rint, mint);
438#endif 441#endif
439 442
440 if (idst) { 443 if (idst) {
441 sc->sc_idma_idst |= idst; 444 sc->sc_idma_idst |= idst;
442 cv_broadcast(&sc->sc_idst_cv); 445 cv_broadcast(&sc->sc_idst_cv);
443 } 446 }
444 447
445 if (rint) { 448 if (rint) {
446 sc->sc_intr_rint |= rint; 449 sc->sc_intr_rint |= rint;
447 cv_broadcast(&sc->sc_intr_cv); 450 cv_broadcast(&sc->sc_intr_cv);
448 } 451 }
449 452
450 mutex_exit(&sc->sc_intr_lock); 453 mutex_exit(&sc->sc_intr_lock);
451 454
452 return 1; 455 return 1;
453} 456}
454 457
455static int 458static int
456awin_mmc_wait_rint(struct awin_mmc_softc *sc, uint32_t mask, int timeout) 459awin_mmc_wait_rint(struct awin_mmc_softc *sc, uint32_t mask, int timeout)
457{ 460{
458 int retry; 461 int retry;
459 int error; 462 int error;
460 463
461 KASSERT(mutex_owned(&sc->sc_intr_lock)); 464 KASSERT(mutex_owned(&sc->sc_intr_lock));
462 465
463 if (sc->sc_intr_rint & mask) 466 if (sc->sc_intr_rint & mask)
464 return 0; 467 return 0;
465 468
466 retry = sc->sc_use_dma ? (timeout / hz) : 10000; 469 retry = sc->sc_use_dma ? (timeout / hz) : 10000;
467 470
468 while (retry > 0) { 471 while (retry > 0) {
469 if (sc->sc_use_dma) { 472 if (sc->sc_use_dma) {
470 error = cv_timedwait(&sc->sc_intr_cv, 473 error = cv_timedwait(&sc->sc_intr_cv,
471 &sc->sc_intr_lock, hz); 474 &sc->sc_intr_lock, hz);
472 if (error && error != EWOULDBLOCK) 475 if (error && error != EWOULDBLOCK)
473 return error; 476 return error;
474 if (sc->sc_intr_rint & mask) 477 if (sc->sc_intr_rint & mask)
475 return 0; 478 return 0;
476 } else { 479 } else {
477 sc->sc_intr_rint |= MMC_READ(sc, AWIN_MMC_RINT); 480 sc->sc_intr_rint |= MMC_READ(sc, AWIN_MMC_RINT);
478 if (sc->sc_intr_rint & mask) 481 if (sc->sc_intr_rint & mask)
479 return 0; 482 return 0;
480 delay(1000); 483 delay(1000);
481 } 484 }
482 --retry; 485 --retry;
483 } 486 }
484 487
485 return ETIMEDOUT; 488 return ETIMEDOUT;
486} 489}
487 490
488static void 491static void
489awin_mmc_led(struct awin_mmc_softc *sc, int on) 492awin_mmc_led(struct awin_mmc_softc *sc, int on)
490{ 493{
491 if (!sc->sc_has_gpio_led) 494 if (!sc->sc_has_gpio_led)
492 return; 495 return;
493 awin_gpio_pindata_write(&sc->sc_gpio_led, on); 496 awin_gpio_pindata_write(&sc->sc_gpio_led, on);
494} 497}
495 498
496static int 499static int
497awin_mmc_host_reset(sdmmc_chipset_handle_t sch) 500awin_mmc_host_reset(sdmmc_chipset_handle_t sch)
498{ 501{
499 struct awin_mmc_softc *sc = sch; 502 struct awin_mmc_softc *sc = sch;
500 int retry = 1000; 503 int retry = 1000;
501 504
502#ifdef AWIN_MMC_DEBUG 505#ifdef AWIN_MMC_DEBUG
503 aprint_normal_dev(sc->sc_dev, "host reset\n"); 506 aprint_normal_dev(sc->sc_dev, "host reset\n");
504#endif 507#endif
505 508
506 if (awin_chip_id() == AWIN_CHIP_ID_A80) { 509 if (awin_chip_id() == AWIN_CHIP_ID_A80) {
507 if (sc->sc_mmc_port == 2 || sc->sc_mmc_port == 3) { 510 if (sc->sc_mmc_port == 2 || sc->sc_mmc_port == 3) {
508 MMC_WRITE(sc, AWIN_MMC_HWRST, 0); 511 MMC_WRITE(sc, AWIN_MMC_HWRST, 0);
509 delay(10); 512 delay(10);
510 MMC_WRITE(sc, AWIN_MMC_HWRST, 1); 513 MMC_WRITE(sc, AWIN_MMC_HWRST, 1);
511 delay(300); 514 delay(300);
512 } 515 }
513 } 516 }
514 517
515 MMC_WRITE(sc, AWIN_MMC_GCTRL, 518 MMC_WRITE(sc, AWIN_MMC_GCTRL,
516 MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_RESET); 519 MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_RESET);
517 while (--retry > 0) { 520 while (--retry > 0) {
518 if (!(MMC_READ(sc, AWIN_MMC_GCTRL) & AWIN_MMC_GCTRL_RESET)) 521 if (!(MMC_READ(sc, AWIN_MMC_GCTRL) & AWIN_MMC_GCTRL_RESET))
519 break; 522 break;
520 delay(100); 523 delay(100);
521 } 524 }
522 525
523 MMC_WRITE(sc, AWIN_MMC_TIMEOUT, 0xffffffff); 526 MMC_WRITE(sc, AWIN_MMC_TIMEOUT, 0xffffffff);
524 527
525 MMC_WRITE(sc, AWIN_MMC_IMASK, 528 MMC_WRITE(sc, AWIN_MMC_IMASK,
526 AWIN_MMC_INT_CMD_DONE | AWIN_MMC_INT_ERROR | 529 AWIN_MMC_INT_CMD_DONE | AWIN_MMC_INT_ERROR |
527 AWIN_MMC_INT_DATA_OVER | AWIN_MMC_INT_AUTO_CMD_DONE); 530 AWIN_MMC_INT_DATA_OVER | AWIN_MMC_INT_AUTO_CMD_DONE);
528 531
529 MMC_WRITE(sc, AWIN_MMC_GCTRL, 532 MMC_WRITE(sc, AWIN_MMC_GCTRL,
530 MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_INTEN); 533 MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_INTEN);
531 534
532 535
533 return 0; 536 return 0;
534} 537}
535 538
536static uint32_t 539static uint32_t
537awin_mmc_host_ocr(sdmmc_chipset_handle_t sch) 540awin_mmc_host_ocr(sdmmc_chipset_handle_t sch)
538{ 541{
539 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS; 542 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
540} 543}
541 544
542static int 545static int
543awin_mmc_host_maxblklen(sdmmc_chipset_handle_t sch) 546awin_mmc_host_maxblklen(sdmmc_chipset_handle_t sch)
544{ 547{
545 return 8192; 548 return 8192;
546} 549}
547 550
548static int 551static int
549awin_mmc_card_detect(sdmmc_chipset_handle_t sch) 552awin_mmc_card_detect(sdmmc_chipset_handle_t sch)
550{ 553{
551 struct awin_mmc_softc *sc = sch; 554 struct awin_mmc_softc *sc = sch;
552 555
553 if (sc->sc_has_gpio_detect == false) { 556 if (sc->sc_has_gpio_detect == false) {
554 return 1; /* no card detect pin, assume present */ 557 return 1; /* no card detect pin, assume present */
555 } else { 558 } else {
556 int v = 0, i; 559 int v = 0, i;
557 for (i = 0; i < 5; i++) { 560 for (i = 0; i < 5; i++) {
558 v += awin_gpio_pindata_read(&sc->sc_gpio_detect); 561 v += awin_gpio_pindata_read(&sc->sc_gpio_detect);
559 delay(1000); 562 delay(1000);
560 } 563 }
561 if (v == 5) 564 if (v == 5)
562 sc->sc_mmc_present = 0; 565 sc->sc_mmc_present = 0;
563 else if (v == 0) 566 else if (v == 0)
564 sc->sc_mmc_present = 1; 567 sc->sc_mmc_present = 1;
565 return sc->sc_mmc_present; 568 return sc->sc_mmc_present;
566 } 569 }
567} 570}
568 571
569static int 572static int
570awin_mmc_write_protect(sdmmc_chipset_handle_t sch) 573awin_mmc_write_protect(sdmmc_chipset_handle_t sch)
571{ 574{
572 struct awin_mmc_softc *sc = sch; 575 struct awin_mmc_softc *sc = sch;
573 576
574 if (sc->sc_has_gpio_wp == false) { 577 if (sc->sc_has_gpio_wp == false) {
575 return 0; /* no write protect pin, assume rw */ 578 return 0; /* no write protect pin, assume rw */
576 } else { 579 } else {
577 return awin_gpio_pindata_read(&sc->sc_gpio_wp); 580 return awin_gpio_pindata_read(&sc->sc_gpio_wp);
578 } 581 }
579} 582}
580 583
581static int 584static int
582awin_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 585awin_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
583{ 586{
584 return 0; 587 return 0;
585} 588}
586 589
587static int 590static int
588awin_mmc_update_clock(struct awin_mmc_softc *sc) 591awin_mmc_update_clock(struct awin_mmc_softc *sc)
589{ 592{
590 uint32_t cmd; 593 uint32_t cmd;
591 int retry; 594 int retry;
592 595
593#ifdef AWIN_MMC_DEBUG 596#ifdef AWIN_MMC_DEBUG
594 aprint_normal_dev(sc->sc_dev, "update clock\n"); 597 aprint_normal_dev(sc->sc_dev, "update clock\n");
595#endif 598#endif
596 599
597 cmd = AWIN_MMC_CMD_START | 600 cmd = AWIN_MMC_CMD_START |
598 AWIN_MMC_CMD_UPCLK_ONLY | 601 AWIN_MMC_CMD_UPCLK_ONLY |
599 AWIN_MMC_CMD_WAIT_PRE_OVER; 602 AWIN_MMC_CMD_WAIT_PRE_OVER;
600 MMC_WRITE(sc, AWIN_MMC_CMD, cmd); 603 MMC_WRITE(sc, AWIN_MMC_CMD, cmd);
601 retry = 0xfffff; 604 retry = 0xfffff;
602 while (--retry > 0) { 605 while (--retry > 0) {
603 if (!(MMC_READ(sc, AWIN_MMC_CMD) & AWIN_MMC_CMD_START)) 606 if (!(MMC_READ(sc, AWIN_MMC_CMD) & AWIN_MMC_CMD_START))
604 break; 607 break;
605 delay(10); 608 delay(10);
606 } 609 }
607 610
608 if (retry == 0) { 611 if (retry == 0) {
609 aprint_error_dev(sc->sc_dev, "timeout updating clock\n"); 612 aprint_error_dev(sc->sc_dev, "timeout updating clock\n");
610#ifdef AWIN_MMC_DEBUG 613#ifdef AWIN_MMC_DEBUG
611 device_printf(sc->sc_dev, "GCTRL: 0x%08x\n", 614 device_printf(sc->sc_dev, "GCTRL: 0x%08x\n",
612 MMC_READ(sc, AWIN_MMC_GCTRL)); 615 MMC_READ(sc, AWIN_MMC_GCTRL));
613 device_printf(sc->sc_dev, "CLKCR: 0x%08x\n", 616 device_printf(sc->sc_dev, "CLKCR: 0x%08x\n",
614 MMC_READ(sc, AWIN_MMC_CLKCR)); 617 MMC_READ(sc, AWIN_MMC_CLKCR));
615 device_printf(sc->sc_dev, "TIMEOUT: 0x%08x\n", 618 device_printf(sc->sc_dev, "TIMEOUT: 0x%08x\n",
616 MMC_READ(sc, AWIN_MMC_TIMEOUT)); 619 MMC_READ(sc, AWIN_MMC_TIMEOUT));
617 device_printf(sc->sc_dev, "WIDTH: 0x%08x\n", 620 device_printf(sc->sc_dev, "WIDTH: 0x%08x\n",
618 MMC_READ(sc, AWIN_MMC_WIDTH)); 621 MMC_READ(sc, AWIN_MMC_WIDTH));
619 device_printf(sc->sc_dev, "CMD: 0x%08x\n", 622 device_printf(sc->sc_dev, "CMD: 0x%08x\n",
620 MMC_READ(sc, AWIN_MMC_CMD)); 623 MMC_READ(sc, AWIN_MMC_CMD));
621 device_printf(sc->sc_dev, "MINT: 0x%08x\n", 624 device_printf(sc->sc_dev, "MINT: 0x%08x\n",
622 MMC_READ(sc, AWIN_MMC_MINT)); 625 MMC_READ(sc, AWIN_MMC_MINT));
623 device_printf(sc->sc_dev, "RINT: 0x%08x\n", 626 device_printf(sc->sc_dev, "RINT: 0x%08x\n",
624 MMC_READ(sc, AWIN_MMC_RINT)); 627 MMC_READ(sc, AWIN_MMC_RINT));
625 device_printf(sc->sc_dev, "STATUS: 0x%08x\n", 628 device_printf(sc->sc_dev, "STATUS: 0x%08x\n",
626 MMC_READ(sc, AWIN_MMC_STATUS)); 629 MMC_READ(sc, AWIN_MMC_STATUS));
627#endif 630#endif
628 return ETIMEDOUT; 631 return ETIMEDOUT;
629 } 632 }
630 633
631 return 0; 634 return 0;
632} 635}
633 636
634static int 637static int
635awin_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq) 638awin_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
636{ 639{
637 struct awin_mmc_softc *sc = sch; 640 struct awin_mmc_softc *sc = sch;
638 uint32_t clkcr; 641 uint32_t clkcr;
639 642
640 clkcr = MMC_READ(sc, AWIN_MMC_CLKCR); 643 clkcr = MMC_READ(sc, AWIN_MMC_CLKCR);
641 if (clkcr & AWIN_MMC_CLKCR_CARDCLKON) { 644 if (clkcr & AWIN_MMC_CLKCR_CARDCLKON) {
642 clkcr &= ~AWIN_MMC_CLKCR_CARDCLKON; 645 clkcr &= ~AWIN_MMC_CLKCR_CARDCLKON;
643 MMC_WRITE(sc, AWIN_MMC_CLKCR, clkcr); 646 MMC_WRITE(sc, AWIN_MMC_CLKCR, clkcr);
644 if (awin_mmc_update_clock(sc) != 0) 647 if (awin_mmc_update_clock(sc) != 0)
645 return 1; 648 return 1;
646 } 649 }
647 650
648 if (freq) { 651 if (freq) {
649 652
650 clkcr &= ~AWIN_MMC_CLKCR_DIV; 653 clkcr &= ~AWIN_MMC_CLKCR_DIV;
651 MMC_WRITE(sc, AWIN_MMC_CLKCR, clkcr); 654 MMC_WRITE(sc, AWIN_MMC_CLKCR, clkcr);
652 if (awin_mmc_update_clock(sc) != 0) 655 if (awin_mmc_update_clock(sc) != 0)
653 return 1; 656 return 1;
654 657
655 if (awin_mmc_set_clock(sc, freq) != 0) 658 if (awin_mmc_set_clock(sc, freq) != 0)
656 return 1; 659 return 1;
657 660
658 clkcr |= AWIN_MMC_CLKCR_CARDCLKON; 661 clkcr |= AWIN_MMC_CLKCR_CARDCLKON;
659 MMC_WRITE(sc, AWIN_MMC_CLKCR, clkcr); 662 MMC_WRITE(sc, AWIN_MMC_CLKCR, clkcr);
660 if (awin_mmc_update_clock(sc) != 0) 663 if (awin_mmc_update_clock(sc) != 0)
661 return 1; 664 return 1;
662 } 665 }
663 666
664 return 0; 667 return 0;
665} 668}
666 669
667static int 670static int
668awin_mmc_bus_width(sdmmc_chipset_handle_t sch, int width) 671awin_mmc_bus_width(sdmmc_chipset_handle_t sch, int width)
669{ 672{
670 struct awin_mmc_softc *sc = sch; 673 struct awin_mmc_softc *sc = sch;
671 674
672#ifdef AWIN_MMC_DEBUG 675#ifdef AWIN_MMC_DEBUG
673 aprint_normal_dev(sc->sc_dev, "width = %d\n", width); 676 aprint_normal_dev(sc->sc_dev, "width = %d\n", width);
674#endif 677#endif
675 678
676 switch (width) { 679 switch (width) {
677 case 1: 680 case 1:
678 MMC_WRITE(sc, AWIN_MMC_WIDTH, AWIN_MMC_WIDTH_1); 681 MMC_WRITE(sc, AWIN_MMC_WIDTH, AWIN_MMC_WIDTH_1);
679 break; 682 break;
680 case 4: 683 case 4:
681 MMC_WRITE(sc, AWIN_MMC_WIDTH, AWIN_MMC_WIDTH_4); 684 MMC_WRITE(sc, AWIN_MMC_WIDTH, AWIN_MMC_WIDTH_4);
682 break; 685 break;
683 case 8: 686 case 8:
684 MMC_WRITE(sc, AWIN_MMC_WIDTH, AWIN_MMC_WIDTH_8); 687 MMC_WRITE(sc, AWIN_MMC_WIDTH, AWIN_MMC_WIDTH_8);
685 break; 688 break;
686 default: 689 default:
687 return 1; 690 return 1;
688 } 691 }
689 692
690 sc->sc_mmc_width = width; 693 sc->sc_mmc_width = width;
691  694
692 return 0; 695 return 0;
693} 696}
694 697
695static int 698static int
696awin_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on) 699awin_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
697{ 700{
698 return -1; 701 return -1;
699} 702}
700 703
701 704
702static int 705static int
703awin_mmc_pio_wait(struct awin_mmc_softc *sc, struct sdmmc_command *cmd) 706awin_mmc_pio_wait(struct awin_mmc_softc *sc, struct sdmmc_command *cmd)
704{ 707{
705 int retry = 0xfffff; 708 int retry = 0xfffff;
706 uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ? 709 uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
707 AWIN_MMC_STATUS_FIFO_EMPTY : AWIN_MMC_STATUS_FIFO_FULL; 710 AWIN_MMC_STATUS_FIFO_EMPTY : AWIN_MMC_STATUS_FIFO_FULL;
708 711
709 while (--retry > 0) { 712 while (--retry > 0) {
710 uint32_t status = MMC_READ(sc, AWIN_MMC_STATUS); 713 uint32_t status = MMC_READ(sc, AWIN_MMC_STATUS);
711 if (!(status & bit)) 714 if (!(status & bit))
712 return 0; 715 return 0;
713 delay(10); 716 delay(10);
714 } 717 }
715 718
716 return ETIMEDOUT; 719 return ETIMEDOUT;
717} 720}
718 721
719static int 722static int
720awin_mmc_pio_transfer(struct awin_mmc_softc *sc, struct sdmmc_command *cmd) 723awin_mmc_pio_transfer(struct awin_mmc_softc *sc, struct sdmmc_command *cmd)
721{ 724{
722 uint32_t *datap = (uint32_t *)cmd->c_data; 725 uint32_t *datap = (uint32_t *)cmd->c_data;
723 int i; 726 int i;
724 727
725 for (i = 0; i < (cmd->c_resid >> 2); i++) { 728 for (i = 0; i < (cmd->c_resid >> 2); i++) {
726 if (awin_mmc_pio_wait(sc, cmd)) 729 if (awin_mmc_pio_wait(sc, cmd))
727 return ETIMEDOUT; 730 return ETIMEDOUT;
728 if (cmd->c_flags & SCF_CMD_READ) { 731 if (cmd->c_flags & SCF_CMD_READ) {
729 datap[i] = MMC_READ(sc, sc->sc_fifo_reg); 732 datap[i] = MMC_READ(sc, sc->sc_fifo_reg);
730 } else { 733 } else {
731 MMC_WRITE(sc, sc->sc_fifo_reg, datap[i]); 734 MMC_WRITE(sc, sc->sc_fifo_reg, datap[i]);
732 } 735 }
733 } 736 }
734 737
735 return 0; 738 return 0;
736} 739}
737 740
738static int 741static int
739awin_mmc_dma_prepare(struct awin_mmc_softc *sc, struct sdmmc_command *cmd) 742awin_mmc_dma_prepare(struct awin_mmc_softc *sc, struct sdmmc_command *cmd)
740{ 743{
741 struct awin_mmc_idma_descriptor *dma = sc->sc_idma_desc; 744 struct awin_mmc_idma_descriptor *dma = sc->sc_idma_desc;
742 bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr; 745 bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr;
743 bus_size_t off; 746 bus_size_t off;
744 int desc, resid, seg; 747 int desc, resid, seg;
745 uint32_t val; 748 uint32_t val;
746 749
747 desc = 0; 750 desc = 0;
748 for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) { 751 for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
749 bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr; 752 bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr;
750 bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len; 753 bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len;
751 resid = min(len, cmd->c_resid); 754 resid = min(len, cmd->c_resid);
752 off = 0; 755 off = 0;
753 while (resid > 0) { 756 while (resid > 0) {
754 if (desc == sc->sc_idma_ndesc) 757 if (desc == sc->sc_idma_ndesc)
755 break; 758 break;
756 len = min(sc->sc_idma_xferlen, resid); 759 len = min(sc->sc_idma_xferlen, resid);
757 dma[desc].dma_buf_size = htole32(len); 760 dma[desc].dma_buf_size = htole32(len);
758 dma[desc].dma_buf_addr = htole32(paddr + off); 761 dma[desc].dma_buf_addr = htole32(paddr + off);
759 dma[desc].dma_config = htole32(AWIN_MMC_IDMA_CONFIG_CH | 762 dma[desc].dma_config = htole32(AWIN_MMC_IDMA_CONFIG_CH |
760 AWIN_MMC_IDMA_CONFIG_OWN); 763 AWIN_MMC_IDMA_CONFIG_OWN);
761 cmd->c_resid -= len; 764 cmd->c_resid -= len;
762 resid -= len; 765 resid -= len;
763 off += len; 766 off += len;
764 if (desc == 0) { 767 if (desc == 0) {
765 dma[desc].dma_config |= htole32(AWIN_MMC_IDMA_CONFIG_FD); 768 dma[desc].dma_config |= htole32(AWIN_MMC_IDMA_CONFIG_FD);
766 } 769 }
767 if (cmd->c_resid == 0) { 770 if (cmd->c_resid == 0) {
768 dma[desc].dma_config |= htole32(AWIN_MMC_IDMA_CONFIG_LD); 771 dma[desc].dma_config |= htole32(AWIN_MMC_IDMA_CONFIG_LD);
769 dma[desc].dma_config |= htole32(AWIN_MMC_IDMA_CONFIG_ER); 772 dma[desc].dma_config |= htole32(AWIN_MMC_IDMA_CONFIG_ER);
770 dma[desc].dma_next = 0; 773 dma[desc].dma_next = 0;
771 } else { 774 } else {
772 dma[desc].dma_config |= 775 dma[desc].dma_config |=
773 htole32(AWIN_MMC_IDMA_CONFIG_DIC); 776 htole32(AWIN_MMC_IDMA_CONFIG_DIC);
774 dma[desc].dma_next = htole32( 777 dma[desc].dma_next = htole32(
775 desc_paddr + ((desc+1) * 778 desc_paddr + ((desc+1) *
776 sizeof(struct awin_mmc_idma_descriptor))); 779 sizeof(struct awin_mmc_idma_descriptor)));
777 } 780 }
778 ++desc; 781 ++desc;
779 } 782 }
780 } 783 }
781 if (desc == sc->sc_idma_ndesc) { 784 if (desc == sc->sc_idma_ndesc) {
782 aprint_error_dev(sc->sc_dev, 785 aprint_error_dev(sc->sc_dev,
783 "not enough descriptors for %d byte transfer!\n", 786 "not enough descriptors for %d byte transfer!\n",
784 cmd->c_datalen); 787 cmd->c_datalen);
785 return EIO; 788 return EIO;
786 } 789 }
787 790
788 bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0, 791 bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
789 sc->sc_idma_size, BUS_DMASYNC_PREWRITE); 792 sc->sc_idma_size, BUS_DMASYNC_PREWRITE);
790 793
791 sc->sc_idma_idst = 0; 794 sc->sc_idma_idst = 0;
792 795
793 val = MMC_READ(sc, AWIN_MMC_GCTRL); 796 val = MMC_READ(sc, AWIN_MMC_GCTRL);
794 val |= AWIN_MMC_GCTRL_DMAEN; 797 val |= AWIN_MMC_GCTRL_DMAEN;
795 val |= AWIN_MMC_GCTRL_INTEN; 798 val |= AWIN_MMC_GCTRL_INTEN;
796 MMC_WRITE(sc, AWIN_MMC_GCTRL, val); 799 MMC_WRITE(sc, AWIN_MMC_GCTRL, val);
797 val |= AWIN_MMC_GCTRL_DMARESET; 800 val |= AWIN_MMC_GCTRL_DMARESET;
798 MMC_WRITE(sc, AWIN_MMC_GCTRL, val); 801 MMC_WRITE(sc, AWIN_MMC_GCTRL, val);
799 MMC_WRITE(sc, AWIN_MMC_DMAC, AWIN_MMC_DMAC_SOFTRESET); 802 MMC_WRITE(sc, AWIN_MMC_DMAC, AWIN_MMC_DMAC_SOFTRESET);
800 MMC_WRITE(sc, AWIN_MMC_DMAC, 803 MMC_WRITE(sc, AWIN_MMC_DMAC,
801 AWIN_MMC_DMAC_IDMA_ON|AWIN_MMC_DMAC_FIX_BURST); 804 AWIN_MMC_DMAC_IDMA_ON|AWIN_MMC_DMAC_FIX_BURST);
802 val = MMC_READ(sc, AWIN_MMC_IDIE); 805 val = MMC_READ(sc, AWIN_MMC_IDIE);
803 val &= ~(AWIN_MMC_IDST_RECEIVE_INT|AWIN_MMC_IDST_TRANSMIT_INT); 806 val &= ~(AWIN_MMC_IDST_RECEIVE_INT|AWIN_MMC_IDST_TRANSMIT_INT);
804 if (cmd->c_flags & SCF_CMD_READ) 807 if (cmd->c_flags & SCF_CMD_READ)
805 val |= AWIN_MMC_IDST_RECEIVE_INT; 808 val |= AWIN_MMC_IDST_RECEIVE_INT;
806 else 809 else
807 val |= AWIN_MMC_IDST_TRANSMIT_INT; 810 val |= AWIN_MMC_IDST_TRANSMIT_INT;
808 MMC_WRITE(sc, AWIN_MMC_IDIE, val); 811 MMC_WRITE(sc, AWIN_MMC_IDIE, val);
809 MMC_WRITE(sc, AWIN_MMC_DLBA, desc_paddr); 812 MMC_WRITE(sc, AWIN_MMC_DLBA, desc_paddr);
810 MMC_WRITE(sc, AWIN_MMC_FTRGLEVEL, sc->sc_dma_ftrglevel); 813 MMC_WRITE(sc, AWIN_MMC_FTRGLEVEL, sc->sc_dma_ftrglevel);
811 814
812 return 0; 815 return 0;
813} 816}
814 817
815static void 818static void
816awin_mmc_dma_complete(struct awin_mmc_softc *sc) 819awin_mmc_dma_complete(struct awin_mmc_softc *sc)
817{ 820{
818 bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0, 821 bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
819 sc->sc_idma_size, BUS_DMASYNC_POSTWRITE); 822 sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
820} 823}
821 824
822static void 825static void
823awin_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 826awin_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
824{ 827{
825 struct awin_mmc_softc *sc = sch; 828 struct awin_mmc_softc *sc = sch;
826 uint32_t cmdval = AWIN_MMC_CMD_START; 829 uint32_t cmdval = AWIN_MMC_CMD_START;
827 830
828#ifdef AWIN_MMC_DEBUG 831#ifdef AWIN_MMC_DEBUG
829 aprint_normal_dev(sc->sc_dev, 832 aprint_normal_dev(sc->sc_dev,
830 "opcode %d flags 0x%x data %p datalen %d blklen %d\n", 833 "opcode %d flags 0x%x data %p datalen %d blklen %d\n",
831 cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen, 834 cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen,
832 cmd->c_blklen); 835 cmd->c_blklen);
833#endif 836#endif
834 837
835 mutex_enter(&sc->sc_intr_lock); 838 mutex_enter(&sc->sc_intr_lock);
836 839
837 if (cmd->c_opcode == 0) 840 if (cmd->c_opcode == 0)
838 cmdval |= AWIN_MMC_CMD_SEND_INIT_SEQ; 841 cmdval |= AWIN_MMC_CMD_SEND_INIT_SEQ;
839 if (cmd->c_flags & SCF_RSP_PRESENT) 842 if (cmd->c_flags & SCF_RSP_PRESENT)
840 cmdval |= AWIN_MMC_CMD_RSP_EXP; 843 cmdval |= AWIN_MMC_CMD_RSP_EXP;
841 if (cmd->c_flags & SCF_RSP_136) 844 if (cmd->c_flags & SCF_RSP_136)
842 cmdval |= AWIN_MMC_CMD_LONG_RSP; 845 cmdval |= AWIN_MMC_CMD_LONG_RSP;
843 if (cmd->c_flags & SCF_RSP_CRC) 846 if (cmd->c_flags & SCF_RSP_CRC)
844 cmdval |= AWIN_MMC_CMD_CHECK_RSP_CRC; 847 cmdval |= AWIN_MMC_CMD_CHECK_RSP_CRC;
845 848
846 if (cmd->c_datalen > 0) { 849 if (cmd->c_datalen > 0) {
847 unsigned int nblks; 850 unsigned int nblks;
848 851
849 cmdval |= AWIN_MMC_CMD_DATA_EXP | AWIN_MMC_CMD_WAIT_PRE_OVER; 852 cmdval |= AWIN_MMC_CMD_DATA_EXP | AWIN_MMC_CMD_WAIT_PRE_OVER;
850 if (!ISSET(cmd->c_flags, SCF_CMD_READ)) { 853 if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
851 cmdval |= AWIN_MMC_CMD_WRITE; 854 cmdval |= AWIN_MMC_CMD_WRITE;
852 } 855 }
853 856
854 nblks = cmd->c_datalen / cmd->c_blklen; 857 nblks = cmd->c_datalen / cmd->c_blklen;
855 if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0) 858 if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
856 ++nblks; 859 ++nblks;
857 860
858 if (nblks > 1) { 861 if (nblks > 1) {
859 cmdval |= AWIN_MMC_CMD_SEND_AUTO_STOP; 862 cmdval |= AWIN_MMC_CMD_SEND_AUTO_STOP;
860 } 863 }
861 864
862 MMC_WRITE(sc, AWIN_MMC_BLKSZ, cmd->c_blklen); 865 MMC_WRITE(sc, AWIN_MMC_BLKSZ, cmd->c_blklen);
863 MMC_WRITE(sc, AWIN_MMC_BYTECNT, nblks * cmd->c_blklen); 866 MMC_WRITE(sc, AWIN_MMC_BYTECNT, nblks * cmd->c_blklen);
864 } 867 }
865 868
866 sc->sc_intr_rint = 0; 869 sc->sc_intr_rint = 0;
867 870
868 if (awin_chip_id() == AWIN_CHIP_ID_A80) { 871 if (awin_chip_id() == AWIN_CHIP_ID_A80) {
869 MMC_WRITE(sc, AWIN_MMC_A12A, 872 MMC_WRITE(sc, AWIN_MMC_A12A,
870 (cmdval & AWIN_MMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff); 873 (cmdval & AWIN_MMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff);
871 } 874 }
872 875
873 MMC_WRITE(sc, AWIN_MMC_ARG, cmd->c_arg); 876 MMC_WRITE(sc, AWIN_MMC_ARG, cmd->c_arg);
874 877
875#ifdef AWIN_MMC_DEBUG 878#ifdef AWIN_MMC_DEBUG
876 aprint_normal_dev(sc->sc_dev, "cmdval = %08x\n", cmdval); 879 aprint_normal_dev(sc->sc_dev, "cmdval = %08x\n", cmdval);
877#endif 880#endif
878 881
879 if (cmd->c_datalen == 0) { 882 if (cmd->c_datalen == 0) {
880 MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); 883 MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode);
881 } else { 884 } else {
882 cmd->c_resid = cmd->c_datalen; 885 cmd->c_resid = cmd->c_datalen;
883 awin_mmc_led(sc, 0); 886 awin_mmc_led(sc, 0);
884 if (sc->sc_use_dma) { 887 if (sc->sc_use_dma) {
885 cmd->c_error = awin_mmc_dma_prepare(sc, cmd); 888 cmd->c_error = awin_mmc_dma_prepare(sc, cmd);
886 MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); 889 MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode);
887 if (cmd->c_error == 0) { 890 if (cmd->c_error == 0) {
888 cmd->c_error = cv_timedwait(&sc->sc_idst_cv, 891 cmd->c_error = cv_timedwait(&sc->sc_idst_cv,
889 &sc->sc_intr_lock, hz*10); 892 &sc->sc_intr_lock, hz*10);
890 } 893 }
891 awin_mmc_dma_complete(sc); 894 awin_mmc_dma_complete(sc);
892 if (sc->sc_idma_idst & AWIN_MMC_IDST_ERROR) { 895 if (sc->sc_idma_idst & AWIN_MMC_IDST_ERROR) {
893 cmd->c_error = EIO; 896 cmd->c_error = EIO;
894 } else if (!(sc->sc_idma_idst & AWIN_MMC_IDST_COMPLETE)) { 897 } else if (!(sc->sc_idma_idst & AWIN_MMC_IDST_COMPLETE)) {
895 cmd->c_error = ETIMEDOUT; 898 cmd->c_error = ETIMEDOUT;
896 } 899 }
897 } else { 900 } else {
898 mutex_exit(&sc->sc_intr_lock); 901 mutex_exit(&sc->sc_intr_lock);
899 MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode); 902 MMC_WRITE(sc, AWIN_MMC_CMD, cmdval | cmd->c_opcode);
900 cmd->c_error = awin_mmc_pio_transfer(sc, cmd); 903 cmd->c_error = awin_mmc_pio_transfer(sc, cmd);
901 mutex_enter(&sc->sc_intr_lock); 904 mutex_enter(&sc->sc_intr_lock);
902 } 905 }
903 awin_mmc_led(sc, 1); 906 awin_mmc_led(sc, 1);
904 if (cmd->c_error) { 907 if (cmd->c_error) {
905#ifdef AWIN_MMC_DEBUG 908#ifdef AWIN_MMC_DEBUG
906 aprint_error_dev(sc->sc_dev, 909 aprint_error_dev(sc->sc_dev,
907 "xfer failed, error %d\n", cmd->c_error); 910 "xfer failed, error %d\n", cmd->c_error);
908#endif 911#endif
909 goto done; 912 goto done;
910 } 913 }
911 } 914 }
912 915
913 cmd->c_error = awin_mmc_wait_rint(sc, 916 cmd->c_error = awin_mmc_wait_rint(sc,
914 AWIN_MMC_INT_ERROR|AWIN_MMC_INT_CMD_DONE, hz * 10); 917 AWIN_MMC_INT_ERROR|AWIN_MMC_INT_CMD_DONE, hz * 10);
915 if (cmd->c_error == 0 && (sc->sc_intr_rint & AWIN_MMC_INT_ERROR)) { 918 if (cmd->c_error == 0 && (sc->sc_intr_rint & AWIN_MMC_INT_ERROR)) {
916 if (sc->sc_intr_rint & AWIN_MMC_INT_RESP_TIMEOUT) { 919 if (sc->sc_intr_rint & AWIN_MMC_INT_RESP_TIMEOUT) {
917 cmd->c_error = ETIMEDOUT; 920 cmd->c_error = ETIMEDOUT;
918 } else { 921 } else {
919 cmd->c_error = EIO; 922 cmd->c_error = EIO;
920 } 923 }
921 } 924 }
922 if (cmd->c_error) { 925 if (cmd->c_error) {
923#ifdef AWIN_MMC_DEBUG 926#ifdef AWIN_MMC_DEBUG
924 aprint_error_dev(sc->sc_dev, 927 aprint_error_dev(sc->sc_dev,
925 "cmd failed, error %d\n", cmd->c_error); 928 "cmd failed, error %d\n", cmd->c_error);
926#endif 929#endif
927 goto done; 930 goto done;
928 } 931 }
929  932
930 if (cmd->c_datalen > 0) { 933 if (cmd->c_datalen > 0) {
931 cmd->c_error = awin_mmc_wait_rint(sc, 934 cmd->c_error = awin_mmc_wait_rint(sc,
932 AWIN_MMC_INT_ERROR| 935 AWIN_MMC_INT_ERROR|
933 AWIN_MMC_INT_AUTO_CMD_DONE| 936 AWIN_MMC_INT_AUTO_CMD_DONE|
934 AWIN_MMC_INT_DATA_OVER, 937 AWIN_MMC_INT_DATA_OVER,
935 hz*10); 938 hz*10);
936 if (cmd->c_error == 0 && 939 if (cmd->c_error == 0 &&
937 (sc->sc_intr_rint & AWIN_MMC_INT_ERROR)) { 940 (sc->sc_intr_rint & AWIN_MMC_INT_ERROR)) {
938 cmd->c_error = ETIMEDOUT; 941 cmd->c_error = ETIMEDOUT;
939 } 942 }
940 if (cmd->c_error) { 943 if (cmd->c_error) {
941#ifdef AWIN_MMC_DEBUG 944#ifdef AWIN_MMC_DEBUG
942 aprint_error_dev(sc->sc_dev, 945 aprint_error_dev(sc->sc_dev,
943 "data timeout, rint = %08x\n", 946 "data timeout, rint = %08x\n",
944 sc->sc_intr_rint); 947 sc->sc_intr_rint);
945#endif 948#endif
946 cmd->c_error = ETIMEDOUT; 949 cmd->c_error = ETIMEDOUT;
947 goto done; 950 goto done;
948 } 951 }
949 } 952 }
950 953
951 if (cmd->c_flags & SCF_RSP_PRESENT) { 954 if (cmd->c_flags & SCF_RSP_PRESENT) {
952 if (cmd->c_flags & SCF_RSP_136) { 955 if (cmd->c_flags & SCF_RSP_136) {
953 cmd->c_resp[0] = MMC_READ(sc, AWIN_MMC_RESP0); 956 cmd->c_resp[0] = MMC_READ(sc, AWIN_MMC_RESP0);
954 cmd->c_resp[1] = MMC_READ(sc, AWIN_MMC_RESP1); 957 cmd->c_resp[1] = MMC_READ(sc, AWIN_MMC_RESP1);
955 cmd->c_resp[2] = MMC_READ(sc, AWIN_MMC_RESP2); 958 cmd->c_resp[2] = MMC_READ(sc, AWIN_MMC_RESP2);
956 cmd->c_resp[3] = MMC_READ(sc, AWIN_MMC_RESP3); 959 cmd->c_resp[3] = MMC_READ(sc, AWIN_MMC_RESP3);
957 if (cmd->c_flags & SCF_RSP_CRC) { 960 if (cmd->c_flags & SCF_RSP_CRC) {
958 cmd->c_resp[0] = (cmd->c_resp[0] >> 8) | 961 cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
959 (cmd->c_resp[1] << 24); 962 (cmd->c_resp[1] << 24);
960 cmd->c_resp[1] = (cmd->c_resp[1] >> 8) | 963 cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
961 (cmd->c_resp[2] << 24); 964 (cmd->c_resp[2] << 24);
962 cmd->c_resp[2] = (cmd->c_resp[2] >> 8) | 965 cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
963 (cmd->c_resp[3] << 24); 966 (cmd->c_resp[3] << 24);
964 cmd->c_resp[3] = (cmd->c_resp[3] >> 8); 967 cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
965 } 968 }
966 } else { 969 } else {
967 cmd->c_resp[0] = MMC_READ(sc, AWIN_MMC_RESP0); 970 cmd->c_resp[0] = MMC_READ(sc, AWIN_MMC_RESP0);
968 } 971 }
969 } 972 }
970 973
971done: 974done:
972 cmd->c_flags |= SCF_ITSDONE; 975 cmd->c_flags |= SCF_ITSDONE;
973 mutex_exit(&sc->sc_intr_lock); 976 mutex_exit(&sc->sc_intr_lock);
974 977
975 if (cmd->c_error) { 978 if (cmd->c_error) {
976#ifdef AWIN_MMC_DEBUG 979#ifdef AWIN_MMC_DEBUG
977 aprint_error_dev(sc->sc_dev, "i/o error %d\n", cmd->c_error); 980 aprint_error_dev(sc->sc_dev, "i/o error %d\n", cmd->c_error);
978#endif 981#endif
979 MMC_WRITE(sc, AWIN_MMC_GCTRL, 982 MMC_WRITE(sc, AWIN_MMC_GCTRL,
980 MMC_READ(sc, AWIN_MMC_GCTRL) | 983 MMC_READ(sc, AWIN_MMC_GCTRL) |
981 AWIN_MMC_GCTRL_DMARESET | AWIN_MMC_GCTRL_FIFORESET); 984 AWIN_MMC_GCTRL_DMARESET | AWIN_MMC_GCTRL_FIFORESET);
982 for (int retry = 0; retry < 1000; retry++) { 985 for (int retry = 0; retry < 1000; retry++) {
983 if (!(MMC_READ(sc, AWIN_MMC_GCTRL) & AWIN_MMC_GCTRL_RESET)) 986 if (!(MMC_READ(sc, AWIN_MMC_GCTRL) & AWIN_MMC_GCTRL_RESET))
984 break; 987 break;
985 delay(10); 988 delay(10);
986 } 989 }
987 awin_mmc_update_clock(sc); 990 awin_mmc_update_clock(sc);
988 } 991 }
989 992
990 if (!sc->sc_use_dma) { 993 if (!sc->sc_use_dma) {
991 MMC_WRITE(sc, AWIN_MMC_GCTRL, 994 MMC_WRITE(sc, AWIN_MMC_GCTRL,
992 MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_FIFORESET); 995 MMC_READ(sc, AWIN_MMC_GCTRL) | AWIN_MMC_GCTRL_FIFORESET);
993 } 996 }
994} 997}
995 998
996static void 999static void
997awin_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable) 1000awin_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
998{ 1001{
999} 1002}
1000 1003
1001static void 1004static void
1002awin_mmc_card_intr_ack(sdmmc_chipset_handle_t sch) 1005awin_mmc_card_intr_ack(sdmmc_chipset_handle_t sch)
1003{ 1006{
1004} 1007}