blob: 31f2a7988da784be17b607404203816e70c912f6 [file] [log] [blame]
Gary Jennejohn6bd24472007-01-24 12:16:56 +01001/*
2 This code was original written by Ulrich Radig and modified by
3 Embedded Artists AB (www.embeddedartists.com).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20#include <config.h>
21#include <common.h>
22#include <asm/arch/hardware.h>
23#include "spi.h"
24
25#define MMC_Enable() PUT32(IO1CLR, 1l << 22)
26#define MMC_Disable() PUT32(IO1SET, 1l << 22)
Wolfgang Denkf8db84f2007-01-30 00:50:40 +010027#define mmc_spi_cfg() spi_set_clock(8); spi_set_cfg(0, 1, 0);
Gary Jennejohn6bd24472007-01-24 12:16:56 +010028
29static unsigned char Write_Command_MMC (unsigned char *CMD);
30static void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer,
31 unsigned short int Bytes);
32
33/* initialize the hardware */
34int mmc_hw_init(void)
35{
36 unsigned long a;
37 unsigned short int Timeout = 0;
38 unsigned char b;
39 unsigned char CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
40
41 /* set-up GPIO and SPI */
42 (*((volatile unsigned long *)PINSEL2)) &= ~(1l << 3); /* clear bit 3 */
43 (*((volatile unsigned long *)IO1DIR)) |= (1l << 22); /* set bit 22 (output) */
44
45 MMC_Disable();
46
47 spi_lock();
48 spi_set_clock(248);
49 spi_set_cfg(0, 1, 0);
50 MMC_Enable();
51
52 /* waste some time */
53 for(a=0; a < 20000; a++)
54 asm("nop");
55
56 /* Put the MMC/SD-card into SPI-mode */
57 for (b = 0; b < 10; b++) /* Sends min 74+ clocks to the MMC/SD-card */
58 spi_write(0xff);
59
60 /* Sends command CMD0 to MMC/SD-card */
61 while (Write_Command_MMC(CMD) != 1) {
62 if (Timeout++ > 200) {
63 MMC_Disable();
64 spi_unlock();
65 return(1); /* Abort with command 1 (return 1) */
66 }
67 }
68 /* Sends Command CMD1 an MMC/SD-card */
69 Timeout = 0;
70 CMD[0] = 0x41;/* Command 1 */
71 CMD[5] = 0xFF;
72
73 while (Write_Command_MMC(CMD) != 0) {
74 if (Timeout++ > 200) {
75 MMC_Disable();
76 spi_unlock();
77 return (2); /* Abort with command 2 (return 2) */
78 }
79 }
80
81 MMC_Disable();
82 spi_unlock();
83
84 return 0;
85}
86
87/* ############################################################################
88 Sends a command to the MMC/SD-card
89 ######################################################################### */
90static unsigned char Write_Command_MMC (unsigned char *CMD)
91{
92 unsigned char a, tmp = 0xff;
93 unsigned short int Timeout = 0;
94
95 MMC_Disable();
96 spi_write(0xFF);
97 MMC_Enable();
98
99 for (a = 0; a < 0x06; a++)
100 spi_write(*CMD++);
101
102 while (tmp == 0xff) {
103 tmp = spi_read();
104 if (Timeout++ > 5000)
105 break;
106 }
107
108 return (tmp);
109}
110
111/* ############################################################################
112 Routine to read the CID register from the MMC/SD-card (16 bytes)
113 ######################################################################### */
114void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer, unsigned short
115 int Bytes)
116{
117 unsigned short int a;
118
119 spi_lock();
120 mmc_spi_cfg();
121 MMC_Enable();
122
123 if (Write_Command_MMC(CMD) != 0) {
124 MMC_Disable();
125 spi_unlock();
126 return;
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100127 }
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100128
129 while (spi_read() != 0xfe) {};
130 for (a = 0; a < Bytes; a++)
131 *Buffer++ = spi_read();
132
133 /* Read the CRC-byte */
134 spi_read(); /* CRC - byte is discarded */
135 spi_read(); /* CRC - byte is discarded */
136 /* set MMC_Chip_Select to high (MMC/SD-card Inaktiv) */
137 MMC_Disable();
138 spi_unlock();
139
140 return;
141}
142
143/* ############################################################################
144 Routine to read a block (512 bytes) from the MMC/SD-card
145 ######################################################################### */
146unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
147{
148 /* Command 16 to read aBlocks from the MMC/SD - caed */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100149 unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100150
151 /* The addres on the MMC/SD-card is in bytes,
152 addr is transformed from blocks to bytes and the result is
153 placed into the command */
154
155 addr = addr << 9; /* addr = addr * 512 */
156
157 CMD[1] = ((addr & 0xFF000000) >> 24);
158 CMD[2] = ((addr & 0x00FF0000) >> 16);
159 CMD[3] = ((addr & 0x0000FF00) >> 8 );
160
161 MMC_Read_Block(CMD, Buffer, 512);
162
163 return (0);
164}
165
166/* ############################################################################
167 Routine to write a block (512 byte) to the MMC/SD-card
168 ######################################################################### */
169unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
170{
171 unsigned char tmp, a;
172 unsigned short int b;
173 /* Command 24 to write a block to the MMC/SD - card */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100174 unsigned char CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100175
176 /* The addres on the MMC/SD-card is in bytes,
177 addr is transformed from blocks to bytes and the result is
178 placed into the command */
179
180 addr = addr << 9; /* addr = addr * 512 */
181
182 CMD[1] = ((addr & 0xFF000000) >> 24);
183 CMD[2] = ((addr & 0x00FF0000) >> 16);
184 CMD[3] = ((addr & 0x0000FF00) >> 8 );
185
186 spi_lock();
187 mmc_spi_cfg();
188 MMC_Enable();
189
190 /* Send command CMD24 to the MMC/SD-card (Write 1 Block/512 Bytes) */
191 tmp = Write_Command_MMC(CMD);
192 if (tmp != 0) {
193 MMC_Disable();
194 spi_unlock();
195 return(tmp);
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100196 }
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100197
198 /* Do a short delay and send a clock-pulse to the MMC/SD-card */
199 for (a = 0; a < 100; a++)
200 spi_read();
201
202 /* Send a start byte to the MMC/SD-card */
Wolfgang Denkf8db84f2007-01-30 00:50:40 +0100203 spi_write(0xFE);
Gary Jennejohn6bd24472007-01-24 12:16:56 +0100204
205 /* Write the block (512 bytes) to the MMC/SD-card */
206 for (b = 0; b < 512; b++)
207 spi_write(*Buffer++);
208
209 /* write the CRC-Byte */
210 spi_write(0xFF); /* write a dummy CRC */
211 spi_write(0xFF); /* CRC code is not used */
212
213 /* Wait for MMC/SD-card busy */
214 while (spi_read() != 0xff) {};
215
216 /* set MMC_Chip_Select to high (MMC/SD-card inactive) */
217 MMC_Disable();
218 spi_unlock();
219 return (0);
220}
221
222/* #########################################################################
223 Routine to read the CSD register from the MMC/SD-card (16 bytes)
224 ######################################################################### */
225unsigned char mmc_read_csd (unsigned char *Buffer)
226{
227 /* Command to read the CSD register */
228 unsigned char CMD[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
229
230 MMC_Read_Block(CMD, Buffer, 16);
231
232 return (0);
233}