imx23_ssp.c revision 1.2.6.4 1 1.2.6.2 tls /* $Id: imx23_ssp.c,v 1.2.6.4 2014/08/20 00:02:46 tls Exp $ */
2 1.2.6.2 tls
3 1.2.6.2 tls /*
4 1.2.6.2 tls * Copyright (c) 2012 The NetBSD Foundation, Inc.
5 1.2.6.2 tls * All rights reserved.
6 1.2.6.2 tls *
7 1.2.6.2 tls * This code is derived from software contributed to The NetBSD Foundation
8 1.2.6.2 tls * by Petri Laakso.
9 1.2.6.2 tls *
10 1.2.6.2 tls * Redistribution and use in source and binary forms, with or without
11 1.2.6.2 tls * modification, are permitted provided that the following conditions
12 1.2.6.2 tls * are met:
13 1.2.6.2 tls * 1. Redistributions of source code must retain the above copyright
14 1.2.6.2 tls * notice, this list of conditions and the following disclaimer.
15 1.2.6.2 tls * 2. Redistributions in binary form must reproduce the above copyright
16 1.2.6.2 tls * notice, this list of conditions and the following disclaimer in the
17 1.2.6.2 tls * documentation and/or other materials provided with the distribution.
18 1.2.6.2 tls *
19 1.2.6.2 tls * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.2.6.2 tls * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.2.6.2 tls * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.2.6.2 tls * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.2.6.2 tls * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.2.6.2 tls * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.2.6.2 tls * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.2.6.2 tls * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.2.6.2 tls * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.2.6.2 tls * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.2.6.2 tls * POSSIBILITY OF SUCH DAMAGE.
30 1.2.6.2 tls */
31 1.2.6.2 tls
32 1.2.6.2 tls #include <sys/param.h>
33 1.2.6.2 tls #include <sys/types.h>
34 1.2.6.2 tls #include <sys/bus.h>
35 1.2.6.2 tls #include <sys/cdefs.h>
36 1.2.6.3 tls #include <sys/condvar.h>
37 1.2.6.2 tls #include <sys/device.h>
38 1.2.6.2 tls #include <sys/errno.h>
39 1.2.6.3 tls #include <sys/mutex.h>
40 1.2.6.2 tls #include <sys/systm.h>
41 1.2.6.2 tls
42 1.2.6.3 tls #include <arm/pic/picvar.h>
43 1.2.6.3 tls
44 1.2.6.3 tls #include <arm/imx/imx23_apbdmavar.h>
45 1.2.6.3 tls #include <arm/imx/imx23_icollreg.h>
46 1.2.6.2 tls #include <arm/imx/imx23_sspreg.h>
47 1.2.6.2 tls #include <arm/imx/imx23var.h>
48 1.2.6.2 tls
49 1.2.6.2 tls #include <dev/sdmmc/sdmmcchip.h>
50 1.2.6.2 tls #include <dev/sdmmc/sdmmcreg.h>
51 1.2.6.2 tls #include <dev/sdmmc/sdmmcvar.h>
52 1.2.6.2 tls
53 1.2.6.2 tls /*
54 1.2.6.2 tls * SD/MMC host controller driver for i.MX23.
55 1.2.6.3 tls *
56 1.2.6.3 tls * TODO:
57 1.2.6.3 tls *
58 1.2.6.3 tls * - Add support for SMC_CAPS_AUTO_STOP.
59 1.2.6.4 tls * - Uset GPIO for SD card detection.
60 1.2.6.2 tls */
61 1.2.6.2 tls
62 1.2.6.3 tls #define DMA_MAXNSEGS ((MAXPHYS / PAGE_SIZE) + 1)
63 1.2.6.3 tls
64 1.2.6.3 tls typedef struct issp_softc {
65 1.2.6.2 tls device_t sc_dev;
66 1.2.6.3 tls apbdma_softc_t sc_dmac;
67 1.2.6.3 tls bus_dma_tag_t sc_dmat;
68 1.2.6.3 tls bus_dmamap_t sc_dmamp;
69 1.2.6.3 tls bus_size_t sc_chnsiz;
70 1.2.6.3 tls bus_dma_segment_t sc_ds[1];
71 1.2.6.3 tls int sc_rseg;
72 1.2.6.2 tls bus_space_handle_t sc_hdl;
73 1.2.6.3 tls bus_space_tag_t sc_iot;
74 1.2.6.2 tls device_t sc_sdmmc;
75 1.2.6.3 tls kmutex_t sc_lock;
76 1.2.6.3 tls struct kcondvar sc_intr_cv;
77 1.2.6.3 tls unsigned int dma_channel;
78 1.2.6.3 tls uint32_t sc_dma_error;
79 1.2.6.3 tls uint32_t sc_irq_error;
80 1.2.6.3 tls uint8_t sc_state;
81 1.2.6.3 tls uint8_t sc_bus_width;
82 1.2.6.3 tls } *issp_softc_t;
83 1.2.6.2 tls
84 1.2.6.2 tls static int issp_match(device_t, cfdata_t, void *);
85 1.2.6.2 tls static void issp_attach(device_t, device_t, void *);
86 1.2.6.2 tls static int issp_activate(device_t, enum devact);
87 1.2.6.2 tls
88 1.2.6.2 tls static void issp_reset(struct issp_softc *);
89 1.2.6.2 tls static void issp_init(struct issp_softc *);
90 1.2.6.3 tls static uint32_t issp_set_sck(struct issp_softc *, uint32_t);
91 1.2.6.3 tls static int issp_dma_intr(void *);
92 1.2.6.3 tls static int issp_error_intr(void *);
93 1.2.6.3 tls static void issp_ack_intr(struct issp_softc *);
94 1.2.6.3 tls static void issp_create_dma_cmd_list_multi(issp_softc_t, void *,
95 1.2.6.3 tls struct sdmmc_command *);
96 1.2.6.3 tls static void issp_create_dma_cmd_list_single(issp_softc_t, void *,
97 1.2.6.3 tls struct sdmmc_command *);
98 1.2.6.3 tls static void issp_create_dma_cmd_list(issp_softc_t, void *,
99 1.2.6.3 tls struct sdmmc_command *);
100 1.2.6.2 tls
101 1.2.6.2 tls /* sdmmc(4) driver chip function prototypes. */
102 1.2.6.2 tls static int issp_host_reset(sdmmc_chipset_handle_t);
103 1.2.6.2 tls static uint32_t issp_host_ocr(sdmmc_chipset_handle_t);
104 1.2.6.2 tls static int issp_host_maxblklen(sdmmc_chipset_handle_t);
105 1.2.6.2 tls static int issp_card_detect(sdmmc_chipset_handle_t);
106 1.2.6.2 tls static int issp_write_protect(sdmmc_chipset_handle_t);
107 1.2.6.2 tls static int issp_bus_power(sdmmc_chipset_handle_t, uint32_t);
108 1.2.6.2 tls static int issp_bus_clock(sdmmc_chipset_handle_t, int);
109 1.2.6.2 tls static int issp_bus_width(sdmmc_chipset_handle_t, int);
110 1.2.6.2 tls static int issp_bus_rod(sdmmc_chipset_handle_t, int);
111 1.2.6.2 tls static void issp_exec_command(sdmmc_chipset_handle_t,
112 1.2.6.3 tls struct sdmmc_command *);
113 1.2.6.2 tls static void issp_card_enable_intr(sdmmc_chipset_handle_t, int);
114 1.2.6.2 tls static void issp_card_intr_ack(sdmmc_chipset_handle_t);
115 1.2.6.2 tls
116 1.2.6.2 tls static struct sdmmc_chip_functions issp_functions = {
117 1.2.6.2 tls .host_reset = issp_host_reset,
118 1.2.6.2 tls .host_ocr = issp_host_ocr,
119 1.2.6.2 tls .host_maxblklen = issp_host_maxblklen,
120 1.2.6.2 tls .card_detect = issp_card_detect,
121 1.2.6.2 tls .write_protect = issp_write_protect,
122 1.2.6.2 tls .bus_power = issp_bus_power,
123 1.2.6.2 tls .bus_clock = issp_bus_clock,
124 1.2.6.2 tls .bus_width = issp_bus_width,
125 1.2.6.2 tls .bus_rod = issp_bus_rod,
126 1.2.6.2 tls .exec_command = issp_exec_command,
127 1.2.6.2 tls .card_enable_intr = issp_card_enable_intr,
128 1.2.6.2 tls .card_intr_ack = issp_card_intr_ack
129 1.2.6.2 tls };
130 1.2.6.2 tls
131 1.2.6.2 tls CFATTACH_DECL3_NEW(ssp,
132 1.2.6.2 tls sizeof(struct issp_softc),
133 1.2.6.2 tls issp_match,
134 1.2.6.2 tls issp_attach,
135 1.2.6.2 tls NULL,
136 1.2.6.2 tls issp_activate,
137 1.2.6.2 tls NULL,
138 1.2.6.2 tls NULL,
139 1.2.6.3 tls 0
140 1.2.6.3 tls );
141 1.2.6.2 tls
142 1.2.6.2 tls #define SSP_SOFT_RST_LOOP 455 /* At least 1 us ... */
143 1.2.6.2 tls
144 1.2.6.2 tls #define SSP_RD(sc, reg) \
145 1.2.6.2 tls bus_space_read_4(sc->sc_iot, sc->sc_hdl, (reg))
146 1.2.6.2 tls #define SSP_WR(sc, reg, val) \
147 1.2.6.2 tls bus_space_write_4(sc->sc_iot, sc->sc_hdl, (reg), (val))
148 1.2.6.2 tls
149 1.2.6.4 tls #define SSP_CLK 160000000 /* CLK_SSP from PLL in Hz */
150 1.2.6.2 tls #define SSP_CLK_MIN 400 /* 400 kHz */
151 1.2.6.2 tls #define SSP_CLK_MAX 48000 /* 48 MHz */
152 1.2.6.2 tls
153 1.2.6.3 tls /* DATA_TIMEOUT is calculated as: * (1 / SSP_CLK) * (DATA_TIMEOUT * 4096) */
154 1.2.6.4 tls #define DATA_TIMEOUT 0x4240
155 1.2.6.2 tls
156 1.2.6.2 tls #define BUS_WIDTH_1_BIT 0x0
157 1.2.6.2 tls #define BUS_WIDTH_4_BIT 0x1
158 1.2.6.2 tls #define BUS_WIDTH_8_BIT 0x2
159 1.2.6.2 tls
160 1.2.6.3 tls #define SSP1_ATTACHED 1
161 1.2.6.3 tls #define SSP2_ATTACHED 2
162 1.2.6.3 tls
163 1.2.6.3 tls /* Flags for sc_state. */
164 1.2.6.3 tls #define SSP_STATE_IDLE 0
165 1.2.6.3 tls #define SSP_STATE_DMA 1
166 1.2.6.3 tls
167 1.2.6.3 tls #define PIO_WORD_CTRL0 0
168 1.2.6.3 tls #define PIO_WORD_CMD0 1
169 1.2.6.3 tls #define PIO_WORD_CMD1 2
170 1.2.6.3 tls
171 1.2.6.3 tls #define HW_SSP_CTRL1_IRQ_MASK ( \
172 1.2.6.3 tls HW_SSP_CTRL1_SDIO_IRQ | \
173 1.2.6.3 tls HW_SSP_CTRL1_RESP_ERR_IRQ | \
174 1.2.6.3 tls HW_SSP_CTRL1_RESP_TIMEOUT_IRQ | \
175 1.2.6.3 tls HW_SSP_CTRL1_DATA_TIMEOUT_IRQ | \
176 1.2.6.3 tls HW_SSP_CTRL1_DATA_CRC_IRQ | \
177 1.2.6.3 tls HW_SSP_CTRL1_FIFO_UNDERRUN_IRQ | \
178 1.2.6.3 tls HW_SSP_CTRL1_RECV_TIMEOUT_IRQ | \
179 1.2.6.3 tls HW_SSP_CTRL1_FIFO_OVERRUN_IRQ)
180 1.2.6.3 tls
181 1.2.6.3 tls /* SSP does not support over 64k transfer size. */
182 1.2.6.3 tls #define MAX_TRANSFER_SIZE 65536
183 1.2.6.3 tls
184 1.2.6.2 tls static int
185 1.2.6.2 tls issp_match(device_t parent, cfdata_t match, void *aux)
186 1.2.6.2 tls {
187 1.2.6.2 tls struct apb_attach_args *aa = aux;
188 1.2.6.2 tls
189 1.2.6.2 tls if ((aa->aa_addr == HW_SSP1_BASE) && (aa->aa_size == HW_SSP1_SIZE))
190 1.2.6.2 tls return 1;
191 1.2.6.2 tls
192 1.2.6.2 tls if ((aa->aa_addr == HW_SSP2_BASE) && (aa->aa_size == HW_SSP2_SIZE))
193 1.2.6.2 tls return 1;
194 1.2.6.2 tls
195 1.2.6.2 tls return 0;
196 1.2.6.2 tls }
197 1.2.6.2 tls
198 1.2.6.2 tls static void
199 1.2.6.2 tls issp_attach(device_t parent, device_t self, void *aux)
200 1.2.6.2 tls {
201 1.2.6.2 tls struct issp_softc *sc = device_private(self);
202 1.2.6.2 tls struct apb_softc *sc_parent = device_private(parent);
203 1.2.6.2 tls struct apb_attach_args *aa = aux;
204 1.2.6.2 tls struct sdmmcbus_attach_args saa;
205 1.2.6.3 tls static int ssp_attached = 0;
206 1.2.6.3 tls int error;
207 1.2.6.3 tls void *intr;
208 1.2.6.2 tls
209 1.2.6.2 tls sc->sc_dev = self;
210 1.2.6.2 tls sc->sc_iot = aa->aa_iot;
211 1.2.6.3 tls sc->sc_dmat = aa->aa_dmat;
212 1.2.6.3 tls
213 1.2.6.3 tls /* Test if device instance is already attached. */
214 1.2.6.3 tls if (aa->aa_addr == HW_SSP1_BASE && ISSET(ssp_attached, SSP1_ATTACHED)) {
215 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "SSP1 already attached\n");
216 1.2.6.3 tls return;
217 1.2.6.3 tls }
218 1.2.6.3 tls if (aa->aa_addr == HW_SSP2_BASE && ISSET(ssp_attached, SSP2_ATTACHED)) {
219 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "SSP2 already attached\n");
220 1.2.6.3 tls return;
221 1.2.6.3 tls }
222 1.2.6.3 tls
223 1.2.6.3 tls if (aa->aa_addr == HW_SSP1_BASE) {
224 1.2.6.3 tls sc->dma_channel = APBH_DMA_CHANNEL_SSP1;
225 1.2.6.3 tls }
226 1.2.6.3 tls if (aa->aa_addr == HW_SSP2_BASE) {
227 1.2.6.3 tls sc->dma_channel = APBH_DMA_CHANNEL_SSP2;
228 1.2.6.3 tls }
229 1.2.6.3 tls
230 1.2.6.3 tls /* This driver requires DMA functionality from the bus.
231 1.2.6.3 tls * Parent bus passes handle to the DMA controller instance. */
232 1.2.6.3 tls if (sc_parent->dmac == NULL) {
233 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "DMA functionality missing\n");
234 1.2.6.3 tls return;
235 1.2.6.3 tls }
236 1.2.6.3 tls sc->sc_dmac = device_private(sc_parent->dmac);
237 1.2.6.3 tls
238 1.2.6.3 tls /* Initialize lock. */
239 1.2.6.3 tls mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SDMMC);
240 1.2.6.3 tls
241 1.2.6.3 tls /* Condvar to wait interrupt complete. */
242 1.2.6.3 tls cv_init(&sc->sc_intr_cv, "ssp_intr");
243 1.2.6.2 tls
244 1.2.6.3 tls /* Establish interrupt handlers for SSP errors and SSP DMA. */
245 1.2.6.3 tls if (aa->aa_addr == HW_SSP1_BASE) {
246 1.2.6.3 tls intr = intr_establish(IRQ_SSP1_DMA, IPL_SDMMC, IST_LEVEL,
247 1.2.6.3 tls issp_dma_intr, sc);
248 1.2.6.3 tls if (intr == NULL) {
249 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "Unable to establish "
250 1.2.6.3 tls "interrupt for SSP1 DMA\n");
251 1.2.6.3 tls return;
252 1.2.6.3 tls }
253 1.2.6.3 tls intr = intr_establish(IRQ_SSP1_ERROR, IPL_SDMMC, IST_LEVEL,
254 1.2.6.3 tls issp_error_intr, sc);
255 1.2.6.3 tls if (intr == NULL) {
256 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "Unable to establish "
257 1.2.6.3 tls "interrupt for SSP1 ERROR\n");
258 1.2.6.3 tls return;
259 1.2.6.3 tls }
260 1.2.6.3 tls }
261 1.2.6.3 tls
262 1.2.6.3 tls if (aa->aa_addr == HW_SSP2_BASE) {
263 1.2.6.3 tls intr = intr_establish(IRQ_SSP2_DMA, IPL_SDMMC, IST_LEVEL,
264 1.2.6.3 tls issp_dma_intr, sc);
265 1.2.6.3 tls if (intr == NULL) {
266 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "Unable to establish "
267 1.2.6.3 tls "interrupt for SSP2 DMA\n");
268 1.2.6.3 tls return;
269 1.2.6.3 tls }
270 1.2.6.3 tls intr = intr_establish(IRQ_SSP2_ERROR, IPL_SDMMC, IST_LEVEL,
271 1.2.6.3 tls issp_error_intr, sc);
272 1.2.6.3 tls if (intr == NULL) {
273 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "Unable to establish "
274 1.2.6.3 tls "interrupt for SSP2 ERROR\n");
275 1.2.6.3 tls return;
276 1.2.6.3 tls }
277 1.2.6.3 tls }
278 1.2.6.3 tls
279 1.2.6.3 tls /* Allocate DMA handle. */
280 1.2.6.3 tls error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, 1, MAXPHYS,
281 1.2.6.3 tls 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &sc->sc_dmamp);
282 1.2.6.3 tls if (error) {
283 1.2.6.3 tls aprint_error_dev(sc->sc_dev,
284 1.2.6.3 tls "Unable to allocate DMA handle\n");
285 1.2.6.3 tls return;
286 1.2.6.3 tls }
287 1.2.6.3 tls
288 1.2.6.3 tls /* Allocate memory for DMA command chain. */
289 1.2.6.3 tls sc->sc_chnsiz = sizeof(struct apbdma_command) *
290 1.2.6.3 tls (MAX_TRANSFER_SIZE / SDMMC_SECTOR_SIZE);
291 1.2.6.3 tls
292 1.2.6.3 tls error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_chnsiz, PAGE_SIZE, 0,
293 1.2.6.3 tls sc->sc_ds, 1, &sc->sc_rseg, BUS_DMA_NOWAIT);
294 1.2.6.3 tls if (error) {
295 1.2.6.3 tls aprint_error_dev(sc->sc_dev,
296 1.2.6.3 tls "Unable to allocate DMA memory\n");
297 1.2.6.3 tls return;
298 1.2.6.3 tls }
299 1.2.6.3 tls
300 1.2.6.3 tls /* Initialize DMA channel. */
301 1.2.6.3 tls apbdma_chan_init(sc->sc_dmac, sc->dma_channel);
302 1.2.6.3 tls
303 1.2.6.3 tls /* Map SSP bus space. */
304 1.2.6.3 tls if (bus_space_map(sc->sc_iot, aa->aa_addr, aa->aa_size, 0,
305 1.2.6.3 tls &sc->sc_hdl)) {
306 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "Unable to map SSP bus space\n");
307 1.2.6.2 tls return;
308 1.2.6.2 tls }
309 1.2.6.2 tls
310 1.2.6.2 tls issp_reset(sc);
311 1.2.6.2 tls issp_init(sc);
312 1.2.6.2 tls
313 1.2.6.2 tls uint32_t issp_vers = SSP_RD(sc, HW_SSP_VERSION);
314 1.2.6.2 tls aprint_normal(": SSP Block v%" __PRIuBIT ".%" __PRIuBIT "\n",
315 1.2.6.2 tls __SHIFTOUT(issp_vers, HW_SSP_VERSION_MAJOR),
316 1.2.6.2 tls __SHIFTOUT(issp_vers, HW_SSP_VERSION_MINOR));
317 1.2.6.2 tls
318 1.2.6.3 tls /* Attach sdmmc to ssp bus. */
319 1.2.6.2 tls saa.saa_busname = "sdmmc";
320 1.2.6.2 tls saa.saa_sct = &issp_functions;
321 1.2.6.2 tls saa.saa_spi_sct = NULL;
322 1.2.6.2 tls saa.saa_sch = sc;
323 1.2.6.2 tls saa.saa_dmat = aa->aa_dmat;
324 1.2.6.2 tls saa.saa_clkmin = SSP_CLK_MIN;
325 1.2.6.2 tls saa.saa_clkmax = SSP_CLK_MAX;
326 1.2.6.3 tls saa.saa_caps = SMC_CAPS_DMA | SMC_CAPS_4BIT_MODE |
327 1.2.6.3 tls SMC_CAPS_MULTI_SEG_DMA;
328 1.2.6.2 tls
329 1.2.6.2 tls sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL);
330 1.2.6.2 tls if (sc->sc_sdmmc == NULL) {
331 1.2.6.2 tls aprint_error_dev(sc->sc_dev, "unable to attach sdmmc\n");
332 1.2.6.2 tls return;
333 1.2.6.2 tls }
334 1.2.6.2 tls
335 1.2.6.3 tls /* Device instance was succesfully attached. */
336 1.2.6.3 tls if (aa->aa_addr == HW_SSP1_BASE)
337 1.2.6.3 tls ssp_attached |= SSP1_ATTACHED;
338 1.2.6.3 tls if (aa->aa_addr == HW_SSP2_BASE)
339 1.2.6.3 tls ssp_attached |= SSP2_ATTACHED;
340 1.2.6.2 tls
341 1.2.6.2 tls return;
342 1.2.6.2 tls }
343 1.2.6.2 tls
344 1.2.6.2 tls static int
345 1.2.6.2 tls issp_activate(device_t self, enum devact act)
346 1.2.6.2 tls {
347 1.2.6.2 tls return EOPNOTSUPP;
348 1.2.6.2 tls }
349 1.2.6.2 tls
350 1.2.6.2 tls /*
351 1.2.6.2 tls * sdmmc chip functions.
352 1.2.6.2 tls */
353 1.2.6.2 tls static int
354 1.2.6.2 tls issp_host_reset(sdmmc_chipset_handle_t sch)
355 1.2.6.2 tls {
356 1.2.6.2 tls struct issp_softc *sc = sch;
357 1.2.6.2 tls issp_reset(sc);
358 1.2.6.2 tls return 0;
359 1.2.6.2 tls }
360 1.2.6.2 tls
361 1.2.6.2 tls static uint32_t
362 1.2.6.2 tls issp_host_ocr(sdmmc_chipset_handle_t sch)
363 1.2.6.2 tls {
364 1.2.6.3 tls /* SSP supports at least 3.2 - 3.3v */
365 1.2.6.2 tls return MMC_OCR_3_2V_3_3V;
366 1.2.6.2 tls }
367 1.2.6.2 tls
368 1.2.6.2 tls static int
369 1.2.6.2 tls issp_host_maxblklen(sdmmc_chipset_handle_t sch)
370 1.2.6.2 tls {
371 1.2.6.2 tls return 512;
372 1.2.6.2 tls }
373 1.2.6.2 tls
374 1.2.6.2 tls /*
375 1.2.6.2 tls * Called at the beginning of sdmmc_task_thread to detect the presence
376 1.2.6.2 tls * of the SD card.
377 1.2.6.2 tls */
378 1.2.6.2 tls static int
379 1.2.6.2 tls issp_card_detect(sdmmc_chipset_handle_t sch)
380 1.2.6.2 tls {
381 1.2.6.2 tls return 1;
382 1.2.6.2 tls }
383 1.2.6.2 tls
384 1.2.6.2 tls static int
385 1.2.6.2 tls issp_write_protect(sdmmc_chipset_handle_t sch)
386 1.2.6.2 tls {
387 1.2.6.2 tls /* The device is not write protected. */
388 1.2.6.2 tls return 0;
389 1.2.6.2 tls }
390 1.2.6.2 tls
391 1.2.6.2 tls static int
392 1.2.6.2 tls issp_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
393 1.2.6.2 tls {
394 1.2.6.2 tls /* i.MX23 SSP does not support setting bus power. */
395 1.2.6.2 tls return 0;
396 1.2.6.2 tls }
397 1.2.6.2 tls
398 1.2.6.2 tls static int
399 1.2.6.2 tls issp_bus_clock(sdmmc_chipset_handle_t sch, int clock)
400 1.2.6.2 tls {
401 1.2.6.2 tls struct issp_softc *sc = sch;
402 1.2.6.2 tls uint32_t sck;
403 1.2.6.2 tls
404 1.2.6.3 tls if (clock < SSP_CLK_MIN)
405 1.2.6.3 tls sck = issp_set_sck(sc, SSP_CLK_MIN * 1000);
406 1.2.6.3 tls else
407 1.2.6.3 tls sck = issp_set_sck(sc, clock * 1000);
408 1.2.6.2 tls
409 1.2.6.3 tls /* Notify user if we didn't get the exact clock rate from SSP that was
410 1.2.6.3 tls * requested from the SDMMC subsystem. */
411 1.2.6.3 tls if (sck != clock * 1000) {
412 1.2.6.3 tls sck = sck / 1000;
413 1.2.6.3 tls if (((sck) / 1000) != 0)
414 1.2.6.3 tls aprint_normal_dev(sc->sc_dev, "bus clock @ %u.%03u "
415 1.2.6.3 tls "MHz\n", sck / 1000, sck % 1000);
416 1.2.6.3 tls else
417 1.2.6.3 tls aprint_normal_dev(sc->sc_dev, "bus clock @ %u KHz\n",
418 1.2.6.3 tls sck % 1000);
419 1.2.6.3 tls }
420 1.2.6.2 tls
421 1.2.6.2 tls return 0;
422 1.2.6.2 tls }
423 1.2.6.2 tls
424 1.2.6.2 tls static int
425 1.2.6.2 tls issp_bus_width(sdmmc_chipset_handle_t sch, int width)
426 1.2.6.2 tls {
427 1.2.6.2 tls struct issp_softc *sc = sch;
428 1.2.6.2 tls
429 1.2.6.2 tls switch(width) {
430 1.2.6.2 tls case(1):
431 1.2.6.3 tls sc->sc_bus_width = BUS_WIDTH_1_BIT;
432 1.2.6.2 tls break;
433 1.2.6.2 tls case(4):
434 1.2.6.3 tls sc->sc_bus_width = BUS_WIDTH_4_BIT;
435 1.2.6.2 tls break;
436 1.2.6.2 tls case(8):
437 1.2.6.3 tls sc->sc_bus_width = BUS_WIDTH_8_BIT;
438 1.2.6.2 tls break;
439 1.2.6.2 tls default:
440 1.2.6.2 tls return 1;
441 1.2.6.2 tls }
442 1.2.6.2 tls
443 1.2.6.2 tls return 0;
444 1.2.6.2 tls }
445 1.2.6.2 tls
446 1.2.6.2 tls static int
447 1.2.6.2 tls issp_bus_rod(sdmmc_chipset_handle_t sch, int rod)
448 1.2.6.2 tls {
449 1.2.6.2 tls /* Go to data transfer mode. */
450 1.2.6.2 tls return 0;
451 1.2.6.2 tls }
452 1.2.6.2 tls
453 1.2.6.2 tls static void
454 1.2.6.2 tls issp_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
455 1.2.6.2 tls {
456 1.2.6.3 tls issp_softc_t sc = sch;
457 1.2.6.3 tls void *dma_chain;
458 1.2.6.3 tls int error;
459 1.2.6.3 tls
460 1.2.6.3 tls /* SSP does not support over 64k transfer size. */
461 1.2.6.3 tls if (cmd->c_data != NULL && cmd->c_datalen > MAX_TRANSFER_SIZE) {
462 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "transfer size over %d: %d\n",
463 1.2.6.3 tls MAX_TRANSFER_SIZE, cmd->c_datalen);
464 1.2.6.3 tls cmd->c_error = ENODEV;
465 1.2.6.3 tls return;
466 1.2.6.3 tls }
467 1.2.6.3 tls
468 1.2.6.3 tls /* Map dma_chain to point allocated previously allocated DMA chain. */
469 1.2.6.3 tls error = bus_dmamem_map(sc->sc_dmat, sc->sc_ds, 1, sc->sc_chnsiz,
470 1.2.6.3 tls &dma_chain, BUS_DMA_NOWAIT);
471 1.2.6.3 tls if (error) {
472 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "bus_dmamem_map: %d\n", error);
473 1.2.6.3 tls cmd->c_error = error;
474 1.2.6.3 tls goto out;
475 1.2.6.3 tls }
476 1.2.6.2 tls
477 1.2.6.3 tls error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamp, dma_chain,
478 1.2.6.3 tls sc->sc_chnsiz, NULL, BUS_DMA_NOWAIT|BUS_DMA_WRITE);
479 1.2.6.3 tls if (error) {
480 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "bus_dmamap_load: %d\n", error);
481 1.2.6.3 tls cmd->c_error = error;
482 1.2.6.3 tls goto dmamem_unmap;
483 1.2.6.3 tls }
484 1.2.6.2 tls
485 1.2.6.3 tls memset(dma_chain, 0, sc->sc_chnsiz);
486 1.2.6.2 tls
487 1.2.6.3 tls /* Setup DMA command chain.*/
488 1.2.6.3 tls if (cmd->c_data != NULL && (cmd->c_datalen / cmd->c_blklen) > 1) {
489 1.2.6.3 tls /* Multi block transfer. */
490 1.2.6.3 tls issp_create_dma_cmd_list_multi(sc, dma_chain, cmd);
491 1.2.6.3 tls } else if (cmd->c_data != NULL && cmd->c_datalen) {
492 1.2.6.3 tls /* Single block transfer. */
493 1.2.6.3 tls issp_create_dma_cmd_list_single(sc, dma_chain, cmd);
494 1.2.6.3 tls } else {
495 1.2.6.3 tls /* Only command, no data. */
496 1.2.6.3 tls issp_create_dma_cmd_list(sc, dma_chain, cmd);
497 1.2.6.2 tls }
498 1.2.6.2 tls
499 1.2.6.3 tls /* Tell DMA controller where it can find just initialized DMA chain. */
500 1.2.6.3 tls apbdma_chan_set_chain(sc->sc_dmac, sc->dma_channel, sc->sc_dmamp);
501 1.2.6.2 tls
502 1.2.6.3 tls /* Synchronize command chain before DMA controller accesses it. */
503 1.2.6.3 tls bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, 0, sc->sc_chnsiz,
504 1.2.6.3 tls BUS_DMASYNC_PREWRITE);
505 1.2.6.2 tls
506 1.2.6.3 tls sc->sc_state = SSP_STATE_DMA;
507 1.2.6.3 tls sc->sc_irq_error = 0;
508 1.2.6.3 tls sc->sc_dma_error = 0;
509 1.2.6.3 tls cmd->c_error = 0;
510 1.2.6.2 tls
511 1.2.6.3 tls mutex_enter(&sc->sc_lock);
512 1.2.6.2 tls
513 1.2.6.3 tls /* Run DMA command chain. */
514 1.2.6.3 tls apbdma_run(sc->sc_dmac, sc->dma_channel);
515 1.2.6.2 tls
516 1.2.6.3 tls /* Wait DMA to complete. */
517 1.2.6.3 tls while (sc->sc_state == SSP_STATE_DMA)
518 1.2.6.3 tls cv_wait(&sc->sc_intr_cv, &sc->sc_lock);
519 1.2.6.3 tls
520 1.2.6.3 tls mutex_exit(&sc->sc_lock);
521 1.2.6.3 tls
522 1.2.6.3 tls bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamp, 0, sc->sc_chnsiz,
523 1.2.6.3 tls BUS_DMASYNC_POSTWRITE);
524 1.2.6.3 tls
525 1.2.6.3 tls if (sc->sc_dma_error) {
526 1.2.6.3 tls if (sc->sc_dma_error == DMA_IRQ_TERM) {
527 1.2.6.3 tls apbdma_chan_reset(sc->sc_dmac, sc->dma_channel);
528 1.2.6.3 tls cmd->c_error = sc->sc_dma_error;
529 1.2.6.2 tls }
530 1.2.6.3 tls else if (sc->sc_dma_error == DMA_IRQ_BUS_ERROR) {
531 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "DMA_IRQ_BUS_ERROR: %d\n",
532 1.2.6.3 tls sc->sc_irq_error);
533 1.2.6.3 tls cmd->c_error = sc->sc_dma_error;
534 1.2.6.2 tls }
535 1.2.6.2 tls }
536 1.2.6.2 tls
537 1.2.6.3 tls if (sc->sc_irq_error) {
538 1.2.6.3 tls /* Do not log RESP_TIMEOUT_IRQ error if bus width is 0 as it is
539 1.2.6.3 tls * expected during SD card initialization phase. */
540 1.2.6.3 tls if (sc->sc_bus_width) {
541 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "SSP_ERROR_IRQ: %d\n",
542 1.2.6.3 tls sc->sc_irq_error);
543 1.2.6.3 tls }
544 1.2.6.3 tls else if(!(sc->sc_irq_error & HW_SSP_CTRL1_RESP_TIMEOUT_IRQ)) {
545 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "SSP_ERROR_IRQ: %d\n",
546 1.2.6.3 tls sc->sc_irq_error);
547 1.2.6.3 tls }
548 1.2.6.2 tls
549 1.2.6.3 tls /* Shift unsigned error code so it fits nicely to signed int. */
550 1.2.6.3 tls cmd->c_error = sc->sc_irq_error >> 8;
551 1.2.6.3 tls }
552 1.2.6.2 tls
553 1.2.6.3 tls /* Check reponse from the card if such was requested. */
554 1.2.6.2 tls if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
555 1.2.6.2 tls cmd->c_resp[0] = SSP_RD(sc, HW_SSP_SDRESP0);
556 1.2.6.2 tls if (ISSET(cmd->c_flags, SCF_RSP_136)) {
557 1.2.6.2 tls cmd->c_resp[1] = SSP_RD(sc, HW_SSP_SDRESP1);
558 1.2.6.2 tls cmd->c_resp[2] = SSP_RD(sc, HW_SSP_SDRESP2);
559 1.2.6.2 tls cmd->c_resp[3] = SSP_RD(sc, HW_SSP_SDRESP3);
560 1.2.6.2 tls /*
561 1.2.6.2 tls * Remove CRC7 + LSB by rotating all bits right by 8 to
562 1.2.6.2 tls * make sdmmc __bitfield() happy.
563 1.2.6.2 tls */
564 1.2.6.2 tls cmd->c_resp[0] >>= 8; /* Remove CRC7 + LSB. */
565 1.2.6.2 tls cmd->c_resp[0] |= (0x000000FF & cmd->c_resp[1]) << 24;
566 1.2.6.2 tls cmd->c_resp[1] >>= 8;
567 1.2.6.2 tls cmd->c_resp[1] |= (0x000000FF & cmd->c_resp[2]) << 24;
568 1.2.6.2 tls cmd->c_resp[2] >>= 8;
569 1.2.6.2 tls cmd->c_resp[2] |= (0x000000FF & cmd->c_resp[3]) << 24;
570 1.2.6.2 tls cmd->c_resp[3] >>= 8;
571 1.2.6.2 tls }
572 1.2.6.2 tls }
573 1.2.6.3 tls
574 1.2.6.3 tls bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamp);
575 1.2.6.3 tls dmamem_unmap:
576 1.2.6.3 tls bus_dmamem_unmap(sc->sc_dmat, dma_chain, sc->sc_chnsiz);
577 1.2.6.3 tls out:
578 1.2.6.3 tls
579 1.2.6.2 tls return;
580 1.2.6.2 tls }
581 1.2.6.2 tls
582 1.2.6.2 tls static void
583 1.2.6.2 tls issp_card_enable_intr(sdmmc_chipset_handle_t sch, int irq)
584 1.2.6.2 tls {
585 1.2.6.2 tls struct issp_softc *sc = sch;
586 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "issp_card_enable_intr not implemented\n");
587 1.2.6.2 tls return;
588 1.2.6.2 tls }
589 1.2.6.2 tls
590 1.2.6.2 tls static void
591 1.2.6.2 tls issp_card_intr_ack(sdmmc_chipset_handle_t sch)
592 1.2.6.2 tls {
593 1.2.6.2 tls struct issp_softc *sc = sch;
594 1.2.6.3 tls aprint_error_dev(sc->sc_dev, "issp_card_intr_ack not implemented\n");
595 1.2.6.2 tls return;
596 1.2.6.2 tls }
597 1.2.6.2 tls
598 1.2.6.2 tls /*
599 1.2.6.2 tls * Reset the SSP block.
600 1.2.6.2 tls *
601 1.2.6.2 tls * Inspired by i.MX23 RM "39.3.10 Correct Way to Soft Reset a Block"
602 1.2.6.2 tls */
603 1.2.6.2 tls static void
604 1.2.6.2 tls issp_reset(struct issp_softc *sc)
605 1.2.6.2 tls {
606 1.2.6.2 tls unsigned int loop;
607 1.2.6.2 tls
608 1.2.6.2 tls /* Prepare for soft-reset by making sure that SFTRST is not currently
609 1.2.6.2 tls * asserted. Also clear CLKGATE so we can wait for its assertion below.
610 1.2.6.2 tls */
611 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
612 1.2.6.2 tls
613 1.2.6.2 tls /* Wait at least a microsecond for SFTRST to deassert. */
614 1.2.6.2 tls loop = 0;
615 1.2.6.2 tls while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
616 1.2.6.2 tls (loop < SSP_SOFT_RST_LOOP))
617 1.2.6.2 tls loop++;
618 1.2.6.2 tls
619 1.2.6.2 tls /* Clear CLKGATE so we can wait for its assertion below. */
620 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
621 1.2.6.2 tls
622 1.2.6.2 tls /* Soft-reset the block. */
623 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL0_SET, HW_SSP_CTRL0_SFTRST);
624 1.2.6.2 tls
625 1.2.6.2 tls /* Wait until clock is in the gated state. */
626 1.2.6.2 tls while (!(SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE));
627 1.2.6.2 tls
628 1.2.6.2 tls /* Bring block out of reset. */
629 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_SFTRST);
630 1.2.6.2 tls
631 1.2.6.2 tls loop = 0;
632 1.2.6.2 tls while ((SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_SFTRST) ||
633 1.2.6.2 tls (loop < SSP_SOFT_RST_LOOP))
634 1.2.6.2 tls loop++;
635 1.2.6.2 tls
636 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL0_CLR, HW_SSP_CTRL0_CLKGATE);
637 1.2.6.2 tls
638 1.2.6.2 tls /* Wait until clock is in the NON-gated state. */
639 1.2.6.2 tls while (SSP_RD(sc, HW_SSP_CTRL0) & HW_SSP_CTRL0_CLKGATE);
640 1.2.6.2 tls
641 1.2.6.2 tls return;
642 1.2.6.2 tls }
643 1.2.6.2 tls
644 1.2.6.2 tls /*
645 1.2.6.2 tls * Initialize SSP controller to SD/MMC mode.
646 1.2.6.2 tls */
647 1.2.6.2 tls static void
648 1.2.6.2 tls issp_init(struct issp_softc *sc)
649 1.2.6.2 tls {
650 1.2.6.2 tls uint32_t reg;
651 1.2.6.2 tls
652 1.2.6.2 tls reg = SSP_RD(sc, HW_SSP_CTRL0);
653 1.2.6.3 tls reg |= HW_SSP_CTRL0_ENABLE;
654 1.2.6.3 tls
655 1.2.6.3 tls /* Initial data bus width is 1-bit. */
656 1.2.6.2 tls reg &= ~(HW_SSP_CTRL0_BUS_WIDTH);
657 1.2.6.2 tls reg |= __SHIFTIN(BUS_WIDTH_1_BIT, HW_SSP_CTRL0_BUS_WIDTH) |
658 1.2.6.2 tls HW_SSP_CTRL0_WAIT_FOR_IRQ | HW_SSP_CTRL0_ENABLE;
659 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL0, reg);
660 1.2.6.3 tls sc->sc_bus_width = BUS_WIDTH_1_BIT;
661 1.2.6.2 tls
662 1.2.6.2 tls /* Set data timeout. */
663 1.2.6.2 tls reg = SSP_RD(sc, HW_SSP_TIMING);
664 1.2.6.2 tls reg &= ~(HW_SSP_TIMING_TIMEOUT);
665 1.2.6.2 tls reg |= __SHIFTIN(DATA_TIMEOUT, HW_SSP_TIMING_TIMEOUT);
666 1.2.6.3 tls SSP_WR(sc, HW_SSP_TIMING, reg);
667 1.2.6.2 tls
668 1.2.6.2 tls /* Set initial clock rate to minimum. */
669 1.2.6.2 tls issp_set_sck(sc, SSP_CLK_MIN * 1000);
670 1.2.6.2 tls
671 1.2.6.2 tls reg = SSP_RD(sc, HW_SSP_CTRL1);
672 1.2.6.3 tls /* Enable all but SDIO IRQ's. */
673 1.2.6.3 tls reg |= HW_SSP_CTRL1_RESP_ERR_IRQ_EN |
674 1.2.6.3 tls HW_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
675 1.2.6.3 tls HW_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
676 1.2.6.3 tls HW_SSP_CTRL1_DATA_CRC_IRQ_EN |
677 1.2.6.3 tls HW_SSP_CTRL1_FIFO_UNDERRUN_EN |
678 1.2.6.3 tls HW_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
679 1.2.6.3 tls HW_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN;
680 1.2.6.3 tls reg |= HW_SSP_CTRL1_DMA_ENABLE;
681 1.2.6.3 tls reg |= HW_SSP_CTRL1_POLARITY;
682 1.2.6.3 tls /* Set SD/MMC mode and use use 8-bits per word. */
683 1.2.6.2 tls reg &= ~(HW_SSP_CTRL1_WORD_LENGTH | HW_SSP_CTRL1_SSP_MODE);
684 1.2.6.3 tls reg |= __SHIFTIN(0x7, HW_SSP_CTRL1_WORD_LENGTH) |
685 1.2.6.2 tls __SHIFTIN(0x3, HW_SSP_CTRL1_SSP_MODE);
686 1.2.6.2 tls SSP_WR(sc, HW_SSP_CTRL1, reg);
687 1.2.6.2 tls
688 1.2.6.2 tls return;
689 1.2.6.2 tls }
690 1.2.6.2 tls
691 1.2.6.2 tls /*
692 1.2.6.2 tls * Set SSP_SCK clock rate to the value specified in target.
693 1.2.6.2 tls *
694 1.2.6.2 tls * SSP_SCK is calculated as: SSP_CLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE))
695 1.2.6.2 tls *
696 1.2.6.3 tls * issp_set_sck finds the most suitable CLOCK_DIVIDE and CLOCK_RATE register
697 1.2.6.2 tls * values for the target clock rate by iterating through all possible register
698 1.2.6.2 tls * values.
699 1.2.6.2 tls */
700 1.2.6.2 tls static uint32_t
701 1.2.6.2 tls issp_set_sck(struct issp_softc *sc, uint32_t target)
702 1.2.6.2 tls {
703 1.2.6.2 tls uint32_t newclk, found, reg;
704 1.2.6.2 tls uint8_t div, rate, d, r;
705 1.2.6.2 tls
706 1.2.6.2 tls found = div = rate = 0;
707 1.2.6.2 tls
708 1.2.6.2 tls for (d = 2; d < 254; d++) {
709 1.2.6.2 tls for (r = 0; r < 255; r++) {
710 1.2.6.2 tls newclk = SSP_CLK / (d * (1 + r));
711 1.2.6.2 tls if (newclk == target) {
712 1.2.6.2 tls found = newclk;
713 1.2.6.2 tls div = d;
714 1.2.6.2 tls rate = r;
715 1.2.6.2 tls goto out;
716 1.2.6.2 tls }
717 1.2.6.2 tls if (newclk < target && newclk > found) {
718 1.2.6.2 tls found = newclk;
719 1.2.6.2 tls div = d;
720 1.2.6.2 tls rate = r;
721 1.2.6.2 tls }
722 1.2.6.2 tls }
723 1.2.6.2 tls }
724 1.2.6.2 tls out:
725 1.2.6.2 tls reg = SSP_RD(sc, HW_SSP_TIMING);
726 1.2.6.2 tls reg &= ~(HW_SSP_TIMING_CLOCK_DIVIDE | HW_SSP_TIMING_CLOCK_RATE);
727 1.2.6.2 tls reg |= __SHIFTIN(div, HW_SSP_TIMING_CLOCK_DIVIDE) |
728 1.2.6.2 tls __SHIFTIN(rate, HW_SSP_TIMING_CLOCK_RATE);
729 1.2.6.2 tls SSP_WR(sc, HW_SSP_TIMING, reg);
730 1.2.6.2 tls
731 1.2.6.2 tls return SSP_CLK / (div * (1 + rate));
732 1.2.6.2 tls }
733 1.2.6.3 tls
734 1.2.6.3 tls /*
735 1.2.6.3 tls * IRQ from DMA.
736 1.2.6.3 tls */
737 1.2.6.3 tls static int
738 1.2.6.3 tls issp_dma_intr(void *arg)
739 1.2.6.3 tls {
740 1.2.6.3 tls issp_softc_t sc = arg;
741 1.2.6.3 tls unsigned int dma_err;
742 1.2.6.3 tls
743 1.2.6.3 tls dma_err = apbdma_intr_status(sc->sc_dmac, sc->dma_channel);
744 1.2.6.3 tls
745 1.2.6.3 tls if (dma_err) {
746 1.2.6.3 tls apbdma_ack_error_intr(sc->sc_dmac, sc->dma_channel);
747 1.2.6.3 tls } else {
748 1.2.6.3 tls apbdma_ack_intr(sc->sc_dmac, sc->dma_channel);
749 1.2.6.3 tls }
750 1.2.6.3 tls
751 1.2.6.3 tls mutex_enter(&sc->sc_lock);
752 1.2.6.3 tls
753 1.2.6.3 tls sc->sc_dma_error = dma_err;
754 1.2.6.3 tls sc->sc_state = SSP_STATE_IDLE;
755 1.2.6.3 tls
756 1.2.6.3 tls /* Signal thread that interrupt was handled. */
757 1.2.6.3 tls cv_signal(&sc->sc_intr_cv);
758 1.2.6.3 tls
759 1.2.6.3 tls mutex_exit(&sc->sc_lock);
760 1.2.6.3 tls
761 1.2.6.3 tls /* Return 1 to acknowledge IRQ. */
762 1.2.6.3 tls return 1;
763 1.2.6.3 tls }
764 1.2.6.3 tls
765 1.2.6.3 tls /*
766 1.2.6.3 tls * IRQ from SSP block.
767 1.2.6.3 tls *
768 1.2.6.3 tls * When SSP receives IRQ it terminates ongoing DMA transfer by issuing DMATERM
769 1.2.6.3 tls * signal to DMA block.
770 1.2.6.3 tls */
771 1.2.6.3 tls static int
772 1.2.6.3 tls issp_error_intr(void *arg)
773 1.2.6.3 tls {
774 1.2.6.3 tls issp_softc_t sc = arg;
775 1.2.6.3 tls
776 1.2.6.3 tls mutex_enter(&sc->sc_lock);
777 1.2.6.3 tls
778 1.2.6.3 tls sc->sc_irq_error =
779 1.2.6.3 tls SSP_RD(sc, HW_SSP_CTRL1) & HW_SSP_CTRL1_IRQ_MASK;
780 1.2.6.3 tls
781 1.2.6.3 tls issp_ack_intr(sc);
782 1.2.6.3 tls
783 1.2.6.3 tls mutex_exit(&sc->sc_lock);
784 1.2.6.3 tls
785 1.2.6.3 tls /* Return 1 to acknowledge IRQ. */
786 1.2.6.3 tls return 1;
787 1.2.6.3 tls }
788 1.2.6.3 tls
789 1.2.6.3 tls /*
790 1.2.6.3 tls * Acknowledge SSP error IRQ.
791 1.2.6.3 tls */
792 1.2.6.3 tls static void
793 1.2.6.3 tls issp_ack_intr(struct issp_softc *sc)
794 1.2.6.3 tls {
795 1.2.6.3 tls
796 1.2.6.3 tls /* Acknowledge all IRQ's. */
797 1.2.6.3 tls SSP_WR(sc, HW_SSP_CTRL1_CLR, HW_SSP_CTRL1_IRQ_MASK);
798 1.2.6.3 tls
799 1.2.6.3 tls return;
800 1.2.6.3 tls }
801 1.2.6.3 tls
802 1.2.6.3 tls /*
803 1.2.6.3 tls * Set up multi block DMA transfer.
804 1.2.6.3 tls */
805 1.2.6.3 tls static void
806 1.2.6.3 tls issp_create_dma_cmd_list_multi(issp_softc_t sc, void *dma_chain,
807 1.2.6.3 tls struct sdmmc_command *cmd)
808 1.2.6.3 tls {
809 1.2.6.3 tls apbdma_command_t dma_cmd;
810 1.2.6.3 tls int blocks;
811 1.2.6.3 tls int nblk;
812 1.2.6.3 tls
813 1.2.6.3 tls blocks = cmd->c_datalen / cmd->c_blklen;
814 1.2.6.3 tls nblk = 0;
815 1.2.6.3 tls dma_cmd = dma_chain;
816 1.2.6.3 tls
817 1.2.6.3 tls /* HEAD */
818 1.2.6.3 tls apbdma_cmd_buf(&dma_cmd[nblk], cmd->c_blklen * nblk, cmd->c_dmamap);
819 1.2.6.3 tls apbdma_cmd_chain(&dma_cmd[nblk], &dma_cmd[nblk+1], dma_chain,
820 1.2.6.3 tls sc->sc_dmamp);
821 1.2.6.3 tls
822 1.2.6.3 tls dma_cmd[nblk].control =
823 1.2.6.3 tls __SHIFTIN(cmd->c_blklen, APBDMA_CMD_XFER_COUNT) |
824 1.2.6.3 tls __SHIFTIN(3, APBDMA_CMD_CMDPIOWORDS) | APBDMA_CMD_HALTONTERMINATE |
825 1.2.6.3 tls APBDMA_CMD_CHAIN;
826 1.2.6.3 tls
827 1.2.6.3 tls if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) {
828 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |=
829 1.2.6.3 tls HW_SSP_CTRL0_IGNORE_CRC;
830 1.2.6.3 tls }
831 1.2.6.3 tls
832 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_DATA_XFER |
833 1.2.6.3 tls __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) |
834 1.2.6.3 tls HW_SSP_CTRL0_WAIT_FOR_IRQ |
835 1.2.6.3 tls __SHIFTIN(cmd->c_datalen, HW_SSP_CTRL0_XFER_COUNT);
836 1.2.6.3 tls
837 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
838 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |=
839 1.2.6.3 tls HW_SSP_CTRL0_GET_RESP;
840 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_RSP_136)) {
841 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |=
842 1.2.6.3 tls HW_SSP_CTRL0_LONG_RESP;
843 1.2.6.3 tls }
844 1.2.6.3 tls }
845 1.2.6.3 tls
846 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_ENABLE;
847 1.2.6.3 tls
848 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CMD0] =
849 1.2.6.3 tls __SHIFTIN(ffs(cmd->c_blklen) - 1, HW_SSP_CMD0_BLOCK_SIZE) |
850 1.2.6.3 tls __SHIFTIN(blocks - 1, HW_SSP_CMD0_BLOCK_COUNT) |
851 1.2.6.3 tls __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD);
852 1.2.6.3 tls
853 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CMD1] = cmd->c_arg;
854 1.2.6.3 tls
855 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
856 1.2.6.3 tls dma_cmd[nblk].control |=
857 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_DMA_WRITE, APBDMA_CMD_COMMAND);
858 1.2.6.3 tls dma_cmd[nblk].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_READ;
859 1.2.6.3 tls } else {
860 1.2.6.3 tls dma_cmd[nblk].control |=
861 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND);
862 1.2.6.3 tls }
863 1.2.6.3 tls
864 1.2.6.3 tls nblk++;
865 1.2.6.3 tls
866 1.2.6.3 tls /* BODY: Build commands for blocks between head and tail, if any. */
867 1.2.6.3 tls for (; nblk < blocks - 1; nblk++) {
868 1.2.6.3 tls
869 1.2.6.3 tls apbdma_cmd_buf(&dma_cmd[nblk], cmd->c_blklen * nblk,
870 1.2.6.3 tls cmd->c_dmamap);
871 1.2.6.3 tls
872 1.2.6.3 tls apbdma_cmd_chain(&dma_cmd[nblk], &dma_cmd[nblk+1], dma_chain,
873 1.2.6.3 tls sc->sc_dmamp);
874 1.2.6.3 tls
875 1.2.6.3 tls dma_cmd[nblk].control =
876 1.2.6.3 tls __SHIFTIN(cmd->c_blklen, APBDMA_CMD_XFER_COUNT) |
877 1.2.6.3 tls APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_CHAIN;
878 1.2.6.3 tls
879 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
880 1.2.6.3 tls dma_cmd[nblk].control |=
881 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_DMA_WRITE,
882 1.2.6.3 tls APBDMA_CMD_COMMAND);
883 1.2.6.3 tls } else {
884 1.2.6.3 tls dma_cmd[nblk].control |=
885 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND);
886 1.2.6.3 tls }
887 1.2.6.3 tls }
888 1.2.6.3 tls
889 1.2.6.3 tls /* TAIL
890 1.2.6.3 tls *
891 1.2.6.3 tls * TODO: Send CMD12/STOP with last DMA command to support
892 1.2.6.3 tls * SMC_CAPS_AUTO_STOP.
893 1.2.6.3 tls */
894 1.2.6.3 tls apbdma_cmd_buf(&dma_cmd[nblk], cmd->c_blklen * nblk, cmd->c_dmamap);
895 1.2.6.3 tls /* next = NULL */
896 1.2.6.3 tls dma_cmd[nblk].control =
897 1.2.6.3 tls __SHIFTIN(cmd->c_blklen, APBDMA_CMD_XFER_COUNT) |
898 1.2.6.3 tls APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_WAIT4ENDCMD |
899 1.2.6.3 tls APBDMA_CMD_SEMAPHORE | APBDMA_CMD_IRQONCMPLT;
900 1.2.6.3 tls
901 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
902 1.2.6.3 tls dma_cmd[nblk].control |= __SHIFTIN(APBDMA_CMD_DMA_WRITE,
903 1.2.6.3 tls APBDMA_CMD_COMMAND);
904 1.2.6.3 tls } else {
905 1.2.6.3 tls dma_cmd[nblk].control |= __SHIFTIN(APBDMA_CMD_DMA_READ,
906 1.2.6.3 tls APBDMA_CMD_COMMAND);
907 1.2.6.3 tls }
908 1.2.6.3 tls
909 1.2.6.3 tls return;
910 1.2.6.3 tls }
911 1.2.6.3 tls
912 1.2.6.3 tls /*
913 1.2.6.3 tls * Set up single block DMA transfer.
914 1.2.6.3 tls */
915 1.2.6.3 tls static void
916 1.2.6.3 tls issp_create_dma_cmd_list_single(issp_softc_t sc, void *dma_chain,
917 1.2.6.3 tls struct sdmmc_command *cmd)
918 1.2.6.3 tls {
919 1.2.6.3 tls apbdma_command_t dma_cmd;
920 1.2.6.3 tls
921 1.2.6.3 tls dma_cmd = dma_chain;
922 1.2.6.3 tls
923 1.2.6.3 tls dma_cmd[0].control = __SHIFTIN(cmd->c_datalen, APBDMA_CMD_XFER_COUNT) |
924 1.2.6.3 tls __SHIFTIN(3, APBDMA_CMD_CMDPIOWORDS) |
925 1.2.6.3 tls APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_WAIT4ENDCMD |
926 1.2.6.3 tls APBDMA_CMD_SEMAPHORE | APBDMA_CMD_IRQONCMPLT;
927 1.2.6.3 tls
928 1.2.6.3 tls /* Transfer single block to the beginning of the DMA buffer. */
929 1.2.6.3 tls apbdma_cmd_buf(&dma_cmd[0], 0, cmd->c_dmamap);
930 1.2.6.3 tls
931 1.2.6.3 tls if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) {
932 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |=
933 1.2.6.3 tls HW_SSP_CTRL0_IGNORE_CRC;
934 1.2.6.3 tls }
935 1.2.6.3 tls
936 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |=
937 1.2.6.3 tls HW_SSP_CTRL0_DATA_XFER |
938 1.2.6.3 tls __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) |
939 1.2.6.3 tls HW_SSP_CTRL0_WAIT_FOR_IRQ |
940 1.2.6.3 tls __SHIFTIN(cmd->c_datalen, HW_SSP_CTRL0_XFER_COUNT);
941 1.2.6.3 tls
942 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
943 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_GET_RESP;
944 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_RSP_136)) {
945 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |=
946 1.2.6.3 tls HW_SSP_CTRL0_LONG_RESP;
947 1.2.6.3 tls }
948 1.2.6.3 tls }
949 1.2.6.3 tls
950 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_ENABLE;
951 1.2.6.3 tls
952 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CMD0] =
953 1.2.6.3 tls HW_SSP_CMD0_APPEND_8CYC |
954 1.2.6.3 tls __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD);
955 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CMD1] = cmd->c_arg;
956 1.2.6.3 tls
957 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
958 1.2.6.3 tls dma_cmd[0].control |=
959 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_DMA_WRITE, APBDMA_CMD_COMMAND);
960 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_READ;
961 1.2.6.3 tls } else {
962 1.2.6.3 tls dma_cmd[0].control |=
963 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_DMA_READ, APBDMA_CMD_COMMAND);
964 1.2.6.3 tls }
965 1.2.6.3 tls
966 1.2.6.3 tls return;
967 1.2.6.3 tls }
968 1.2.6.3 tls
969 1.2.6.3 tls /*
970 1.2.6.3 tls * Do DMA PIO (issue CMD). No block transfers.
971 1.2.6.3 tls */
972 1.2.6.3 tls static void
973 1.2.6.3 tls issp_create_dma_cmd_list(issp_softc_t sc, void *dma_chain,
974 1.2.6.3 tls struct sdmmc_command *cmd)
975 1.2.6.3 tls {
976 1.2.6.3 tls apbdma_command_t dma_cmd;
977 1.2.6.3 tls
978 1.2.6.3 tls dma_cmd = dma_chain;
979 1.2.6.3 tls
980 1.2.6.3 tls dma_cmd[0].control = __SHIFTIN(3, APBDMA_CMD_CMDPIOWORDS) |
981 1.2.6.3 tls APBDMA_CMD_HALTONTERMINATE | APBDMA_CMD_WAIT4ENDCMD |
982 1.2.6.3 tls APBDMA_CMD_SEMAPHORE | APBDMA_CMD_IRQONCMPLT |
983 1.2.6.3 tls __SHIFTIN(APBDMA_CMD_NO_DMA_XFER, APBDMA_CMD_COMMAND);
984 1.2.6.3 tls
985 1.2.6.3 tls if (!ISSET(cmd->c_flags, SCF_RSP_CRC)) {
986 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |=
987 1.2.6.3 tls HW_SSP_CTRL0_IGNORE_CRC;
988 1.2.6.3 tls }
989 1.2.6.3 tls
990 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |=
991 1.2.6.3 tls __SHIFTIN(sc->sc_bus_width, HW_SSP_CTRL0_BUS_WIDTH) |
992 1.2.6.3 tls HW_SSP_CTRL0_WAIT_FOR_IRQ;
993 1.2.6.3 tls
994 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
995 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_GET_RESP;
996 1.2.6.3 tls if (ISSET(cmd->c_flags, SCF_RSP_136)) {
997 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |=
998 1.2.6.3 tls HW_SSP_CTRL0_LONG_RESP;
999 1.2.6.3 tls }
1000 1.2.6.3 tls }
1001 1.2.6.3 tls
1002 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CTRL0] |= HW_SSP_CTRL0_ENABLE;
1003 1.2.6.3 tls
1004 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CMD0] =
1005 1.2.6.3 tls __SHIFTIN(cmd->c_opcode, HW_SSP_CMD0_CMD);
1006 1.2.6.3 tls dma_cmd[0].pio_words[PIO_WORD_CMD1] = cmd->c_arg;
1007 1.2.6.3 tls
1008 1.2.6.3 tls return;
1009 1.2.6.3 tls }
1010