1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright © 2008 Rafaël Carré
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 /* Driver for the ARM PL180 SD/MMC controller inside AS3525 SoC */
24 #include "config.h" /* for HAVE_MULTIVOLUME */
34 static const int pl180_base
[2] = { NAND_FLASH_BASE
, SD_MCI_BASE
};
36 /* ARM PL180 registers */
37 #define MMC_POWER(i) (*(volatile unsigned long *) (pl180_base[i]+0x00))
38 #define MMC_CLOCK(i) (*(volatile unsigned long *) (pl180_base[i]+0x04))
39 #define MMC_ARGUMENT(i) (*(volatile unsigned long *) (pl180_base[i]+0x08))
40 #define MMC_COMMAND(i) (*(volatile unsigned long *) (pl180_base[i]+0x0C))
41 #define MMC_RESPCMD(i) (*(volatile unsigned long *) (pl180_base[i]+0x10))
42 #define MMC_RESP0(i) (*(volatile unsigned long *) (pl180_base[i]+0x14))
43 #define MMC_RESP1(i) (*(volatile unsigned long *) (pl180_base[i]+0x18))
44 #define MMC_RESP2(i) (*(volatile unsigned long *) (pl180_base[i]+0x1C))
45 #define MMC_RESP3(i) (*(volatile unsigned long *) (pl180_base[i]+0x20))
46 #define MMC_DATACTRL(i) (*(volatile unsigned long *) (pl180_base[i]+0x2C))
47 #define MMC_STATUS(i) (*(volatile unsigned long *) (pl180_base[i]+0x34))
48 #define MMC_CLEAR(i) (*(volatile unsigned long *) (pl180_base[i]+0x38))
49 #define MMC_MASK0(i) (*(volatile unsigned long *) (pl180_base[i]+0x3C))
50 #define MMC_MASK1(i) (*(volatile unsigned long *) (pl180_base[i]+0x40))
51 #define MMC_SELECT(i) (*(volatile unsigned long *) (pl180_base[i]+0x44))
55 #define GO_IDLE_STATE 0
56 #define MMC_CMD_READ_CID 2
57 #define SEND_IF_COND 8
58 #define SEND_OP_COND 41
62 #define MMC_NO_FLAGS (0<<0)
63 #define MMC_RESP (1<<0)
64 #define MMC_LONG_RESP (1<<1)
65 #define MMC_ARG (1<<2)
69 void reset_screen(void);
70 void printf(const char *format
, ...);
81 static inline void mci_delay(void) { int i
= 0xffff; while(i
--) ; }
83 static void mci_set_clock_divider(const int drive
, int divider
)
85 int clock
= MMC_CLOCK(drive
);
89 /* use divide logic */
90 clock
&= ~MCI_CLOCK_BYPASS
;
92 /* convert divider to MMC_CLOCK logic */
93 divider
= (divider
/2) - 1;
99 /* bypass dividing logic */
100 clock
|= MCI_CLOCK_BYPASS
;
104 MMC_CLOCK(drive
) = clock
| divider
;
109 static int send_cmd(const int drive
, struct mmc_command
*cmd
)
113 while(MMC_STATUS(drive
) & MCI_CMD_ACTIVE
); /* useless */
115 if(MMC_COMMAND(drive
) & MCI_COMMAND_ENABLE
) /* clears existing command */
117 MMC_COMMAND(drive
) = 0;
121 val
= cmd
->cmd
| MCI_COMMAND_ENABLE
;
122 if(cmd
->flags
& MMC_RESP
)
124 val
|= MCI_COMMAND_RESPONSE
;
125 if(cmd
->flags
& MMC_LONG_RESP
)
126 val
|= MCI_COMMAND_LONG_RESPONSE
;
129 MMC_CLEAR(drive
) = 0x7ff;
131 MMC_ARGUMENT(drive
) = (cmd
->flags
& MMC_ARG
) ? cmd
->arg
: 0;
132 MMC_COMMAND(drive
) = val
;
134 while(MMC_STATUS(drive
) & MCI_CMD_ACTIVE
);
136 MMC_COMMAND(drive
) = 0;
137 MMC_ARGUMENT(drive
) = ~0;
141 status
= MMC_STATUS(drive
);
142 if(cmd
->flags
& MMC_RESP
)
144 if(status
& MCI_CMD_TIMEOUT
)
146 if(cmd
->cmd
== SEND_IF_COND
)
147 break; /* SDHC test can fail */
148 panicf("Response timeout");
150 else if(status
& (MCI_CMD_CRC_FAIL
|MCI_CMD_RESP_END
))
151 { /* resp received */
152 cmd
->resp
[0] = MMC_RESP0(drive
);
153 if(cmd
->flags
& MMC_LONG_RESP
)
155 cmd
->resp
[1] = MMC_RESP1(drive
);
156 cmd
->resp
[2] = MMC_RESP2(drive
);
157 cmd
->resp
[3] = MMC_RESP3(drive
);
163 if(status
& MCI_CMD_SENT
)
168 MMC_CLEAR(drive
) = 0x7ff;
172 static void sd_init_card(const int drive
)
174 struct mmc_command cmd_app
, cmd_op_cond
, cmd_idle
, cmd_if_cond
;
180 printf("now - powered up");
183 cmd_idle
.cmd
= GO_IDLE_STATE
;
185 cmd_idle
.flags
= MMC_NO_FLAGS
;
186 if(send_cmd(drive
, &cmd_idle
) != MCI_CMD_SENT
)
187 panicf("goto idle failed!");
190 printf("now - idle");
195 cmd_if_cond
.cmd
= SEND_IF_COND
;
196 cmd_if_cond
.arg
= (1 /* 2.7-3.6V */ << 8) | 0xAA /* check pattern */;
197 cmd_if_cond
.flags
= MMC_RESP
| MMC_ARG
;
199 cmd_app
.cmd
= APP_CMD
;
200 cmd_app
.flags
= MMC_RESP
| MMC_ARG
;
201 cmd_app
.arg
= 0; /* 31:16 RCA (0) , 15:0 stuff bits */
203 cmd_op_cond
.cmd
= SEND_OP_COND
;
204 cmd_op_cond
.flags
= MMC_RESP
| MMC_ARG
;
207 printf("now - card powering up");
211 status
= send_cmd(drive
, &cmd_if_cond
);
212 if(status
& (MCI_CMD_CRC_FAIL
|MCI_CMD_RESP_END
))
214 if((cmd_if_cond
.resp
[0] & 0xFFF) == cmd_if_cond
.arg
)
218 printf("Bad resp: %x",cmd_if_cond
.arg
);
223 printf("cmd_if_cond stat: 0x%x",status
);
225 printf("%s Capacity",sdhc
?"High":"Normal");
239 printf("Loop number #%d", ++loop
);
242 status
= send_cmd(drive
, &cmd_app
);
243 if( !(status
& (MCI_CMD_CRC_FAIL
|MCI_CMD_RESP_END
)) ||
244 !(cmd_app
.resp
[0] & (1<<5)) )
246 panicf("app_cmd failed");
249 cmd_op_cond
.arg
= sdhc
? 0x40FF8000 : (8<<0x14); /* ocr */
250 status
= send_cmd(drive
, &cmd_op_cond
);
251 if(!(status
& (MCI_CMD_CRC_FAIL
|MCI_CMD_RESP_END
)))
252 panicf("cmd_op_cond failed");
255 printf("OP COND: 0x%.8x", cmd_op_cond
.resp
[0]);
257 } while(!(cmd_op_cond
.resp
[0] & (1<<31))); /* until card is powered up */
260 printf("now - card ready !");
264 static void init_pl180_controller(const int drive
)
266 MMC_COMMAND(drive
) = MMC_DATACTRL(drive
) = 0;
267 MMC_CLEAR(drive
) = 0x7ff;
269 MMC_MASK0(drive
) = MMC_MASK1(drive
) = 0; /* disable all interrupts */
271 MMC_POWER(drive
) = MCI_POWER_UP
|(10 /*voltage*/ << 2); /* use OF voltage */
274 MMC_POWER(drive
) |= MCI_POWER_ON
;
277 MMC_SELECT(drive
) = 0;
279 MMC_CLOCK(drive
) = MCI_CLOCK_ENABLE
;
280 MMC_CLOCK(drive
) &= ~MCI_CLOCK_POWERSAVE
;
282 /* set MCLK divider */
283 mci_set_clock_divider(drive
, 200);
288 /* reset peripherals */
291 #ifdef HAVE_MULTIVOLUME
294 CCU_SRC_NAF_EN
| CCU_SRC_IDE_EN
| CCU_SRC_IDE_AHB_EN
| CCU_SRC_MST_EN
;
296 CCU_SRL
= CCU_SRL_MAGIC_NUMBER
;
299 GPIOC_DIR
&= ~(1<<1);
301 CCU_SPARE1
|= 4; /* sets bit 2 of undocumented register */
303 CCU_SPARE1
&= ~4; /* or clear it */
305 CGU_IDE
= (1<<7)|(1<<6); /* enable, 24MHz clock */
306 CGU_MEMSTICK
= (1<<8); /* enable, 24MHz clock */
308 CGU_PERI
|= CGU_NAF_CLOCK_ENABLE
;
309 #ifdef HAVE_MULTIVOLUME
310 CGU_PERI
|= CGU_MCI_CLOCK_ENABLE
;
313 CCU_IO
&= ~8; /* bits 3:2 = 01, xpd is SD interface */
316 init_pl180_controller(NAND_AS3525
);
317 sd_init_card(NAND_AS3525
);
319 #ifdef HAVE_MULTIVOLUME
320 init_pl180_controller(SD_AS3525
);
321 sd_init_card(SD_AS3525
);
327 int ata_read_sectors(IF_MV2(int drive
,) unsigned long start
, int count
, void* buf
)
335 int ata_write_sectors(IF_MV2(int drive
,) unsigned long start
, int count
, const void* buf
)