source: uKadecot/trunk/pfatfs/mmc_rspi.c@ 154

Last change on this file since 154 was 154, checked in by coas-nagasima, 8 years ago

SDカードの中身を/~/でアクセスできるよう変更

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 23.7 KB
Line 
1/*------------------------------------------------------------------------*/
2/* FRK-RX62N: MMCv3/SDv1/SDv2 (SPI mode) Control Module */
3/*------------------------------------------------------------------------*/
4/*
5/ Copyright (C) 2014, ChaN, all right reserved.
6/
7/ * This software is a free software and there is NO WARRANTY.
8/ * No restriction on use. You can use, modify and redistribute it for
9/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
10/ * Redistributions of source code must retain the above copyright notice.
11/
12/-------------------------------------------------------------------------*/
13
14#include <kernel.h> /* Platform dependent include file */
15#include <t_syslog.h>
16#include <kernel/kernel_rename.h>
17#include <sil.h>
18#include <string.h>
19#include "pffconf.h"
20#include "target_config.h"
21#include "kernel_cfg.h"
22#include "mmc_rspi.h"
23
24static void CS_LOW()
25{
26 sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) & ~PORT_PODR_B0_BIT); /* Set CS# low */
27}
28
29static void CS_HIGH()
30{
31 sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) | PORT_PODR_B0_BIT); /* Set CS# high */
32}
33
34static bool_t WP()
35{
36 return false;
37}
38
39static bool_t INS()
40{
41 return (sil_reb_mem(PORT1_PIDR_ADDR) & PORT_PIDR_B5_BIT) == 0;
42}
43
44static void CTRL_INIT()
45{
46 /* CS=OUT */
47 sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B0_BIT);
48 /* INS=IN */
49 sil_wrb_mem(PORT1_PDR_ADDR, sil_reb_mem(PORT1_PDR_ADDR) & ~PORT_PDR_B5_BIT);
50 /* SPICLK,SPIMOSI=OUT */
51 sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B5_BIT | PORT_PDR_B6_BIT);
52 /* CS,SPICLK,SPIMOSI=HI */
53 sil_wrb_mem(PORTC_PODR_ADDR, sil_reb_mem(PORTC_PODR_ADDR) | PORT_PODR_B0_BIT | PORT_PDR_B5_BIT | PORT_PDR_B6_BIT);
54 /* SPIMISO=IN */
55 sil_wrb_mem(PORTC_PDR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) & ~PORT_PDR_B7_BIT);
56 /* SPIMISO=PULLUP */
57 sil_wrb_mem(PORTC_PCR_ADDR, sil_reb_mem(PORTC_PDR_ADDR) | PORT_PDR_B7_BIT);
58 /* CMOS‚ð‘I‘ð */
59 sil_wrb_mem(PORTC_ODR0_ADDR, 0x00);
60 /* CMOS‚ð‘I‘ð */
61 sil_wrb_mem(PORTC_ODR1_ADDR, 0x00);
62}
63
64#define F_PCLK 48000000UL /* PCLK frequency (configured by SCKCR.PCK) */
65#define SCLK_FAST 24000000UL /* SCLK frequency (R/W) */
66#define SCLK_SLOW 375000UL /* SCLK frequency (Init) */
67
68static void RSPI_ATTACH()
69{
70 /*
71 * ƒ‚ƒWƒ…
72[ƒ‹ƒXƒgƒbƒv‹@”\‚̐ݒè(RSPI0)
73 */
74 sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* ‘ž‚Ý‹–‰Â */
75 sil_wrw_mem(SYSTEM_MSTPCRB_ADDR,
76 sil_rew_mem(SYSTEM_MSTPCRB_ADDR) & ~SYSTEM_MSTPCRB_MSTPB17_BIT);
77 sil_wrh_mem(SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* ‘ž‚Ý‹ÖŽ~ */
78
79 /* P15‚ðGPIO‚Æ‚µ‚ÄŽg—p */
80 sil_wrb_mem(PORT1_PMR_ADDR,
81 sil_reb_mem(PORT1_PMR_ADDR) & ~PORT_PMR_B5_BIT);
82 /* PC0‚ðGPIO‚Æ‚µ‚ÄŽg—p */
83 sil_wrb_mem(PORTC_PMR_ADDR,
84 sil_reb_mem(PORTC_PMR_ADDR) & ~PORT_PMR_B0_BIT);
85 /* PC5, PC6, PC7‚ðŽü•Ó‹@”\‚Æ‚µ‚ÄŽg—p */
86 sil_wrb_mem(PORTC_PMR_ADDR,
87 sil_reb_mem(PORTC_PMR_ADDR) | PORT_PMR_B5_BIT | PORT_PMR_B6_BIT | PORT_PMR_B7_BIT);
88
89 /* ‘‚«ž‚݃vƒƒeƒNƒgƒŒƒWƒXƒ^‚̐ݒè PFSWEƒrƒbƒg‚ւ̏‘‚«ž‚Ý‚ð‹–‰Â */
90 sil_wrb_mem(MPC_PWPR_ADDR, 0x00);
91 /* ‘‚«ž‚݃vƒƒeƒNƒgƒŒƒWƒXƒ^‚̐ݒè PxxFSƒŒƒWƒXƒ^‚ւ̏‘‚«ž‚Ý‚ð‹–‰Â */
92 sil_wrb_mem(MPC_PWPR_ADDR, 0x40);
93
94 /* RSPCKA‚ð‘I‘ð */
95 sil_wrb_mem(MPC_PC5PFS_ADDR, 0x0d);
96 /* MOSIA‚ð‘I‘ð */
97 sil_wrb_mem(MPC_PC6PFS_ADDR, 0x0d);
98 /* MISOA‚ð‘I‘ð */
99 sil_wrb_mem(MPC_PC7PFS_ADDR, 0x0d);
100
101 /* ‘‚«ž‚݃vƒƒeƒNƒgƒŒƒWƒXƒ^‚ÌÝ’è ‘‚«ž‚Ý‚ð‹ÖŽ~ */
102 sil_wrb_mem(MPC_PWPR_ADDR, 0x80);
103}
104
105static void FCLK_FAST()
106{
107 /* RSPI‹@”\‚𖳌ø‰» */
108 sil_wrb_mem(RSPI0_SPCR_ADDR,
109 sil_reb_mem(RSPI0_SPCR_ADDR) & ~RSPI_SPCR_SPE_BIT);
110 /* ƒrƒbƒgƒŒ[ƒgÝ’è */
111 sil_wrb_mem(RSPI0_SPBR_ADDR, F_PCLK / 2 / SCLK_FAST - 1);
112 /* RSPI‹@”\‚ð—LŒø‰» */
113 sil_wrb_mem(RSPI0_SPCR_ADDR,
114 sil_reb_mem(RSPI0_SPCR_ADDR) | RSPI_SPCR_SPE_BIT);
115}
116
117#ifdef SIL_ENDIAN_LITTLE
118#define LDDW(x) rev_endian_uint32(x) /* Little endian: swap bytes */
119#else
120#define LDDW(x) x /* Big endian: no swap */
121#endif
122
123
124
125/*--------------------------------------------------------------------------
126
127 Module Private Functions
128
129---------------------------------------------------------------------------*/
130
131/* MMC/SD command */
132#define CMD0 (0) /* GO_IDLE_STATE */
133#define CMD1 (1) /* SEND_OP_COND (MMC) */
134#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
135#define CMD8 (8) /* SEND_IF_COND */
136#define CMD9 (9) /* SEND_CSD */
137#define CMD10 (10) /* SEND_CID */
138#define CMD12 (12) /* STOP_TRANSMISSION */
139#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
140#define CMD16 (16) /* SET_BLOCKLEN */
141#define CMD17 (17) /* READ_SINGLE_BLOCK */
142#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
143#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
144#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
145#define CMD24 (24) /* WRITE_BLOCK */
146#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
147#define CMD32 (32) /* ERASE_ER_BLK_START */
148#define CMD33 (33) /* ERASE_ER_BLK_END */
149#define CMD38 (38) /* ERASE */
150#define CMD55 (55) /* APP_CMD */
151#define CMD58 (58) /* READ_OCR */
152
153
154
155static volatile
156DSTATUS Stat = STA_NOINIT; /* Physical drive status */
157
158static volatile
159WORD Timer1, Timer2; /* 1000Hz decrement timer stopped at zero (driven by mmc_rspi_timerproc()) */
160
161static
162BYTE CardType; /* Card type flags */
163
164static
165BYTE CSD[16], CID[16];
166
167static
168uint64_t CardCapacity;
169
170static
171uint32_t CardBlockSize;
172
173/*-----------------------------------------------------------------------*/
174/* Control SPI module */
175/*-----------------------------------------------------------------------*/
176/* Only these five functions are platform dependent. Any other functions */
177/* are portable to different system. */
178
179/*---------------------------------*/
180/* Enable SPI and MMC/SDC controls */
181/*---------------------------------*/
182static
183void power_on(void)
184{
185 /* Initialize CS/INS/WP port */
186 CTRL_INIT();
187
188 /* Attach RSPI0 module to I/O pads, disable module stop */
189 RSPI_ATTACH();
190
191 /* Initialize RSPI module */
192 sil_wrb_mem(RSPI0_SPCR_ADDR, 0); /* Stop RSPI module */
193 sil_wrb_mem(RSPI0_SPPCR_ADDR, 0); /* Fixed idle value, disable loop-back mode */
194 sil_wrb_mem(RSPI0_SPSCR_ADDR, 0); /* Disable sequence control */
195 sil_wrb_mem(RSPI0_SPDCR_ADDR, 0x20); /* SPLW=1 */
196 sil_wrh_mem(RSPI0_SPCMD0_ADDR, 0x0700); /* LSBF=0, SPB=7, BRDV=0, CPOL=0, CPHA=0 */
197 sil_wrb_mem(RSPI0_SPBR_ADDR, F_PCLK / 2 / SCLK_SLOW - 1); /* Bit rate */
198 sil_wrb_mem(RSPI0_SPCR_ADDR, 0xC9); /* Start RSPI in master mode */
199
200 //ena_int(INTNO_MMC_RSPI_SPRI);
201 //ena_int(INTNO_MMC_RSPI_SPTI);
202 //ena_int(INTNO_MMC_RSPI_SPII);
203 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
204
205 sta_cyc(MMC_RSPI_CYC);
206}
207
208
209/*---------------------*/
210/* Disable SPI */
211/*---------------------*/
212static
213void power_off(void) /* Disable MMC/SDC interface */
214{
215 stp_cyc(MMC_RSPI_CYC);
216
217 //dis_int(INTNO_MMC_RSPI_SPRI);
218 //dis_int(INTNO_MMC_RSPI_SPTI);
219 //dis_int(INTNO_MMC_RSPI_SPII);
220
221 sil_wrb_mem(RSPI0_SPCR_ADDR, 0); /* Stop RSPI module */
222}
223
224
225/*---------------------*/
226/* Send/Receive a byte */
227/*---------------------*/
228static
229BYTE xchg_spi(
230 BYTE dat /* Data to send */
231 )
232{
233 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
234 sil_wrw_mem(RSPI0_SPDR_ADDR, dat); /* Start transmission (lower 8bits) */
235 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
236 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
237 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
238 return sil_rew_mem(RSPI0_SPDR_ADDR); /* Returen received byte (lower 8bits) */
239}
240
241
242/*---------------------*/
243/* Send multiple bytes */
244/*---------------------*/
245static
246void xmit_spi_multi(
247 const BYTE *buff, /* Pointer to the data */
248 UINT btx /* Number of bytes to send (multiple of 4) */
249 )
250{
251 const DWORD *lp = (const DWORD*)buff;
252
253 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
254 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (3 << RSPI_SPCMD_SPB_OFFSET)); /* Set 32-bit mode */
255
256 do {
257 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
258 sil_wrw_mem(RSPI0_SPDR_ADDR, LDDW(*lp++)); /* Send four data bytes */
259 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
260 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
261 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
262 sil_rew_mem(RSPI0_SPDR_ADDR); /* Discard four received bytes */
263 } while (btx -= 4); /* Repeat until all data sent */
264
265 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
266 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (7 << RSPI_SPCMD_SPB_OFFSET)); /* Set 8-bit mode */
267}
268
269
270/*------------------------*/
271/* Receive multiple bytes */
272/*------------------------*/
273static
274void rcvr_spi_multi(
275 BYTE *buff, /* Pointer to data buffer */
276 UINT size, /* Buffer size */
277 UINT skip,
278 UINT btr /* Number of bytes to receive (multiple of 4) */
279 )
280{
281 DWORD *lp, data;
282 UINT pos, start = skip & ~3, end = (skip + size) & ~3, temp, dpos;
283
284 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
285 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (3 << RSPI_SPCMD_SPB_OFFSET)); /* Set 32-bit mode */
286
287 for (pos = 0; pos < start; pos += 4) {
288 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
289 sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
290 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
291 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
292 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
293 sil_rew_mem(RSPI0_SPDR_ADDR); /* skip four received bytes */
294 }
295
296 if ((temp = skip & 3) != 0) {
297 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
298 sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
299 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
300 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
301 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
302 data = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
303 pos += 4;
304 dpos = 0;
305 switch (temp) {
306 case 1:
307 buff[dpos++] = (BYTE)(data >> 8);
308 case 2:
309 buff[dpos++] = (BYTE)(data >> 16);
310 case 3:
311 buff[dpos++] = (BYTE)(data >> 24);
312 }
313 lp = (DWORD*)&buff[dpos];
314 }
315 else
316 lp = (DWORD*)buff;
317
318 for (; pos < end; pos += 4) {
319 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
320 sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
321 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
322 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
323 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
324 *lp++ = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
325 } /* Repeat until all data received */
326
327 if ((temp = (skip + size) & 3) != 0) {
328 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
329 sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
330 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
331 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
332 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
333 data = LDDW(sil_rew_mem(RSPI0_SPDR_ADDR)); /* Store four received bytes */
334 pos += 4;
335 buff = (BYTE *)lp;
336 switch (temp) {
337 case 3:
338 buff[2] = (BYTE)(data >> 16);
339 case 2:
340 buff[1] = (BYTE)(data >> 8);
341 case 1:
342 buff[0] = (BYTE)data;
343 }
344 }
345
346 for (pos = 0; pos < btr; pos += 4) {
347 sil_wrb_mem(RSPI0_SPSR_ADDR, 0xA0);
348 sil_wrw_mem(RSPI0_SPDR_ADDR, 0xFFFFFFFF); /* Send four 0xFFs */
349 /*while ((sil_reb_mem(RSPI0_SPSR_ADDR) & RSPI_SPSR_SPRF_BIT) == 0); /* Wait for end of transfer */
350 while ((sil_reb_mem(ICU_IR039_ADDR) & 0x01) == 0);
351 sil_wrb_mem(ICU_IR039_ADDR, 0x00);
352 sil_rew_mem(RSPI0_SPDR_ADDR); /* skip four received bytes */
353 }
354
355 sil_wrh_mem(RSPI0_SPCMD0_ADDR,
356 (sil_reh_mem(RSPI0_SPCMD0_ADDR) & ~RSPI_SPCMD_SPB_MASK) | (7 << RSPI_SPCMD_SPB_OFFSET)); /* Set 8-bit mode */
357}
358
359
360
361
362/*-----------------------------------------------------------------------*/
363/* Wait for card ready */
364/*-----------------------------------------------------------------------*/
365
366static
367int wait_ready( /* 1:Ready, 0:Timeout */
368 UINT wt /* Timeout [ms] */
369 )
370{
371 Timer2 = (WORD)wt;
372
373 do {
374 if (xchg_spi(0xFF) == 0xFF) return 1; /* Card goes ready */
375 /* This loop takes a time. Insert rot_rdq() here for multitask envilonment. */
376 } while (Timer2); /* Wait until card goes ready or timeout */
377
378 return 0; /* Timeout occured */
379}
380
381
382
383/*-----------------------------------------------------------------------*/
384/* Deselect card and release SPI */
385/*-----------------------------------------------------------------------*/
386
387static
388void deselect(void)
389{
390 CS_HIGH(); /* Set CS# high */
391 xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
392}
393
394
395
396/*-----------------------------------------------------------------------*/
397/* Select card and wait for ready */
398/*-----------------------------------------------------------------------*/
399
400static
401int select(void) /* 1:OK, 0:Timeout */
402{
403 CS_LOW(); /* Set CS# low */
404 xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
405
406 if (wait_ready(500)) return 1; /* Wait for card ready */
407
408 deselect();
409 return 0; /* Failed to select the card due to timeout */
410}
411
412
413
414/*-----------------------------------------------------------------------*/
415/* Receive a data packet from the MMC */
416/*-----------------------------------------------------------------------*/
417
418static
419int rcvr_datablock( /* 1:OK, 0:Error */
420 BYTE *buff, /* Data buffer */
421 UINT size, /* Buffer size */
422 UINT skip,
423 UINT btr /* Data block length (byte) */
424 )
425{
426 BYTE token;
427
428
429 Timer1 = 200;
430 do { /* Wait for DataStart token in timeout of 200ms */
431 token = xchg_spi(0xFF);
432 /* This loop will take a time. Insert rot_rdq() here for multitask envilonment. */
433 } while ((token == 0xFF) && Timer1);
434 if (token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */
435
436 rcvr_spi_multi(buff, size, skip, btr); /* Store trailing data to the buffer */
437 xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */
438
439 return 1; /* Function succeeded */
440}
441
442
443
444/*-----------------------------------------------------------------------*/
445/* Send a data packet to the MMC */
446/*-----------------------------------------------------------------------*/
447
448#if _USE_WRITE
449static
450int xmit_datablock( /* 1:OK, 0:Failed */
451 const BYTE *buff, /* Ponter to 512 byte data to be sent */
452 BYTE token /* Token */
453 )
454{
455 BYTE resp;
456
457
458 if (!wait_ready(500)) return 0; /* Wait for card ready */
459
460 xchg_spi(token); /* Send token */
461 if (token != 0xFD) { /* Send data if token is other than StopTran */
462 xmit_spi_multi(buff, 512); /* Data */
463 xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */
464
465 resp = xchg_spi(0xFF); /* Receive data resp */
466 if ((resp & 0x1F) != 0x05) /* Function fails if the data packet was not accepted */
467 return 0;
468 }
469 return 1;
470}
471#endif /* _USE_WRITE */
472
473
474
475/*-----------------------------------------------------------------------*/
476/* Send a command packet to the MMC */
477/*-----------------------------------------------------------------------*/
478
479static
480BYTE send_cmd( /* Return value: R1 resp (bit7==1:Failed to send) */
481 BYTE cmd, /* Command index */
482 DWORD arg /* Argument */
483 )
484{
485 BYTE n, res;
486
487
488 if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */
489 cmd &= 0x7F;
490 res = send_cmd(CMD55, 0);
491 if (res > 1) return res;
492 }
493
494 /* Select the card and wait for ready except to stop multiple block read */
495 if (cmd != CMD12) {
496 deselect();
497 if (!select()) return 0xFF;
498 }
499
500 /* Send command packet */
501 xchg_spi(0x40 | cmd); /* Start + command index */
502 xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
503 xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
504 xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
505 xchg_spi((BYTE)arg); /* Argument[7..0] */
506 n = 0x01; /* Dummy CRC + Stop */
507 if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
508 if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
509 xchg_spi(n);
510
511 /* Receive command resp */
512 if (cmd == CMD12) xchg_spi(0xFF); /* Diacard stuff byte on CMD12 */
513 n = 10; /* Wait for response (10 bytes max) */
514 do
515 res = xchg_spi(0xFF);
516 while ((res & 0x80) && --n);
517
518 return res; /* Return received response */
519}
520
521
522
523/*--------------------------------------------------------------------------
524
525 Public Functions
526
527---------------------------------------------------------------------------*/
528
529
530/*-----------------------------------------------------------------------*/
531/* Initialize disk drive */
532/*-----------------------------------------------------------------------*/
533
534DSTATUS mmc_rspi_initialize(void)
535{
536 BYTE n, cmd, ty, ocr[4];
537
538
539 power_on(); /* Initialize RSPI */
540 for (n = 10; n; n--) xchg_spi(0xFF);/* Send 80 dummy clocks */
541
542 ty = 0;
543 if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI/Idle state */
544 Timer1 = 1000; /* Initialization timeout = 1 sec */
545 if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
546 for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */
547 if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Is the card supports vcc of 2.7-3.6V? */
548 while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for end of initialization with ACMD41(HCS) */
549 if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
550 for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
551 ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Card id SDv2 */
552 }
553 }
554 }
555 else { /* Not SDv2 card */
556 if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMC? */
557 ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */
558 }
559 else {
560 ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */
561 }
562 while (Timer1 && send_cmd(cmd, 0)); /* Wait for end of initialization */
563 //if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */
564 // ty = 0;
565 }
566 if (ty) {
567 if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
568 && rcvr_datablock(CSD, 16, 0, 16)){
569 /* CSD Ver.1.0 */
570 if ((CSD[0] & 0xC0) == 0) {
571 CardBlockSize = 1 << (CSD[5] & 0x0F);
572 CardCapacity = (((CSD[6] & 0x03) << 10) | (CSD[7] << 2) | ((CSD[8] & 0xC0) >> 6)) + 1;
573 CardCapacity *= (((uint64_t)1) << ((((CSD[9] & 0x03) << 1) | (CSD[10] & 0x80) >> 7) + 2));
574 CardCapacity *= (uint64_t)CardBlockSize;
575 }
576 else {
577 CardBlockSize = 512;
578 CardCapacity = ((uint64_t)((((CSD[7] & 0x3F) << 16) | (CSD[8] << 8) | CSD[9]) + 1)) * 512 * 1024;
579 }
580 if (send_cmd(CMD10, 0) != 0 /* READ_CID */
581 || !rcvr_datablock(CID, 16, 0, 16)) {
582 ty = 0;
583 }
584 }
585 else {
586 ty = 0;
587 }
588 }
589 }
590 CardType = ty; /* Card type */
591 deselect();
592
593 if (ty) { /* OK */
594 FCLK_FAST(); /* Set fast clock */
595 Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */
596 }
597 else { /* Failed */
598 power_off();
599 Stat = STA_NOINIT;
600 }
601
602 return Stat;
603}
604
605
606
607/*-----------------------------------------------------------------------*/
608/* Get disk status */
609/*-----------------------------------------------------------------------*/
610
611DSTATUS mmc_rspi_get_status(void)
612{
613 return Stat; /* Return disk status */
614}
615
616
617
618/*-----------------------------------------------------------------------*/
619/* Read sector(s) */
620/*-----------------------------------------------------------------------*/
621
622DRESULT mmc_rspi_readp(
623 BYTE *buff, /* Pointer to the data buffer to store read data */
624 DWORD sector, /* Start sector number (LBA) */
625 UINT offset, /* Offset in the sector */
626 UINT count /* Byte count */
627 )
628{
629 if (!count) return RES_PARERR; /* Check parameter */
630 if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
631
632 if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */
633
634 if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
635 && rcvr_datablock(buff, count, offset, 512))
636 count = 0;
637 deselect();
638
639 return count ? RES_ERROR : RES_OK; /* Return result */
640}
641
642
643
644/*-----------------------------------------------------------------------*/
645/* Write sector(s) */
646/*-----------------------------------------------------------------------*/
647
648#if _USE_WRITE
649DRESULT mmc_rspi_writep(
650 const BYTE *buff, /* Ponter to the data to write */
651 DWORD sector /* Start sector number (LBA) */
652 )
653{
654 DRESULT res = RES_ERROR;
655 if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */
656 if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */
657
658 if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */
659
660 if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
661 && xmit_datablock(buff, 0xFE))
662 res = RES_OK;
663 deselect();
664
665 return res; /* Return result */
666}
667#endif /* _USE_WRITE */
668
669
670
671/*-----------------------------------------------------------------------*/
672/* Miscellaneous drive controls other than data read/write */
673/*-----------------------------------------------------------------------*/
674
675#if _USE_IOCTL
676DRESULT mmc_rspi_ioctl(
677 BYTE ctrl, /* Control command code */
678 void *buff /* Pointer to the conrtol data */
679 )
680{
681 DRESULT res;
682 BYTE n, csd[16], *ptr = buff;
683 DWORD *dp, st, ed;
684
685
686 if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
687
688 res = RES_ERROR;
689
690 switch (ctrl) {
691 case CTRL_SYNC: /* Wait for end of internal write process of the drive */
692 if (select()) res = RES_OK;
693 break;
694
695 case GET_SECTOR_SIZE:
696 *(WORD*)buff = 512;
697 res = RES_OK;
698 break;
699
700 case GET_SECTOR_COUNT:
701 *(DWORD*)buff = CardCapacity / 512;
702 res = RES_OK;
703 break;
704
705 case GET_BLOCK_SIZE:
706 *(DWORD*)buff = CardBlockSize;
707 res = RES_OK;
708 break;
709
710 case CTRL_TRIM: /* Erase a block of sectors (used when _USE_TRIM == 1) */
711 if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */
712 if (mmc_rspi_ioctl(MMC_GET_CSD, csd)) break; /* Get CSD */
713 if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */
714 dp = buff; st = dp[0]; ed = dp[1]; /* Load sector block */
715 if (!(CardType & CT_BLOCK)) {
716 st *= 512; ed *= 512;
717 }
718 if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) /* Erase sector block */
719 res = RES_OK;
720 break;
721
722 /* Following command are not used by FatFs module */
723
724 case MMC_GET_TYPE: /* Get MMC/SDC type (BYTE) */
725 *ptr = CardType;
726 res = RES_OK;
727 break;
728
729 case MMC_GET_CSD: /* Read CSD (16 bytes) */
730 memcpy(ptr, CSD, sizeof(CSD));
731 res = RES_OK;
732 break;
733
734 case MMC_GET_CID: /* Read CID (16 bytes) */
735 memcpy(ptr, CID, sizeof(CID));
736 res = RES_OK;
737 break;
738
739 case MMC_GET_OCR: /* Read OCR (4 bytes) */
740 if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
741 for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
742 res = RES_OK;
743 }
744 break;
745
746 case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */
747 if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
748 xchg_spi(0xFF);
749 if (rcvr_datablock(ptr, 64, 0, 64))
750 res = RES_OK;
751 }
752 break;
753
754 default:
755 res = RES_PARERR;
756 }
757
758 deselect();
759
760 return res;
761}
762#endif /* _USE_IOCTL */
763
764
765/*-----------------------------------------------------------------------*/
766/* Device timer function */
767/*-----------------------------------------------------------------------*/
768/* This function must be called from system timer process
769/ in period of 1 ms to generate card control timing.
770*/
771
772void mmc_rspi_timerproc(void)
773{
774 WORD n;
775 BYTE s;
776
777
778 n = Timer1; /* 1kHz decrement timer stopped at 0 */
779 if (n) Timer1 = --n;
780 n = Timer2;
781 if (n) Timer2 = --n;
782
783 s = Stat;
784 if (WP()) /* Write protected */
785 s |= STA_PROTECT;
786 else /* Write enabled */
787 s &= ~STA_PROTECT;
788 if (INS()) /* Card is in socket */
789 s &= ~STA_NODISK;
790 else /* Socket empty */
791 s |= (STA_NODISK | STA_NOINIT);
792 Stat = s;
793}
794
795void mmc_rspi_spri_handler(void)
796{
797 i_begin_int(INTNO_MMC_RSPI_SPRI);
798
799 i_end_int(INTNO_MMC_RSPI_SPRI);
800}
801
802void mmc_rspi_spti_handler(void)
803{
804 i_begin_int(INTNO_MMC_RSPI_SPTI);
805
806 i_end_int(INTNO_MMC_RSPI_SPTI);
807}
808
809void mmc_rspi_spii_handler(void)
810{
811 i_begin_int(INTNO_MMC_RSPI_SPII);
812
813 i_end_int(INTNO_MMC_RSPI_SPII);
814}
815
816void mmc_rspi_cychdr(intptr_t exinf)
817{
818 mmc_rspi_timerproc();
819}
Note: See TracBrowser for help on using the repository browser.