]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/glsdk-u-boot.git/blob - arch/arm/cpu/arm720t/lpc2292/mmc_hw.c
am335x: add initial AM335x IDK board support
[glsdk/glsdk-u-boot.git] / arch / arm / cpu / arm720t / lpc2292 / mmc_hw.c
1 /*
2     This code was original written by Ulrich Radig and modified by
3     Embedded Artists AB (www.embeddedartists.com).
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.
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.
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 */
20 #include <config.h>
21 #include <common.h>
22 #include <asm/arch/hardware.h>
23 #include <asm/arch/spi.h>
25 #define MMC_Enable() PUT32(IO1CLR, 1l << 22)
26 #define MMC_Disable() PUT32(IO1SET, 1l << 22)
27 #define mmc_spi_cfg() spi_set_clock(8); spi_set_cfg(0, 1, 0);
29 static unsigned char Write_Command_MMC (unsigned char *CMD);
30 static void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer,
31                     unsigned short int Bytes);
33 /* initialize the hardware */
34 int 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};
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) */
45         MMC_Disable();
47         spi_lock();
48         spi_set_clock(248);
49         spi_set_cfg(0, 1, 0);
50         MMC_Enable();
52         /* waste some time */
53         for(a=0; a < 20000; a++)
54                 asm("nop");
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);
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;
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         }
81         MMC_Disable();
82         spi_unlock();
84         return 0;
85 }
87 /* ############################################################################
88    Sends a command to the MMC/SD-card
89    ######################################################################### */
90 static unsigned char Write_Command_MMC (unsigned char *CMD)
91 {
92         unsigned char a, tmp = 0xff;
93         unsigned short int Timeout = 0;
95         MMC_Disable();
96         spi_write(0xFF);
97         MMC_Enable();
99         for (a = 0; a < 0x06; a++)
100                 spi_write(*CMD++);
102         while (tmp == 0xff) {
103                 tmp = spi_read();
104                 if (Timeout++ > 5000)
105                   break;
106         }
108         return (tmp);
111 /* ############################################################################
112    Routine to read the CID register from the MMC/SD-card (16 bytes)
113    ######################################################################### */
114 void MMC_Read_Block(unsigned char *CMD, unsigned char *Buffer, unsigned short
115         int Bytes)
117         unsigned short int a;
119         spi_lock();
120         mmc_spi_cfg();
121         MMC_Enable();
123         if (Write_Command_MMC(CMD) != 0) {
124                 MMC_Disable();
125                 spi_unlock();
126                 return;
127         }
129         while (spi_read() != 0xfe) {};
130         for (a = 0; a < Bytes; a++)
131                 *Buffer++ = spi_read();
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();
140         return;
143 /* ############################################################################
144    Routine to read a block (512 bytes) from the MMC/SD-card
145    ######################################################################### */
146 unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
148         /* Command 16 to read aBlocks from the MMC/SD - caed */
149         unsigned char CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
151         /* The address 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 */
155         addr = addr << 9; /* addr = addr * 512 */
157         CMD[1] = ((addr & 0xFF000000) >> 24);
158         CMD[2] = ((addr & 0x00FF0000) >> 16);
159         CMD[3] = ((addr & 0x0000FF00) >> 8 );
161         MMC_Read_Block(CMD, Buffer, 512);
163         return (0);
166 /* ############################################################################
167    Routine to write a block (512 byte) to the MMC/SD-card
168    ######################################################################### */
169 unsigned char mmc_write_sector (unsigned long addr,unsigned char *Buffer)
171         unsigned char tmp, a;
172         unsigned short int b;
173         /* Command 24 to write a block to the MMC/SD - card */
174         unsigned char CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
176         /* The address 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 */
180         addr = addr << 9; /* addr = addr * 512 */
182         CMD[1] = ((addr & 0xFF000000) >> 24);
183         CMD[2] = ((addr & 0x00FF0000) >> 16);
184         CMD[3] = ((addr & 0x0000FF00) >> 8 );
186         spi_lock();
187         mmc_spi_cfg();
188         MMC_Enable();
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);
196         }
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();
202         /* Send a start byte to the MMC/SD-card */
203         spi_write(0xFE);
205         /* Write the block (512 bytes) to the MMC/SD-card */
206         for (b = 0; b < 512; b++)
207                 spi_write(*Buffer++);
209         /* write the CRC-Byte */
210         spi_write(0xFF); /* write a dummy CRC */
211         spi_write(0xFF); /* CRC code is not used */
213         /* Wait for MMC/SD-card busy */
214         while (spi_read() != 0xff) {};
216         /* set MMC_Chip_Select to high (MMC/SD-card inactive) */
217         MMC_Disable();
218         spi_unlock();
219         return (0);
222 /* #########################################################################
223    Routine to read the CSD register from the MMC/SD-card (16 bytes)
224    ######################################################################### */
225 unsigned char mmc_read_csd (unsigned char *Buffer)
227         /* Command to read the CSD register */
228         unsigned char CMD[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
230         MMC_Read_Block(CMD, Buffer, 16);
232         return (0);