summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_x1000/msc-x1000.c
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-02-27 22:08:58 +0000
committerAidan MacDonald <amachronic@protonmail.com>2021-03-28 00:01:37 +0000
commit3ec66893e377b088c1284d2d23adb2aeea6d7965 (patch)
treeb647717f83ad56b15dc42cfdef5d04d68cd9bd6b /firmware/target/mips/ingenic_x1000/msc-x1000.c
parent83fcbedc65f4b9ae7e491ecf6f07c0af4b245f74 (diff)
downloadrockbox-3ec66893e377b088c1284d2d23adb2aeea6d7965.tar.gz
rockbox-3ec66893e377b088c1284d2d23adb2aeea6d7965.zip
New port: FiiO M3K on bare metal
Change-Id: I7517e7d5459e129dcfc9465c6fbd708619888fbe
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/msc-x1000.c')
-rw-r--r--firmware/target/mips/ingenic_x1000/msc-x1000.c904
1 files changed, 904 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.c b/firmware/target/mips/ingenic_x1000/msc-x1000.c
new file mode 100644
index 0000000000..62aa76988c
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/msc-x1000.c
@@ -0,0 +1,904 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "system.h"
23#include "panic.h"
24#include "msc-x1000.h"
25#include "gpio-x1000.h"
26#include "irq-x1000.h"
27#include "clk-x1000.h"
28#include "x1000/msc.h"
29#include "x1000/cpm.h"
30#include <string.h>
31#include <stddef.h>
32
33/* #define LOGF_ENABLE */
34#include "logf.h"
35
36/* TODO - this needs some auditing to better handle errors
37 *
38 * There should be a clearer code path involving errors. Especially we should
39 * ensure that removing the card always resets the driver to a sane state.
40 */
41
42static const msc_config msc_configs[] = {
43#ifdef FIIO_M3K
44#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A
45#define msc0_cd_interrupt GPIOB06
46 {
47 .msc_nr = 0,
48 .msc_type = MSC_TYPE_SD,
49 .bus_width = 4,
50 .label = "microSD",
51 .cd_gpio = {GPIO_B, 1 << 6, 0},
52 },
53#else
54# error "Please add X1000 MSC config"
55#endif
56 {.msc_nr = -1},
57};
58
59static const msc_config* msc_lookup_config(int msc)
60{
61 for(int i = 0; i < MSC_COUNT; ++i)
62 if(msc_configs[i].msc_nr == msc)
63 return &msc_configs[i];
64 return NULL;
65}
66
67static msc_drv msc_drivers[MSC_COUNT];
68
69/* ---------------------------------------------------------------------------
70 * Initialization
71 */
72
73static void msc_gate_clock(int msc, bool gate)
74{
75 int bit;
76 if(msc == 0)
77 bit = BM_CPM_CLKGR_MSC0;
78 else
79 bit = BM_CPM_CLKGR_MSC1;
80
81 if(gate)
82 REG_CPM_CLKGR |= bit;
83 else
84 REG_CPM_CLKGR &= ~bit;
85}
86
87static void msc_init_one(msc_drv* d, int msc)
88{
89 /* Lookup config */
90 d->drive_nr = -1;
91 d->config = msc_lookup_config(msc);
92 if(!d->config) {
93 d->msc_nr = -1;
94 return;
95 }
96
97 /* Initialize driver state */
98 d->msc_nr = msc;
99 d->driver_flags = 0;
100 d->clk_status = 0;
101 d->cmdat_def = jz_orf(MSC_CMDAT, RTRG_V(GE32), TTRG_V(LE32));
102 d->req = NULL;
103 d->iflag_done = 0;
104 d->card_present = 1;
105 d->req_running = 0;
106 mutex_init(&d->lock);
107 semaphore_init(&d->cmd_done, 1, 0);
108
109 /* Ensure correct clock source */
110 jz_writef(CPM_MSC0CDR, CE(1), CLKDIV(0),
111 CLKSRC(MSC_CLOCK_SOURCE == X1000_CLK_MPLL ? 1 : 0));
112 while(jz_readf(CPM_MSC0CDR, BUSY));
113 jz_writef(CPM_MSC0CDR, CE(0));
114
115 /* Initialize the hardware */
116 msc_gate_clock(msc, false);
117 msc_full_reset(d);
118 system_enable_irq(msc == 0 ? IRQ_MSC0 : IRQ_MSC1);
119
120 /* Configure bus pins */
121 int port, device;
122 unsigned pins;
123 if(msc == 0) {
124 port = GPIO_A;
125 device = 1;
126 switch(d->config->bus_width) {
127 case 8: pins = 0x3ff << 16; break;
128 case 4: pins = 0x03f << 20; break;
129 case 1: pins = 0x007 << 23; break;
130 default: pins = 0; break;
131 }
132 } else {
133 port = GPIO_C;
134 device = 0;
135 switch(d->config->bus_width) {
136 case 4: pins = 0x3f; break;
137 case 1: pins = 0x07; break;
138 default: pins = 0; break;
139 }
140 }
141
142 gpio_config(port, pins, GPIO_DEVICE(device));
143
144 /* Setup the card detect IRQ */
145 if(d->config->cd_gpio.pin) {
146 port = d->config->cd_gpio.port;
147 pins = d->config->cd_gpio.pin;
148 int level = (REG_GPIO_PIN(port) & pins) ? 1 : 0;
149 if(level != d->config->cd_gpio.active_level)
150 d->card_present = 0;
151
152 gpio_config(port, pins, GPIO_IRQ_EDGE(level ? 0 : 1));
153 gpio_enable_irq(port, pins);
154 }
155}
156
157void msc_init(void)
158{
159 /* Only do this once -- each storage subsystem calls us in its init */
160 static bool done = false;
161 if(done)
162 return;
163 done = true;
164
165 /* Set up each MSC driver according to msc_configs */
166 for(int i = 0; i < MSC_COUNT; ++i)
167 msc_init_one(&msc_drivers[i], i);
168}
169
170msc_drv* msc_get(int type, int index)
171{
172 for(int i = 0, m = 0; i < MSC_COUNT; ++i) {
173 if(msc_drivers[i].config == NULL)
174 continue;
175 if(type == MSC_TYPE_ANY || msc_drivers[i].config->msc_type == type)
176 if(index == m++)
177 return &msc_drivers[i];
178 }
179
180 return NULL;
181}
182
183msc_drv* msc_get_by_drive(int drive_nr)
184{
185 for(int i = 0; i < MSC_COUNT; ++i)
186 if(msc_drivers[i].drive_nr == drive_nr)
187 return &msc_drivers[i];
188 return NULL;
189}
190
191void msc_lock(msc_drv* d)
192{
193 mutex_lock(&d->lock);
194}
195
196void msc_unlock(msc_drv* d)
197{
198 mutex_unlock(&d->lock);
199}
200
201void msc_full_reset(msc_drv* d)
202{
203 msc_lock(d);
204 msc_set_clock_mode(d, MSC_CLK_AUTOMATIC);
205 msc_set_speed(d, MSC_SPEED_INIT);
206 msc_set_width(d, 1);
207 msc_ctl_reset(d);
208 d->driver_flags = 0;
209 memset(&d->cardinfo, 0, sizeof(tCardInfo));
210 msc_unlock(d);
211}
212
213bool msc_card_detect(msc_drv* d)
214{
215 if(!d->config->cd_gpio.pin)
216 return true;
217
218 int l = REG_GPIO_PIN(d->config->cd_gpio.port) & d->config->cd_gpio.pin;
219 l = l ? 1 : 0;
220 return l == d->config->cd_gpio.active_level;
221}
222
223/* ---------------------------------------------------------------------------
224 * Controller API
225 */
226
227void msc_ctl_reset(msc_drv* d)
228{
229 /* Ingenic code suggests a reset changes clkrt */
230 int clkrt = REG_MSC_CLKRT(d->msc_nr);
231
232 /* Send reset -- bit is NOT self clearing */
233 jz_overwritef(MSC_CTRL(d->msc_nr), RESET(1));
234 udelay(100);
235 jz_writef(MSC_CTRL(d->msc_nr), RESET(0));
236
237 /* Verify reset in the status register */
238 long deadline = current_tick + HZ;
239 while(jz_readf(MSC_STAT(d->msc_nr), IS_RESETTING) &&
240 current_tick < deadline) {
241 sleep(1);
242 }
243
244 /* Ensure the clock state is as expected */
245 if(d->clk_status & MSC_CLKST_AUTO)
246 jz_writef(MSC_LPM(d->msc_nr), ENABLE(1));
247 else if(d->clk_status & MSC_CLKST_ENABLE)
248 jz_overwritef(MSC_CTRL(d->msc_nr), CLOCK_V(START));
249 else
250 jz_overwritef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP));
251
252 /* Clear and mask interrupts */
253 REG_MSC_IMASK(d->msc_nr) = 0xffffffff;
254 REG_MSC_IFLAG(d->msc_nr) = 0xffffffff;
255
256 /* Restore clkrt */
257 REG_MSC_CLKRT(d->msc_nr) = clkrt;
258}
259
260void msc_set_clock_mode(msc_drv* d, int mode)
261{
262 int cur_mode = (d->clk_status & MSC_CLKST_AUTO) ? MSC_CLK_AUTOMATIC
263 : MSC_CLK_MANUAL;
264 if(mode == cur_mode)
265 return;
266
267 d->clk_status &= ~MSC_CLKST_ENABLE;
268 if(mode == MSC_CLK_AUTOMATIC) {
269 d->clk_status |= MSC_CLKST_AUTO;
270 jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP));
271 jz_writef(MSC_LPM(d->msc_nr), ENABLE(1));
272 } else {
273 d->clk_status &= ~MSC_CLKST_AUTO;
274 jz_writef(MSC_LPM(d->msc_nr), ENABLE(0));
275 jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP));
276 }
277}
278
279void msc_enable_clock(msc_drv* d, bool enable)
280{
281 if(d->clk_status & MSC_CLKST_AUTO)
282 return;
283
284 bool is_enabled = (d->clk_status & MSC_CLKST_ENABLE);
285 if(enable == is_enabled)
286 return;
287
288 if(enable) {
289 jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(START));
290 d->clk_status |= MSC_CLKST_ENABLE;
291 } else {
292 jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP));
293 d->clk_status &= ~MSC_CLKST_ENABLE;
294 }
295}
296
297void msc_set_speed(msc_drv* d, int rate)
298{
299 /* Shut down clock while we change frequencies */
300 if(d->clk_status & MSC_CLKST_ENABLE)
301 jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(STOP));
302
303 /* Wait for clock to go idle */
304 while(jz_readf(MSC_STAT(d->msc_nr), CLOCK_EN))
305 sleep(1);
306
307 /* freq1 is output by MSCxDIV; freq2 is output by MSC_CLKRT */
308 uint32_t freq1 = rate;
309 uint32_t freq2 = rate;
310 if(freq1 < MSC_SPEED_FAST)
311 freq1 = MSC_SPEED_FAST;
312
313 /* Handle MSCxDIV */
314 uint32_t src_freq = clk_get(MSC_CLOCK_SOURCE) / 2;
315 uint32_t div = clk_calc_div(src_freq, freq1);
316 if(d->msc_nr == 0) {
317 jz_writef(CPM_MSC0CDR, CE(1), CLKDIV(div - 1));
318 while(jz_readf(CPM_MSC0CDR, BUSY));
319 jz_writef(CPM_MSC0CDR, CE(0));
320 } else {
321 jz_writef(CPM_MSC1CDR, CE(1), CLKDIV(div - 1));
322 while(jz_readf(CPM_MSC1CDR, BUSY));
323 jz_writef(CPM_MSC1CDR, CE(0));
324 }
325
326 /* Handle MSC_CLKRT */
327 uint32_t clkrt = clk_calc_shift(src_freq/div, freq2);
328 REG_MSC_CLKRT(d->msc_nr) = clkrt;
329
330 /* Handle frequency dependent timing settings
331 * TODO - these settings might be SD specific...
332 */
333 uint32_t out_freq = (src_freq/div) >> clkrt;
334 if(out_freq > MSC_SPEED_FAST) {
335 jz_writef(MSC_LPM(d->msc_nr),
336 DRV_SEL_V(RISE_EDGE_DELAY_QTR_PHASE),
337 SMP_SEL_V(RISE_EDGE_DELAYED));
338 } else {
339 jz_writef(MSC_LPM(d->msc_nr),
340 DRV_SEL_V(FALL_EDGE),
341 SMP_SEL_V(RISE_EDGE));
342 }
343
344 /* Restart clock if it was running before */
345 if(d->clk_status & MSC_CLKST_ENABLE)
346 jz_writef(MSC_CTRL(d->msc_nr), CLOCK_V(START));
347}
348
349void msc_set_width(msc_drv* d, int width)
350{
351 /* Bus width is controlled per command with MSC_CMDAT. */
352 if(width == 8)
353 jz_vwritef(d->cmdat_def, MSC_CMDAT, BUS_WIDTH_V(8BIT));
354 else if(width == 4)
355 jz_vwritef(d->cmdat_def, MSC_CMDAT, BUS_WIDTH_V(4BIT));
356 else
357 jz_vwritef(d->cmdat_def, MSC_CMDAT, BUS_WIDTH_V(1BIT));
358}
359
360/* ---------------------------------------------------------------------------
361 * Request API
362 */
363
364/* Note -- this must only be called with IRQs disabled */
365static void msc_finish_request(msc_drv* d, int status)
366{
367 REG_MSC_IMASK(d->msc_nr) = 0xffffffff;
368 REG_MSC_IFLAG(d->msc_nr) = 0xffffffff;
369 if(d->req->flags & MSC_RF_DATA)
370 jz_writef(MSC_DMAC(d->msc_nr), ENABLE(0));
371
372 d->req->status = status;
373 d->req_running = 0;
374 d->iflag_done = 0;
375 timeout_cancel(&d->cmd_tmo);
376 semaphore_release(&d->cmd_done);
377}
378
379static int msc_req_timeout(struct timeout* tmo)
380{
381 msc_drv* d = (msc_drv*)tmo->data;
382 msc_async_abort(d, MSC_REQ_LOCKUP);
383 return 0;
384}
385
386void msc_async_start(msc_drv* d, msc_req* r)
387{
388 /* Determined needed cmdat and interrupts */
389 unsigned cmdat = d->cmdat_def;
390 d->iflag_done = jz_orm(MSC_IFLAG, END_CMD_RES);
391
392 cmdat |= jz_orf(MSC_CMDAT, RESP_FMT(r->resptype & ~MSC_RESP_BUSY));
393 if(r->resptype & MSC_RESP_BUSY)
394 cmdat |= jz_orm(MSC_CMDAT, BUSY);
395
396 if(r->flags & MSC_RF_INIT)
397 cmdat |= jz_orm(MSC_CMDAT, INIT);
398
399 if(r->flags & MSC_RF_DATA) {
400 cmdat |= jz_orm(MSC_CMDAT, DATA_EN);
401 if(r->flags & MSC_RF_PROG)
402 d->iflag_done = jz_orm(MSC_IFLAG, WR_ALL_DONE);
403 else
404 d->iflag_done = jz_orm(MSC_IFLAG, DMA_DATA_DONE);
405 }
406
407 if(r->flags & MSC_RF_WRITE)
408 cmdat |= jz_orm(MSC_CMDAT, WRITE_READ);
409
410 if(r->flags & MSC_RF_AUTO_CMD12)
411 cmdat |= jz_orm(MSC_CMDAT, AUTO_CMD12);
412
413 if(r->flags & MSC_RF_ABORT)
414 cmdat |= jz_orm(MSC_CMDAT, IO_ABORT);
415
416 unsigned imask = jz_orm(MSC_IMASK,
417 CRC_RES_ERROR, CRC_READ_ERROR, CRC_WRITE_ERROR,
418 TIME_OUT_RES, TIME_OUT_READ, END_CMD_RES);
419 imask |= d->iflag_done;
420
421 /* Program the controller */
422 if(r->flags & MSC_RF_DATA) {
423 REG_MSC_NOB(d->msc_nr) = r->nr_blocks;
424 REG_MSC_BLKLEN(d->msc_nr) = r->block_len;
425 }
426
427 REG_MSC_CMD(d->msc_nr) = r->command;
428 REG_MSC_ARG(d->msc_nr) = r->argument;
429 REG_MSC_CMDAT(d->msc_nr) = cmdat;
430
431 REG_MSC_IFLAG(d->msc_nr) = imask;
432 REG_MSC_IMASK(d->msc_nr) &= ~imask;
433
434 if(r->flags & MSC_RF_DATA) {
435 d->dma_desc.nda = 0;
436 d->dma_desc.mem = PHYSADDR(r->data);
437 d->dma_desc.len = r->nr_blocks * r->block_len;
438 d->dma_desc.cmd = 2; /* ID=0, ENDI=1, LINK=0 */
439 commit_dcache_range(&d->dma_desc, sizeof(d->dma_desc));
440
441 if(r->flags & MSC_RF_WRITE)
442 commit_dcache_range(r->data, d->dma_desc.len);
443 else
444 discard_dcache_range(r->data, d->dma_desc.len);
445
446 /* TODO - should use MODE_SEL bit? what value of INCR? */
447 unsigned long addr_off = ((unsigned long)r->data) & 3;
448 jz_writef(MSC_DMAC(d->msc_nr), MODE_SEL(0), INCR(0), DMASEL(0),
449 ALIGN_EN(addr_off != 0 ? 1 : 0), ADDR_OFFSET(addr_off));
450 REG_MSC_DMANDA(d->msc_nr) = PHYSADDR(&d->dma_desc);
451 }
452
453 /* Begin processing */
454 d->req = r;
455 d->req_running = 1;
456 jz_writef(MSC_CTRL(d->msc_nr), START_OP(1));
457 if(r->flags & MSC_RF_DATA)
458 jz_writef(MSC_DMAC(d->msc_nr), ENABLE(1));
459
460 /* TODO: calculate a suitable lower value for the lockup timeout.
461 *
462 * The SD spec defines timings based on the number of blocks transferred,
463 * see sec. 4.6.2 "Read, write, and erase timeout conditions". This should
464 * reduce the long delays which happen if errors occur.
465 *
466 * Also need to check if registers MSC_RDTO / MSC_RESTO are correctly set.
467 */
468 timeout_register(&d->cmd_tmo, msc_req_timeout, 10*HZ, (intptr_t)d);
469}
470
471void msc_async_abort(msc_drv* d, int status)
472{
473 int irq = disable_irq_save();
474 if(d->req_running) {
475 logf("msc%d: async abort status:%d", d->msc_nr, status);
476 msc_finish_request(d, status);
477 }
478
479 restore_irq(irq);
480}
481
482int msc_async_wait(msc_drv* d, int timeout)
483{
484 if(semaphore_wait(&d->cmd_done, timeout) == OBJ_WAIT_TIMEDOUT)
485 return MSC_REQ_INCOMPLETE;
486
487 return d->req->status;
488}
489
490int msc_request(msc_drv* d, msc_req* r)
491{
492 msc_async_start(d, r);
493 return msc_async_wait(d, TIMEOUT_BLOCK);
494}
495
496/* ---------------------------------------------------------------------------
497 * Command response handling
498 */
499
500static void msc_read_response(msc_drv* d)
501{
502 unsigned res = REG_MSC_RES(d->msc_nr);
503 unsigned dat;
504 switch(d->req->resptype) {
505 case MSC_RESP_R1:
506 case MSC_RESP_R1B:
507 case MSC_RESP_R3:
508 case MSC_RESP_R6:
509 case MSC_RESP_R7:
510 dat = res << 24;
511 res = REG_MSC_RES(d->msc_nr);
512 dat |= res << 8;
513 res = REG_MSC_RES(d->msc_nr);
514 dat |= res & 0xff;
515 d->req->response[0] = dat;
516 break;
517
518 case MSC_RESP_R2:
519 for(int i = 0; i < 4; ++i) {
520 dat = res << 24;
521 res = REG_MSC_RES(d->msc_nr);
522 dat |= res << 8;
523 res = REG_MSC_RES(d->msc_nr);
524 dat |= res >> 8;
525 d->req->response[i] = dat;
526 }
527
528 break;
529
530 default:
531 return;
532 }
533}
534
535static int msc_check_sd_response(msc_drv* d)
536{
537 if(d->req->resptype == MSC_RESP_R1 ||
538 d->req->resptype == MSC_RESP_R1B) {
539 if(d->req->response[0] & SD_R1_CARD_ERROR) {
540 logf("msc%d: R1 card error: %08x", d->msc_nr, d->req->response[0]);
541 return MSC_REQ_CARD_ERR;
542 }
543 }
544
545 return MSC_REQ_SUCCESS;
546}
547
548static int msc_check_response(msc_drv* d)
549{
550 switch(d->config->msc_type) {
551 case MSC_TYPE_SD:
552 return msc_check_sd_response(d);
553 default:
554 /* TODO - implement msc_check_response for MMC and CE-ATA */
555 return 0;
556 }
557}
558
559/* ---------------------------------------------------------------------------
560 * Interrupt handlers
561 */
562
563static void msc_interrupt(msc_drv* d)
564{
565 const unsigned tmo_bits = jz_orm(MSC_IFLAG, TIME_OUT_READ, TIME_OUT_RES);
566 const unsigned crc_bits = jz_orm(MSC_IFLAG, CRC_RES_ERROR,
567 CRC_READ_ERROR, CRC_WRITE_ERROR);
568 const unsigned err_bits = tmo_bits | crc_bits;
569
570 unsigned iflag = REG_MSC_IFLAG(d->msc_nr) & ~REG_MSC_IMASK(d->msc_nr);
571 bool handled = false;
572
573 /* In case card was removed */
574 if(!msc_card_detect(d)) {
575 msc_finish_request(d, MSC_REQ_EXTRACTED);
576 return;
577 }
578
579 /* Check for errors */
580 if(iflag & err_bits) {
581 int st;
582 if(iflag & crc_bits)
583 st = MSC_REQ_CRC_ERR;
584 else if(iflag & tmo_bits)
585 st = MSC_REQ_TIMEOUT;
586 else
587 st = MSC_REQ_ERROR;
588
589 msc_finish_request(d, st);
590 return;
591 }
592
593 /* Read and check the command response */
594 if(iflag & BM_MSC_IFLAG_END_CMD_RES) {
595 msc_read_response(d);
596 int st = msc_check_response(d);
597 if(st == MSC_REQ_SUCCESS) {
598 jz_writef(MSC_IMASK(d->msc_nr), END_CMD_RES(1));
599 jz_overwritef(MSC_IFLAG(d->msc_nr), END_CMD_RES(1));
600 handled = true;
601 } else {
602 msc_finish_request(d, st);
603 return;
604 }
605 }
606
607 /* Check if the "done" interrupt is signaled */
608 if(iflag & d->iflag_done) {
609 /* Discard after DMA in case of hardware cache prefetching.
610 * Only needed for read operations.
611 */
612 if((d->req->flags & MSC_RF_DATA) != 0 &&
613 (d->req->flags & MSC_RF_WRITE) == 0) {
614 discard_dcache_range(d->req->data,
615 d->req->block_len * d->req->nr_blocks);
616 }
617
618 msc_finish_request(d, MSC_REQ_SUCCESS);
619 return;
620 }
621
622 if(!handled) {
623 panicf("msc%d: irq bug! iflag:%08x raw_iflag:%08lx imask:%08lx",
624 d->msc_nr, iflag, REG_MSC_IFLAG(d->msc_nr), REG_MSC_IMASK(d->msc_nr));
625 }
626}
627
628static int msc_cd_callback(struct timeout* tmo)
629{
630 msc_drv* d = (msc_drv*)tmo->data;
631
632 /* If card is still present we assume the card is properly inserted */
633 if(msc_card_detect(d)) {
634 d->card_present = 1;
635 queue_broadcast(SYS_HOTSWAP_INSERTED, d->drive_nr);
636 }
637
638 return 0;
639}
640
641static void msc_cd_interrupt(msc_drv* d)
642{
643 if(!msc_card_detect(d)) {
644 /* Immediately abort and notify when removing a card */
645 msc_async_abort(d, MSC_REQ_EXTRACTED);
646 if(d->card_present) {
647 d->card_present = 0;
648 queue_broadcast(SYS_HOTSWAP_EXTRACTED, d->drive_nr);
649 }
650 } else {
651 /* Timer to debounce input */
652 timeout_register(&d->cd_tmo, msc_cd_callback, HZ/4, (intptr_t)d);
653 }
654
655 /* Invert the IRQ */
656 REG_GPIO_PAT0(d->config->cd_gpio.port) ^= d->config->cd_gpio.pin;
657}
658
659void MSC0(void)
660{
661 msc_interrupt(&msc_drivers[0]);
662}
663
664void MSC1(void)
665{
666 msc_interrupt(&msc_drivers[1]);
667}
668
669#ifdef msc0_cd_interrupt
670void msc0_cd_interrupt(void)
671{
672 msc_cd_interrupt(&msc_drivers[0]);
673}
674#endif
675
676#ifdef msc1_cd_interrupt
677void msc1_cd_interrupt(void)
678{
679 msc_cd_interrupt(&msc_drivers[1]);
680}
681#endif
682
683/* ---------------------------------------------------------------------------
684 * SD command helpers
685 */
686
687int msc_cmd_exec(msc_drv* d, msc_req* r)
688{
689 int status = msc_request(d, r);
690 if(status == MSC_REQ_SUCCESS)
691 return status;
692 else if(status == MSC_REQ_LOCKUP || status == MSC_REQ_EXTRACTED)
693 d->driver_flags |= MSC_DF_ERRSTATE;
694 else if(r->flags & (MSC_RF_ERR_CMD12|MSC_RF_AUTO_CMD12)) {
695 /* After an error, the controller does not automatically issue CMD12,
696 * so we need to send it if it's needed, as required by the SD spec.
697 */
698 msc_req nreq = {0};
699 nreq.command = SD_STOP_TRANSMISSION;
700 nreq.resptype = MSC_RESP_R1B;
701 nreq.flags = MSC_RF_ABORT;
702 logf("msc%d: cmd%d error, sending cmd12", d->msc_nr, r->command);
703 if(msc_cmd_exec(d, &nreq))
704 d->driver_flags |= MSC_DF_ERRSTATE;
705 }
706
707 logf("msc%d: err:%d, cmd%d, arg:%x", d->msc_nr, status,
708 r->command, r->argument);
709 return status;
710}
711
712int msc_app_cmd_exec(msc_drv* d, msc_req* r)
713{
714 msc_req areq = {0};
715 areq.command = SD_APP_CMD;
716 areq.argument = d->cardinfo.rca;
717 areq.resptype = MSC_RESP_R1;
718 if(msc_cmd_exec(d, &areq))
719 return areq.status;
720
721 /* Verify that CMD55 was accepted */
722 if((areq.response[0] & (1 << 5)) == 0)
723 return MSC_REQ_ERROR;
724
725 return msc_cmd_exec(d, r);
726}
727
728int msc_cmd_go_idle_state(msc_drv* d)
729{
730 msc_req req = {0};
731 req.command = SD_GO_IDLE_STATE;
732 req.resptype = MSC_RESP_NONE;
733 req.flags = MSC_RF_INIT;
734 return msc_cmd_exec(d, &req);
735}
736
737int msc_cmd_send_if_cond(msc_drv* d)
738{
739 msc_req req = {0};
740 req.command = SD_SEND_IF_COND;
741 req.argument = 0x1aa;
742 req.resptype = MSC_RESP_R7;
743
744 /* TODO - Check if SEND_IF_COND timeout is really an error
745 * IIRC, this can occur if the card isn't HCS (old cards < 2 GiB).
746 */
747 if(msc_cmd_exec(d, &req))
748 return req.status;
749
750 /* Set HCS bit if the card responds correctly */
751 if((req.response[0] & 0xff) == 0xaa)
752 d->driver_flags |= MSC_DF_HCS_CARD;
753
754 return MSC_REQ_SUCCESS;
755}
756
757int msc_cmd_app_op_cond(msc_drv* d)
758{
759 msc_req req = {0};
760 req.command = SD_APP_OP_COND;
761 req.argument = 0x00300000; /* 3.4 - 3.6 V */
762 req.resptype = MSC_RESP_R3;
763 if(d->driver_flags & MSC_DF_HCS_CARD)
764 req.argument |= (1 << 30);
765
766 int timeout = 2 * HZ;
767 do {
768 if(msc_app_cmd_exec(d, &req))
769 return req.status;
770 if(req.response[0] & (1 << 31))
771 break;
772 sleep(1);
773 } while(--timeout > 0);
774
775 if(timeout == 0)
776 return MSC_REQ_TIMEOUT;
777
778 return MSC_REQ_SUCCESS;
779}
780
781int msc_cmd_all_send_cid(msc_drv* d)
782{
783 msc_req req = {0};
784 req.command = SD_ALL_SEND_CID;
785 req.resptype = MSC_RESP_R2;
786 if(msc_cmd_exec(d, &req))
787 return req.status;
788
789 for(int i = 0; i < 4; ++i)
790 d->cardinfo.cid[i] = req.response[i];
791
792 return MSC_REQ_SUCCESS;
793}
794
795int msc_cmd_send_rca(msc_drv* d)
796{
797 msc_req req = {0};
798 req.command = SD_SEND_RELATIVE_ADDR;
799 req.resptype = MSC_RESP_R6;
800 if(msc_cmd_exec(d, &req))
801 return req.status;
802
803 d->cardinfo.rca = req.response[0] & 0xffff0000;
804 return MSC_REQ_SUCCESS;
805}
806
807int msc_cmd_send_csd(msc_drv* d)
808{
809 msc_req req = {0};
810 req.command = SD_SEND_CSD;
811 req.argument = d->cardinfo.rca;
812 req.resptype = MSC_RESP_R2;
813 if(msc_cmd_exec(d, &req))
814 return req.status;
815
816 for(int i = 0; i < 4; ++i)
817 d->cardinfo.csd[i] = req.response[i];
818 sd_parse_csd(&d->cardinfo);
819
820 if((req.response[0] >> 30) == 1)
821 d->driver_flags |= MSC_DF_V2_CARD;
822
823 return 0;
824}
825
826int msc_cmd_select_card(msc_drv* d)
827{
828 msc_req req = {0};
829 req.command = SD_SELECT_CARD;
830 req.argument = d->cardinfo.rca;
831 req.resptype = MSC_RESP_R1B;
832 return msc_cmd_exec(d, &req);
833}
834
835int msc_cmd_set_bus_width(msc_drv* d, int width)
836{
837 /* TODO - must we check bus width is supported in the cardinfo? */
838 msc_req req = {0};
839 req.command = SD_SET_BUS_WIDTH;
840 req.resptype = MSC_RESP_R1;
841 switch(width) {
842 case 1: req.argument = 0; break;
843 case 4: req.argument = 2; break;
844 default: return MSC_REQ_ERROR;
845 }
846
847 if(msc_app_cmd_exec(d, &req))
848 return req.status;
849
850 msc_set_width(d, width);
851 return MSC_REQ_SUCCESS;
852}
853
854int msc_cmd_set_clr_card_detect(msc_drv* d, int arg)
855{
856 msc_req req = {0};
857 req.command = SD_SET_CLR_CARD_DETECT;
858 req.argument = arg;
859 req.resptype = MSC_RESP_R1;
860 return msc_app_cmd_exec(d, &req);
861}
862
863int msc_cmd_switch_freq(msc_drv* d)
864{
865 /* If card doesn't support High Speed, we don't need to send a command */
866 if((d->driver_flags & MSC_DF_V2_CARD) == 0) {
867 msc_set_speed(d, MSC_SPEED_FAST);
868 return MSC_REQ_SUCCESS;
869 }
870
871 /* Try switching to High Speed (50 MHz) */
872 char buffer[64] CACHEALIGN_ATTR;
873 msc_req req = {0};
874 req.command = SD_SWITCH_FUNC;
875 req.argument = 0x80fffff1;
876 req.resptype = MSC_RESP_R1;
877 req.flags = MSC_RF_DATA;
878 req.data = &buffer[0];
879 req.block_len = 64;
880 req.nr_blocks = 1;
881 if(msc_cmd_exec(d, &req))
882 return req.status;
883
884 msc_set_speed(d, MSC_SPEED_HIGH);
885 return MSC_REQ_SUCCESS;
886}
887
888int msc_cmd_send_status(msc_drv* d)
889{
890 msc_req req = {0};
891 req.command = SD_SEND_STATUS;
892 req.argument = d->cardinfo.rca;
893 req.resptype = MSC_RESP_R1;
894 return msc_cmd_exec(d, &req);
895}
896
897int msc_cmd_set_block_len(msc_drv* d, unsigned len)
898{
899 msc_req req = {0};
900 req.command = SD_SET_BLOCKLEN;
901 req.argument = len;
902 req.resptype = MSC_RESP_R1;
903 return msc_cmd_exec(d, &req);
904}