1 /*==============================================================================
2 * spi.c - routines that communicate with the card using spi
4 * Methods in this file perform all I/O with the media card.
6 * This file is broken into 2 sections:
8 * 1) Unoptimized methods
10 * -Methods that have not been optimized for maximum performance.
12 * -Honour the maximum frequency setting (if set).
14 * -There's little payback trying to optimize these, as they are only used
15 * during card initialization.
17 * 2) Optimized methods
19 * -Methods that have been optimized for maximum performance.
21 * -Don't honour the maximum frequency setting and are coded to run as fast
22 * as possible - don't call any from code that does card initialization
23 * (max 400khz frequency).
25 * -There are different variants of methods to help optimize throughput.
26 * For example, there is rarely a need to both send and receive data at
27 * the same time, so instead of using just spi_io, 3 variants can be
28 * created that have better performance.
30 * r = spi_io(0xab) - send argument, return data out bits.
31 * spi_io_v_o(0xab) - send argument, ignore data out bits.
32 * r = spi_io_ff_o() - send 0xff, return data out bits.
33 * spi_io_ff_v_o() - send 0xff, ignore data out bits.
35 * -Efficiency was tuned by having the compiler dump the generated MIPS
36 * assembler instructions, then adjusting the C source to minimize the
37 * number of MIPS instructions generated (wherever possible).
39 * -Looping is avoided or reduced where possible to improve efficiency. This
40 * does increase module size.
42 * -The compiler, with optimization on, winds up inlining the vast majority
43 * of the code, so even though we have more methods, code size is not
48 * -All methods begin with "spi_".
49 * -Optimized methods are suffixed with "_o" to make them easy to identify.
50 * -Variants of methods that return no (void) value are suffixed with "_v".
51 * -Only variables used exclusively by methods in this module are defined here.
52 * All begin with "spi_".
53 *============================================================================*/
55 // Handy to turn off inlining globally when analyzing generated MIPS assembler code
58 // Function prototypes - non optimized functions
59 static int spi_init(void);
60 static int spi_freq_max(int);
61 static void spi_freq_wait(cycles_t
);
62 static void spi_cs_ass(void);
63 static void spi_cs_dea(void);
64 static unsigned char spi_io(unsigned char);
65 static unsigned char spi_mmc_cmd_r(unsigned char, unsigned int, unsigned char, unsigned char *, int);
66 static unsigned char spi_mmc_read_blk(unsigned char, unsigned int, unsigned char, unsigned char *, int);
68 // Function prototypes - optimized functions
69 static inline void spi_cs_ass_o(void);
70 static inline void spi_cs_dea_o(void);
71 static inline void spi_io_ff_v_o(void);
72 static inline void spi_io_2ff_v_o(void);
73 static inline void spi_io_6ff_v_o(void);
74 static inline unsigned char spi_io_ff_o(void);
75 static inline void spi_io_v_o(unsigned char);
76 static inline unsigned char spi_mmc_write_multi_o(unsigned int, unsigned char *, int, unsigned char, unsigned char);
77 static inline unsigned char spi_mmc_read_multi_o(unsigned int, unsigned char *, int, unsigned char, unsigned char);
79 // Variables used to set GPIO port state (cs low = asserted)
80 static unsigned char spi_ps_d0_c1
; // data low, clock hi, cs low
81 static unsigned char spi_ps_d0_c0
; // data low, clock low, cs low
82 static unsigned char spi_ps_d1_c1
; // data hi, clock hi, cs low
83 static unsigned char spi_ps_d1_c0
; // data hi, clock low, cs low
85 // Masks and bit numbers - spi->GPIO mappings
86 static unsigned char spi_di_mask
;
87 static unsigned char spi_do_mask
;
88 static unsigned char spi_do_pin
;
89 static unsigned char spi_cl_mask
;
90 static unsigned char spi_cs_mask
;
92 // Vars that are used to control the max clock frequency
93 static cycles_t spi_clk_delay
= 0; // set max clock frequency (khz)
94 static cycles_t spi_clk_last
= 0; // time of last clock transition
97 //======================= UNOPTIMIZED METHODS ==================================
100 /*------------------------------------------------------------------------------
103 * Initialize spi hardware - specify which IO pins used for SPI communications
105 * Set the required state, IO mode, and control mode for SPI.
107 *----------------------------------------------------------------------------*/
108 static int spi_init() {
110 // Convert gpio pin nums to bit mask used to set/clear appropriate GPIO bit.
111 spi_di_mask
= (1 << din
);
112 spi_do_mask
= (1 << dout
);
113 spi_cl_mask
= (1 << clk
);
114 spi_cs_mask
= (1 << cs
);
117 // Disable weak pullups on all GPIO pins used by this module
118 *gpio_control
&= ~( spi_di_mask
| spi_cl_mask
| spi_cs_mask
| spi_do_mask
);
120 // Set din, clk and cs GPIO pins to outputs, dout GPIO pin to input
121 *gpio_enable
= (*gpio_enable
| spi_di_mask
| spi_cl_mask
| spi_cs_mask
) & ~spi_do_mask
;
123 // Initial setup of port state variables
124 spi_ps_d1_c0
= ((*gpio_output
| spi_di_mask
) & ~spi_cl_mask
) & ~spi_cs_mask
; // din hi, clock low
125 spi_ps_d1_c1
= spi_ps_d1_c0
| spi_cl_mask
; // din hi, clock hi
126 spi_ps_d0_c1
= spi_ps_d1_c1
& ~spi_di_mask
; // din low, clock hi
127 spi_ps_d0_c0
= spi_ps_d0_c1
& ~spi_cl_mask
; // din low, clock hi
129 // Initial state - data hi, clock low, cs hi - restores output state of unused pins
130 *gpio_output
= spi_ps_d1_c0
| spi_cs_mask
;
136 /*------------------------------------------------------------------------------
139 * Set the maximum frequency (in KHz) the spi clock may run at.
140 * A value of zero means no maximum frequency - as fast as possible.
143 *----------------------------------------------------------------------------*/
144 static int spi_freq_max(int freq
) {
146 /* calculate and save the period of the specified frequency */
148 spi_clk_delay
= (loops_per_jiffy
*(HZ
<<1)) / (freq
*1000*2);
157 /*------------------------------------------------------------------------------
160 * Used to ensure enough time has elapsed between clock transitions so clock
161 * frequency remains below the set maximum.
165 * -spi_clk_last is global. It is also set in the spi_cs_ass method...
166 *----------------------------------------------------------------------------*/
167 static void spi_freq_wait(cycles_t wait
) {
168 cycles_t now
, delta
, future
;
170 // Calculate how many cycles have elapsed since clock last toggled
172 delta
= (now
> spi_clk_last
) ? (now
- spi_clk_last
) : (spi_clk_last
- now
); // abs(now - last)
176 // Less than requested wait - calc future time we must wait until
177 future
= now
+ (wait
- delta
); /* can overflow and wrap arround */
179 // Now wait until that future time - handle overflow...
181 // Value overflowed - wait till now <= future
182 while (get_cycles() > future
) ;
184 while (get_cycles() < future
) ;
188 // Save current cycles value so we know when next transition allowed.
189 spi_clk_last
= get_cycles();
193 /*------------------------------------------------------------------------------
196 * Assert CS signal. Unoptimized version that supports max frequency setting.
199 *----------------------------------------------------------------------------*/
200 static INLINE
void spi_cs_ass(void) {
201 spi_clk_last
= get_cycles(); // assume clock just transitioned
202 spi_ps_d1_c0
= ((*gpio_output
| spi_di_mask
) & ~spi_cl_mask
) & ~spi_cs_mask
; // din hi, clock low
203 spi_ps_d1_c1
= spi_ps_d1_c0
| spi_cl_mask
; // din hi, clock hi
204 spi_ps_d0_c1
= spi_ps_d1_c1
& ~spi_di_mask
; // din low, clock hi
205 spi_ps_d0_c0
= spi_ps_d0_c1
& ~spi_cl_mask
; // din low, clock hi
206 *gpio_output
= spi_ps_d1_c0
; // assert cs
210 /*------------------------------------------------------------------------------
213 * Deassert CS signal - send 8 clocks to release DO
216 *----------------------------------------------------------------------------*/
217 static INLINE
void spi_cs_dea(void) {
218 *gpio_output
= spi_ps_d1_c0
| spi_cs_mask
; // deassert cs (cs line hi) and clock low
219 spi_io(0xff); // 8 clocks
223 /*------------------------------------------------------------------------------
226 * Send/Receive 8 bits of data at same time.
229 *----------------------------------------------------------------------------*/
230 static unsigned char spi_io(unsigned char data_out
) {
231 volatile unsigned char * out
= gpio_output
;
232 volatile unsigned char * in
= gpio_input
;
236 for (i
= 7; i
>= 0; i
--) {
238 // Set data bit appropriately and toggle clock hi
239 if (data_out
& (1 << i
)) {
242 *out
&= ~spi_di_mask
;
246 // read data from card...
248 r
|= ((*in
& spi_do_mask
) ? 1 : 0);
251 if (spi_clk_delay
) spi_freq_wait(spi_clk_delay
);
252 *out
&= ~spi_cl_mask
;
260 /*------------------------------------------------------------------------------
263 * Send a command and retrieve the command response
265 * Supports commands that return r1, r3 and r7 response formats.
267 * The first byte of the response (the r1 data) is the subroutine return value.
268 * If executing commands that return additional bytes in the response (r3 and r7 formats),
269 * pass a buffer and the additional number of bytes to read in the buf and len values.
272 *----------------------------------------------------------------------------*/
273 static unsigned char spi_mmc_cmd_r(unsigned char cmd
, unsigned int param
, unsigned char crc7
, unsigned char *buf
, int len
) {
280 // send command, arguments, crc
288 // wait up to 8 bytes for command r1 response
289 for (i
= 0; i
< 8; i
++) {
291 if (r
!= 0xff) break;
294 // return additional response bytes in buffer if requested
295 for (i
= 0; i
< len
; i
++) buf
[i
] = spi_io(0xff);
303 /*------------------------------------------------------------------------------
306 * Send an mmc command that returns a single block of data
307 *----------------------------------------------------------------------------*/
308 static unsigned char spi_mmc_read_blk(unsigned char cmd
, unsigned int param
, unsigned char crc7
, unsigned char *buf
, int len
) {
315 // send command, arguments, crc
323 // wait up to 8 bytes for command response
324 for (i
= 0; i
< 8; i
++) {
326 if (r
== 0x00) break;
328 if (r
!= 0x00) goto err1
;
330 // wait for start of data token
331 for (i
= 0; i
< 1000000; i
++) {
333 if (r
== 0xfe) break;
335 if (r
!= 0xfe) goto err1
;
338 for (i
= 0; i
< len
; i
++) buf
[i
] = spi_io(0xff);
340 // Read and discard the data packet crc bytes
344 // Deassert CS - send 8 bits to release DO
355 //======================== OPTIMIZED METHODS ===================================
358 /*------------------------------------------------------------------------------
361 * Assert CS signal - don't care about max frequency setting
365 * -Re-read port to pick up any changes to wlan/power values.
366 * -Precalculate port states - allows bit changes via assignement (1 cycle)
367 * vs by bit operations (3 cycles)
368 *----------------------------------------------------------------------------*/
369 static INLINE
void spi_cs_ass_o(void) {
370 spi_ps_d1_c0
= ((*gpio_output
| spi_di_mask
) & ~spi_cl_mask
) & ~spi_cs_mask
; // din hi, clock low
371 spi_ps_d1_c1
= spi_ps_d1_c0
| spi_cl_mask
; // din hi, clock hi
372 spi_ps_d0_c1
= spi_ps_d1_c1
& ~spi_di_mask
; // din low, clock hi
373 spi_ps_d0_c0
= spi_ps_d0_c1
& ~spi_cl_mask
; // din low, clock hi
374 *gpio_output
= spi_ps_d1_c0
; // assert cs
378 /*------------------------------------------------------------------------------
381 * Deassert CS signal. Send 8 clocks to release DO.
384 * - Local vars out, clk_hi, clk_low improve efficiency of generated code
385 *----------------------------------------------------------------------------*/
386 static INLINE
void spi_cs_dea_o(void) {
387 volatile unsigned char * out
= gpio_output
;
388 const unsigned char clk_hi
= spi_ps_d1_c1
| spi_cs_mask
;
389 const unsigned char clk_low
= spi_ps_d1_c0
| spi_cs_mask
;
391 *out
= clk_low
; // deassert cs (cs line hi) and clock low
392 *out
= clk_hi
; *out
= clk_low
;
393 *out
= clk_hi
; *out
= clk_low
;
394 *out
= clk_hi
; *out
= clk_low
;
395 *out
= clk_hi
; *out
= clk_low
;
396 *out
= clk_hi
; *out
= clk_low
;
397 *out
= clk_hi
; *out
= clk_low
;
398 *out
= clk_hi
; *out
= clk_low
;
399 *out
= clk_hi
; *out
= clk_low
;
403 /*------------------------------------------------------------------------------
406 * Send 0xff - don't worry about reading response
410 * - One asm instruction per clock toggle!
411 * - Could this possibly exceed 25MHz max for clock?
412 * - Local vars out, clk_hi, clk_low improve efficiency of generated code
413 *----------------------------------------------------------------------------*/
414 static INLINE
void spi_io_ff_v_o(void) {
415 volatile unsigned char * out
= gpio_output
;
416 const unsigned char clk_hi
= spi_ps_d1_c1
;
417 const unsigned char clk_low
= spi_ps_d1_c0
;
419 *out
= clk_low
; *out
= clk_hi
;
420 *out
= clk_low
; *out
= clk_hi
;
421 *out
= clk_low
; *out
= clk_hi
;
422 *out
= clk_low
; *out
= clk_hi
;
423 *out
= clk_low
; *out
= clk_hi
;
424 *out
= clk_low
; *out
= clk_hi
;
425 *out
= clk_low
; *out
= clk_hi
;
426 *out
= clk_low
; *out
= clk_hi
;
430 /*------------------------------------------------------------------------------
433 * Send 0xff 2 times - don't worry about reading response
437 * - Ever so slightly more efficient than calling spi_io_ff_v_o 2 times
438 *----------------------------------------------------------------------------*/
439 static INLINE
void spi_io_2ff_v_o(void) {
440 volatile unsigned char * out
= gpio_output
;
441 const unsigned char clk_hi
= spi_ps_d1_c1
;
442 const unsigned char clk_low
= spi_ps_d1_c0
;
444 *out
= clk_low
; *out
= clk_hi
;
445 *out
= clk_low
; *out
= clk_hi
;
446 *out
= clk_low
; *out
= clk_hi
;
447 *out
= clk_low
; *out
= clk_hi
;
448 *out
= clk_low
; *out
= clk_hi
;
449 *out
= clk_low
; *out
= clk_hi
;
450 *out
= clk_low
; *out
= clk_hi
;
451 *out
= clk_low
; *out
= clk_hi
;
452 *out
= clk_low
; *out
= clk_hi
;
453 *out
= clk_low
; *out
= clk_hi
;
454 *out
= clk_low
; *out
= clk_hi
;
455 *out
= clk_low
; *out
= clk_hi
;
456 *out
= clk_low
; *out
= clk_hi
;
457 *out
= clk_low
; *out
= clk_hi
;
458 *out
= clk_low
; *out
= clk_hi
;
459 *out
= clk_low
; *out
= clk_hi
;
463 /*------------------------------------------------------------------------------
466 * Send 0xff 6 times - don't worry about reading response
470 * - Ever so slightly more efficient than calling spi_io_ff_v_o 6 times
471 *----------------------------------------------------------------------------*/
472 static INLINE
void spi_io_6ff_v_o(void) {
473 volatile unsigned char * out
= gpio_output
;
474 const unsigned char clk_hi
= spi_ps_d1_c1
;
475 const unsigned char clk_low
= spi_ps_d1_c0
;
477 *out
= clk_low
; *out
= clk_hi
;
478 *out
= clk_low
; *out
= clk_hi
;
479 *out
= clk_low
; *out
= clk_hi
;
480 *out
= clk_low
; *out
= clk_hi
;
481 *out
= clk_low
; *out
= clk_hi
;
482 *out
= clk_low
; *out
= clk_hi
;
483 *out
= clk_low
; *out
= clk_hi
;
484 *out
= clk_low
; *out
= clk_hi
;
485 *out
= clk_low
; *out
= clk_hi
;
486 *out
= clk_low
; *out
= clk_hi
;
487 *out
= clk_low
; *out
= clk_hi
;
488 *out
= clk_low
; *out
= clk_hi
;
489 *out
= clk_low
; *out
= clk_hi
;
490 *out
= clk_low
; *out
= clk_hi
;
491 *out
= clk_low
; *out
= clk_hi
;
492 *out
= clk_low
; *out
= clk_hi
;
493 *out
= clk_low
; *out
= clk_hi
;
494 *out
= clk_low
; *out
= clk_hi
;
495 *out
= clk_low
; *out
= clk_hi
;
496 *out
= clk_low
; *out
= clk_hi
;
497 *out
= clk_low
; *out
= clk_hi
;
498 *out
= clk_low
; *out
= clk_hi
;
499 *out
= clk_low
; *out
= clk_hi
;
500 *out
= clk_low
; *out
= clk_hi
;
501 *out
= clk_low
; *out
= clk_hi
;
502 *out
= clk_low
; *out
= clk_hi
;
503 *out
= clk_low
; *out
= clk_hi
;
504 *out
= clk_low
; *out
= clk_hi
;
505 *out
= clk_low
; *out
= clk_hi
;
506 *out
= clk_low
; *out
= clk_hi
;
507 *out
= clk_low
; *out
= clk_hi
;
508 *out
= clk_low
; *out
= clk_hi
;
509 *out
= clk_low
; *out
= clk_hi
;
510 *out
= clk_low
; *out
= clk_hi
;
511 *out
= clk_low
; *out
= clk_hi
;
512 *out
= clk_low
; *out
= clk_hi
;
513 *out
= clk_low
; *out
= clk_hi
;
514 *out
= clk_low
; *out
= clk_hi
;
515 *out
= clk_low
; *out
= clk_hi
;
516 *out
= clk_low
; *out
= clk_hi
;
517 *out
= clk_low
; *out
= clk_hi
;
518 *out
= clk_low
; *out
= clk_hi
;
519 *out
= clk_low
; *out
= clk_hi
;
520 *out
= clk_low
; *out
= clk_hi
;
521 *out
= clk_low
; *out
= clk_hi
;
522 *out
= clk_low
; *out
= clk_hi
;
523 *out
= clk_low
; *out
= clk_hi
;
524 *out
= clk_low
; *out
= clk_hi
;
528 /*------------------------------------------------------------------------------
531 * Send 0xff - read and return response.
535 * - Local vars improve efficiency of generated code
536 * - 'r' must be an int (because of the way shifting is done). Approach
537 * allows efficient read with gpio assignment via module parm. Added
538 * bonus: switch to int saves one instruction per read (5 to 4).
539 * - Final shift fixes up return value.
540 *----------------------------------------------------------------------------*/
541 static INLINE
unsigned char spi_io_ff_o(void) {
542 volatile unsigned char *out
= gpio_output
;
543 volatile unsigned char *in
= gpio_input
;
544 const unsigned char clk_hi
= spi_ps_d1_c1
;
545 const unsigned char clk_low
= spi_ps_d1_c0
;
546 const unsigned char do_mask
= spi_do_mask
;
549 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
550 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
551 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
552 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
553 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
554 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
555 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
556 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
);
558 // Fixup result - shift right based on gpio pin dout assigned to...
564 /*------------------------------------------------------------------------------
567 * Send 0xffffff - read and return 32 bit response (word).
571 * - Local vars improve efficiency of generated code
572 * - Slightly more efficient than 4 calls to spi_io_ff_o
573 * - The MIPS architecture is little endian, so bytes have to be reversed in
574 * the register before the word is written to memory
575 * byte order while reading, so when bytes are reversed when the word is written
576 * to memory, they are stored correctly!
578 * e.g. Card sends the characters "abcd" as 4 bytes.
579 * Algorithm reads it into the 32 bit register as "dcba" (bytes reversed).
580 * Memory write reverses the bytes - storing "abcd" in ascending locations.
581 *----------------------------------------------------------------------------*/
582 static INLINE
unsigned int spi_io_4ff_o(void) {
583 volatile unsigned char *out
= gpio_output
;
584 volatile unsigned char *in
= gpio_input
;
585 const unsigned char clk_hi
= spi_ps_d1_c1
;
586 const unsigned char clk_low
= spi_ps_d1_c0
;
587 const unsigned char do_mask
= spi_do_mask
;
588 const unsigned char do_pin
= spi_do_pin
;
592 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
593 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
594 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
595 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
596 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
597 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
598 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
599 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
);
600 r
>>= do_pin
; w
|= r
; r
= 0;
601 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
602 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
603 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
604 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
605 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
606 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
607 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
608 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
);
609 r
>>= do_pin
; r
<<= 8; w
|= r
; r
= 0;
610 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
611 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
612 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
613 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
614 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
615 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
616 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
617 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
);
618 r
>>= do_pin
; r
<<= 16; w
|= r
; r
= 0;
619 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
620 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
621 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
622 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
623 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
624 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
625 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
); r
<<= 1;
626 *out
= clk_low
; *out
=clk_hi
; r
|= (*in
& do_mask
);
627 r
>>= do_pin
; r
<<= 24; w
|= r
;
633 /*------------------------------------------------------------------------------
636 * Send 8 bits of data - don't worry about reading response.
640 * - Local vars improve efficiency of generated code
641 * - if structures - larger code size, but less instructions per bit written
642 * than attempting to use bit shift/and/or instructions...
643 *----------------------------------------------------------------------------*/
644 static INLINE
void spi_io_v_o(unsigned char data_out
) {
645 volatile unsigned char * out
= gpio_output
;
646 const unsigned int d1_c0
= spi_ps_d1_c0
;
647 const unsigned int d1_c1
= spi_ps_d1_c1
;
648 const unsigned int d0_c0
= spi_ps_d0_c0
;
649 const unsigned int d0_c1
= spi_ps_d0_c1
;
651 if (data_out
& (1 << 7)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
652 if (data_out
& (1 << 6)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
653 if (data_out
& (1 << 5)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
654 if (data_out
& (1 << 4)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
655 if (data_out
& (1 << 3)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
656 if (data_out
& (1 << 2)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
657 if (data_out
& (1 << 1)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
658 if (data_out
& (1 << 0)) { *out
= d1_c0
; *out
= d1_c1
; } else { *out
= d0_c0
; *out
= d0_c1
; }
662 /*------------------------------------------------------------------------------
663 * spi_mmc_write_multi_o
665 * Write multiple 512 byte blocks from buffer with the multi block write CMD25
669 * 0 - Successful write
670 * 1 - Busy wait timeout
671 * 2 - CMD25 (multi block write) error
672 * 3 - Data response token not received
673 * 4 - Data response token - busy error
674 * 11 - Data rejected due to crc error
675 * 14 - Data rejected due to write error
679 * - Local vars improve efficiency of generated code
680 * - Possible improvements - unsigned int array - send 32 bits at a time
681 * - Try pre-erase command and analyze effect
682 *----------------------------------------------------------------------------*/
683 static INLINE
unsigned char spi_mmc_write_multi_o(unsigned int addr
, unsigned char *buf
, int blocks
, unsigned char first
, unsigned char last
) {
684 volatile unsigned char *in
= gpio_input
;
685 volatile unsigned char *out
= gpio_output
;
686 const unsigned char clk_hi
= spi_ps_d1_c1
;
687 const unsigned char clk_low
= spi_ps_d1_c0
;
688 const unsigned int do_mask
= spi_do_mask
;
689 unsigned char *p
= buf
;
694 // Only send the multi block write if first first buffer in a request
695 // Otherwise it's a continuation of an already running request
698 // send multi block write command, address, crc
700 spi_io_v_o(0x40 | 25);
701 spi_io_v_o(addr
>>24);
702 spi_io_v_o(addr
>>16);
707 // wait up to 8 bytes for command response
708 for (i
= 0; i
< 8; i
++) {
710 if (r
== 0x00) break;
712 if (r
!= 0x00) return 2;
715 // process each block in a loop
716 for (j
=0; j
< blocks
; j
++) {
718 // write start of data token
722 for (i
= 0; i
< 512; i
++) {
727 // write dummy crc (2 bytes)
730 // wait up to 9 bytes for data response token
731 for (i
= 0; i
< 29; i
++) {
733 if (r
!= 0xff) break;
735 if ((r
& 0x0f) != 0x05) {
745 // Busy state follows data response token (dout pulled low).
746 // Keep the clock running until it's done..
748 for (i
= 1; i
< 1000000; i
++) {
749 *out
= clk_low
; *out
= clk_hi
;
750 *out
= clk_low
; *out
= clk_hi
;
751 *out
= clk_low
; *out
= clk_hi
;
752 *out
= clk_low
; *out
= clk_hi
;
753 *out
= clk_low
; *out
= clk_hi
;
754 *out
= clk_low
; *out
= clk_hi
;
755 *out
= clk_low
; *out
= clk_hi
;
756 *out
= clk_low
; *out
= clk_hi
;
757 if (*in
& do_mask
) break;
760 LOG_DEBUG(DBG_BUSY
, "Write_multi: Data response busy: %d clock cycles\n",i
* 8);
763 // Only send the stop transmission if last buffer, otherwise we'll be called again
764 // with the next buffer.
767 // send stop transmission token + 1 byte till busy flag appears
771 // Busy state follows stop transmission token (dout pulled low).
772 // Keep the clock running until it's done..
773 for (i
= 1; i
< 1000000; i
++) {
774 *out
= clk_low
; *out
= clk_hi
;
775 *out
= clk_low
; *out
= clk_hi
;
776 *out
= clk_low
; *out
= clk_hi
;
777 *out
= clk_low
; *out
= clk_hi
;
778 *out
= clk_low
; *out
= clk_hi
;
779 *out
= clk_low
; *out
= clk_hi
;
780 *out
= clk_low
; *out
= clk_hi
;
781 *out
= clk_low
; *out
= clk_hi
;
782 if (*in
& do_mask
) break;
785 LOG_DEBUG(DBG_BUSY
, "Write_multi: Stop tran busy: %d clock cycles\n",i
* 8);
794 /*------------------------------------------------------------------------------
795 * spi_mmc_read_multi_o
797 * Read multiple 512 byte blocks into a buffer with the multi block read CMD18
801 * 0 - Successful write
802 * 1 - Busy wait timeout
803 * 2 - CMD18 (multi block read) error
804 * 3 - Start of data packet not received
805 * 11 - Data rejected due to crc error
806 * 14 - Data rejected due to write error
810 * - Local vars improve efficiency of generated code
811 * - Possible improvements - unsigned int array - send 32 bits at a time
812 * read 32 bits at at time...
813 *----------------------------------------------------------------------------*/
814 static INLINE
unsigned char spi_mmc_read_multi_o(unsigned int addr
, unsigned char *buf
, int blocks
, unsigned char first
, unsigned char last
) {
815 volatile unsigned char *in
= gpio_input
;
816 volatile unsigned char *out
= gpio_output
;
817 const unsigned char clk_hi
= spi_ps_d1_c1
;
818 const unsigned char clk_low
= spi_ps_d1_c0
;
819 const unsigned int do_mask
= spi_do_mask
;
825 p
= (unsigned int *) buf
; // Cast to an int pointer for 32bit io...
827 // Only send the multi block write if first first buffer in a request
828 // Otherwise it's a continuation of an already running request
831 // send multi block read command, address, crc
833 spi_io_v_o(0x40 | 18);
834 spi_io_v_o(addr
>>24);
835 spi_io_v_o(addr
>>16);
840 // wait up to 8 bytes for command response
841 for (i
= 0; i
< 8; i
++) {
843 if (r
== 0x00) break;
845 if (r
!= 0x00) goto err2
;
848 // process each block in a loop
849 for (j
=0; j
< blocks
; j
++) {
851 // wait for start of data token
852 for (i
= 1; i
< 1000000; i
++) {
854 if (r
!= 0xff) break;
860 LOG_DEBUG(DBG_BUSY
, "Read_multi: Data token busy: %d clock cycles\n",i
* 8);
862 // Read in data block a word at a time. Reduce looping overhead by doing
863 // multiple reads per an iteration of the loop.
864 for (i
= 0; i
< 512/4/4; i
++) {
865 *p
= spi_io_4ff_o(); p
++;
866 *p
= spi_io_4ff_o(); p
++;
867 *p
= spi_io_4ff_o(); p
++;
868 *p
= spi_io_4ff_o(); p
++;
871 // Read and discard the data packet crc bytes
875 // Only send the stop transmission if last buffer, otherwise we'll be called again
876 // with the next buffer.
879 // send stop transmission command, parm, crc and skip following stuff byte.
880 spi_io_v_o(0x40 | 12);
881 spi_io_6ff_v_o(); // parm (4) - crc (1) - stuff byte (1)
883 // wait up to 8 bytes for command response
884 for (i
= 0; i
< 8; i
++) {
886 if (r
== 0x00) break;
888 if (r
!= 0x00) err
=4;
890 // Busy state can follow CMD12
892 for (i
= 1; i
< 1000000; i
++) {
893 *out
= clk_low
; *out
= clk_hi
;
894 *out
= clk_low
; *out
= clk_hi
;
895 *out
= clk_low
; *out
= clk_hi
;
896 *out
= clk_low
; *out
= clk_hi
;
897 *out
= clk_low
; *out
= clk_hi
;
898 *out
= clk_low
; *out
= clk_hi
;
899 *out
= clk_low
; *out
= clk_hi
;
900 *out
= clk_low
; *out
= clk_hi
;
901 if (*in
& do_mask
) break;
904 LOG_DEBUG(DBG_BUSY
, "Read_multi: Stop tran busy: %d clock cycles\n",i
* 8);
905 if ((*in
& do_mask
) == 0) goto err1
;