2 Copyright © 2013, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <aros/bootloader.h>
10 #include <aros/symbolsets.h>
11 #include <exec/exec.h>
12 #include <exec/resident.h>
13 #include <exec/tasks.h>
14 #include <exec/memory.h>
15 #include <exec/nodes.h>
16 #include <utility/utility.h>
17 #include <libraries/expansion.h>
18 #include <libraries/configvars.h>
20 #include <dos/dosextens.h>
21 #include <dos/filehandler.h>
23 #include <proto/exec.h>
24 #include <proto/timer.h>
25 #include <proto/bootloader.h>
26 #include <proto/expansion.h>
27 #include <proto/utility.h>
28 #include <proto/vcmbox.h>
30 #include <asm/bcm2835.h>
31 #include <hardware/videocore.h>
32 #include <hardware/mmc.h>
33 #include <hardware/sdhc.h>
37 #include "sdcard_intern.h"
40 #include LC_LIBDEFS_FILE
42 UBYTE
FNAME_SDCBUS(MMIOReadByte
)(ULONG reg
, struct sdcard_Bus
*bus
)
44 ULONG val
= *(volatile ULONG
*)(((ULONG
)bus
->sdcb_IOBase
+ reg
) & ~3);
46 return (val
>> ((reg
& 3) << 3)) & 0xff;
49 UWORD
FNAME_SDCBUS(MMIOReadWord
)(ULONG reg
, struct sdcard_Bus
*bus
)
51 ULONG val
= *(volatile ULONG
*)(((ULONG
)bus
->sdcb_IOBase
+ reg
) & ~3);
53 return (val
>> (((reg
>> 1) & 1) << 4)) & 0xffff;
56 ULONG
FNAME_SDCBUS(MMIOReadLong
)(ULONG reg
, struct sdcard_Bus
*bus
)
58 return *(volatile ULONG
*)(bus
->sdcb_IOBase
+ reg
);
61 void FNAME_SDCBUS(ArasanWriteLong
)(ULONG reg
, ULONG val
, struct sdcard_Bus
*bus
)
63 /* Bug: two SDC clock cycle delay required between successive chipset writes */
64 while (*((volatile ULONG
*)(SYSTIMER_CLO
)) < (bus
->sdcb_LastWrite
+ 100))
65 asm volatile("mov r0, r0\n");
67 *(volatile ULONG
*)(bus
->sdcb_IOBase
+ reg
) = val
;
68 bus
->sdcb_LastWrite
= *((volatile ULONG
*)(SYSTIMER_CLO
));
71 void FNAME_SDCBUS(MMIOWriteByte
)(ULONG reg
, UBYTE val
, struct sdcard_Bus
*bus
)
73 ULONG currval
= *(volatile ULONG
*)(((ULONG
)bus
->sdcb_IOBase
+ reg
) & ~3);
74 ULONG shift
= (reg
& 3) * 8;
75 ULONG mask
= 0xff << shift
;
76 ULONG newval
= (currval
& ~mask
) | (val
<< shift
);
78 FNAME_SDCBUS(ArasanWriteLong
)(reg
& ~3, newval
, bus
);
81 void FNAME_SDCBUS(MMIOWriteWord
)(ULONG reg
, UWORD val
, struct sdcard_Bus
*bus
)
83 ULONG currval
= *(volatile ULONG
*)(((ULONG
)bus
->sdcb_IOBase
+ reg
) & ~3);
84 ULONG shift
= ((reg
>> 1) & 1) * 16;
85 ULONG mask
= 0xffff << shift
;
86 ULONG newval
= (currval
& ~mask
) | (val
<< shift
);
88 FNAME_SDCBUS(ArasanWriteLong
)(reg
& ~3, newval
, bus
);
91 void FNAME_SDCBUS(MMIOWriteLong
)(ULONG reg
, ULONG val
, struct sdcard_Bus
*bus
)
93 FNAME_SDCBUS(ArasanWriteLong
)(reg
, val
, bus
);
96 void FNAME_SDCBUS(SoftReset
)(UBYTE mask
, struct sdcard_Bus
*bus
)
98 ULONG timeout
= 10000, timeout_udelay
;
100 FNAME_SDCBUS(MMIOWriteByte
)(SDHCI_RESET
, mask
, bus
);
101 while (FNAME_SDCBUS(MMIOReadByte
)(SDHCI_RESET
, bus
) & mask
) {
103 D(bug("[SDCard--] %s: Timeout\n", __PRETTY_FUNCTION__
));
106 timeout_udelay
= timeout
- 1000;
107 for (; timeout
> timeout_udelay
; timeout
--) asm volatile("mov r0, r0\n");
111 ULONG
FNAME_SDCBUS(SendCmd
)(struct TagItem
*CmdTags
, struct sdcard_Bus
*bus
)
113 struct TagItem
*Response
= NULL
;
115 UWORD sdCommand
= (UWORD
)GetTagData(SDCARD_TAG_CMD
, 0, CmdTags
);
116 ULONG sdArg
= GetTagData(SDCARD_TAG_ARG
, 0, CmdTags
);
117 ULONG sdResponseType
= GetTagData(SDCARD_TAG_RSPTYPE
, MMC_RSP_NONE
, CmdTags
);
118 ULONG sdData
, sdDataLen
= 0, sdDataFlags
;
120 UWORD sdcTransMode
= 0, sdCommandFlags
;
121 ULONG sdStatus
= 0, sdCommandMask
= SDHCI_PS_CMD_INHIBIT
;
122 ULONG timeout
= 10000, timeout_udelay
;
125 if (sdResponseType
!= MMC_RSP_NONE
)
127 Response
= FindTagItem(SDCARD_TAG_RSP
, CmdTags
);
130 if ((sdData
= GetTagData(SDCARD_TAG_DATA
, 0, CmdTags
)) != 0)
132 sdDataLen
= GetTagData(SDCARD_TAG_DATALEN
, 0, CmdTags
);
133 sdDataFlags
= GetTagData(SDCARD_TAG_DATAFLAGS
, 0, CmdTags
);
138 /* Dont wait for DATA inihibit for stop commands */
139 if (sdCommand
!= MMC_CMD_STOP_TRANSMISSION
)
140 sdCommandMask
|= SDHCI_PS_DATA_INHIBIT
;
142 while (FNAME_SDCBUS(MMIOReadLong
)(SDHCI_PRESENT_STATE
, bus
) & sdCommandMask
) {
144 D(bug("[SDCard--] %s: Controller failed to release inhibited bit(s).\n", __PRETTY_FUNCTION__
));
147 timeout_udelay
= timeout
- 1000;
148 for (; timeout
> timeout_udelay
; timeout
--)
149 asm volatile("mov r0, r0\n");
152 sdCommandMask
= SDHCI_INT_RESPONSE
;
153 if (!(sdResponseType
& MMC_RSP_PRESENT
))
154 sdCommandFlags
= SDHCI_CMD_RESP_NONE
;
155 else if (sdResponseType
& MMC_RSP_136
)
156 sdCommandFlags
= SDHCI_CMD_RESP_LONG
;
157 else if (sdResponseType
& MMC_RSP_BUSY
) {
158 sdCommandFlags
= SDHCI_CMD_RESP_SHORT_BUSY
;
159 sdCommandMask
|= SDHCI_INT_DATA_END
;
161 sdCommandFlags
= SDHCI_CMD_RESP_SHORT
;
163 if (sdResponseType
& MMC_RSP_CRC
)
164 sdCommandFlags
|= SDHCI_CMD_CRC
;
165 if (sdResponseType
& MMC_RSP_OPCODE
)
166 sdCommandFlags
|= SDHCI_CMD_INDEX
;
168 sdCommandFlags
|= SDHCI_CMD_DATA
;
171 sdcTransMode
= SDHCI_TRANSMOD_BLK_CNT_EN
;
172 D(bug("[SDCard--] %s: Configuring Data Transfer\n", __PRETTY_FUNCTION__
));
174 *(volatile ULONG
*)GPCLR0
= 1<<16; // Turn Activity LED ON
176 FNAME_SDCBUS(MMIOWriteByte
)(SDHCI_TIMEOUT_CONTROL
, 0xe, bus
);
178 FNAME_SDCBUS(MMIOWriteWord
)(SDHCI_BLOCK_SIZE
, 1 << bus
->sdcb_SectorShift
, bus
);
179 if ((sdDataLen
>> bus
->sdcb_SectorShift
) > 1)
181 sdcTransMode
|= SDHCI_TRANSMOD_MULTI
;
182 FNAME_SDCBUS(MMIOWriteWord
)(SDHCI_BLOCK_COUNT
, sdDataLen
>> bus
->sdcb_SectorShift
, bus
);
186 FNAME_SDCBUS(MMIOWriteWord
)(SDHCI_BLOCK_COUNT
, 1, bus
);
189 if (sdDataFlags
== MMC_DATA_READ
)
190 sdcTransMode
|= SDHCI_TRANSMOD_READ
;
192 D(bug("[SDCard--] %s: Mode %08x, BlockSize %d, Count %d\n", __PRETTY_FUNCTION__
, sdcTransMode
, 1 << bus
->sdcb_SectorShift
, sdDataLen
>> bus
->sdcb_SectorShift
));
195 FNAME_SDCBUS(MMIOWriteLong
)(SDHCI_ARGUMENT
, sdArg
, bus
);
197 FNAME_SDCBUS(MMIOWriteLong
)(SDHCI_TRANSFER_MODE
, (sdcTransMode
<< 16) | SDHCI_MAKE_CMD(sdCommand
, sdCommandFlags
), bus
);
199 FNAME_SDCBUS(MMIOWriteWord
)(SDHCI_COMMAND
, SDHCI_MAKE_CMD(sdCommand
, sdCommandFlags
), bus
);
203 sdStatus
= FNAME_SDCBUS(MMIOReadLong
)(SDHCI_INT_STATUS
, bus
);
204 if (sdStatus
& SDHCI_INT_ERROR
)
208 } while ((sdStatus
& sdCommandMask
) != sdCommandMask
);
211 if ((sdStatus
& (sdCommandMask
|SDHCI_INT_ERROR
)) == sdCommandMask
) {
212 if (sdStatus
& SDHCI_INT_ERROR
)
214 D(bug("[SDCard--] %s: Error?", __PRETTY_FUNCTION__
));
219 D(bug("[SDCard--] %s: Reading Response ", __PRETTY_FUNCTION__
));
220 if (sdResponseType
& MMC_RSP_136
)
222 D(bug("[136bit]\n"));
223 if (Response
->ti_Data
)
226 for (i
= 0; i
< 4; i
++)
228 ((ULONG
*)Response
->ti_Data
)[i
] = FNAME_SDCBUS(MMIOReadLong
)(SDHCI_RESPONSE
+ (3 - i
) * 4, bus
) << 8;
230 ((ULONG
*)Response
->ti_Data
)[i
] |= FNAME_SDCBUS(MMIOReadByte
)(SDHCI_RESPONSE
+ (3 - i
) * 4 - 1, bus
);
237 Response
->ti_Data
= FNAME_SDCBUS(MMIOReadLong
)(SDHCI_RESPONSE
, bus
);
240 FNAME_SDCBUS(MMIOWriteLong
)(SDHCI_INT_STATUS
, sdCommandMask
, bus
);
244 D(bug("[SDCard--] %s: Failed? [status = %08x]\n", __PRETTY_FUNCTION__
, sdStatus
));
250 D(bug("[SDCard--] %s: Transfering Data..\n", __PRETTY_FUNCTION__
));
252 sdCommand
= SDHCI_INT_SPACE_AVAIL
| SDHCI_INT_DATA_AVAIL
;
253 sdCommandMask
= SDHCI_PS_DATA_AVAILABLE
| SDHCI_PS_SPACE_AVAILABLE
;
255 sdStatus
= FNAME_SDCBUS(MMIOReadLong
)(SDHCI_INT_STATUS
, bus
);
256 if (sdStatus
& SDHCI_INT_ERROR
) {
257 D(bug("[SDCard--] %s: Error [status 0x%X]!\n", __PRETTY_FUNCTION__
, sdStatus
));
261 if (sdStatus
& sdCommand
) {
262 if (!(FNAME_SDCBUS(MMIOReadLong
)(SDHCI_PRESENT_STATE
, bus
) & sdCommandMask
))
264 FNAME_SDCBUS(MMIOWriteLong
)(SDHCI_INT_STATUS
, sdCommand
, bus
);
265 #warning "TODO: Transfer bytes ;)"
269 D(bug("[SDCard--] %s: Timeout!\n", __PRETTY_FUNCTION__
));
273 } while (!(sdStatus
& SDHCI_INT_DATA_END
));
278 D(bug("[SDCard--] %s: Error - command timed out\n", __PRETTY_FUNCTION__
));
283 for (; timeout
> timeout_udelay
; timeout
--) asm volatile("mov r0, r0\n");
285 *(volatile ULONG
*)GPSET0
= (1 << 16); // Turn Activity LED OFF
287 sdStatus
= FNAME_SDCBUS(MMIOReadLong
)(SDHCI_INT_STATUS
, bus
);
288 FNAME_SDCBUS(MMIOWriteLong
)(SDHCI_INT_STATUS
, SDHCI_INT_ALL_MASK
, bus
);
293 D(bug("[SDCard--] %s: Reseting SDHCI CMD/DATA\n", __PRETTY_FUNCTION__
));
295 FNAME_SDCBUS(SoftReset
)(SDHCI_RESET_CMD
, bus
);
296 FNAME_SDCBUS(SoftReset
)(SDHCI_RESET_DATA
, bus
);
297 if (sdStatus
& SDHCI_INT_TIMEOUT
)
303 ULONG
FNAME_SDCBUS(Rsp136Unpack
)(ULONG
*buf
, ULONG offset
, const ULONG len
)
305 const ULONG mask
= ((len
< 32) ? (1 << len
) : 0) - 1;
306 const ULONG shift
= (offset
) & 0x1F;
309 retval
= buf
[3 - (offset
>> 5)] >> shift
;
310 if (len
+ shift
> 32)
311 retval
|= buf
[3 - (offset
>> 5) - 1] << ((32 - shift
) % 32);
313 return (retval
& mask
);
317 int FNAME_SDCBUS(SDUnitSwitch
)(BOOL test
, int group
, UBYTE value
, APTR buf
, struct sdcard_Unit
*sdcUnit
)
319 struct TagItem sdcSwitchTags
[] =
321 {SDCARD_TAG_CMD
, SD_CMD_SWITCH_FUNC
},
323 {SDCARD_TAG_RSPTYPE
, MMC_RSP_R1
},
325 {SDCARD_TAG_DATA
, buf
},
326 {SDCARD_TAG_DATALEN
, 64},
327 {SDCARD_TAG_DATAFLAGS
, MMC_DATA_READ
},
331 D(bug("[SDCard%02ld] %s()\n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
333 sdcSwitchTags
[1].ti_Data
= ((test
) ? 0 : (1 << 31)) | 0xffffff;
334 sdcSwitchTags
[1].ti_Data
&= ~(0xf << (group
* 4));
335 sdcSwitchTags
[1].ti_Data
|= value
<< (group
* 4);
337 return FNAME_SDCBUS(SendCmd
)(sdcSwitchTags
, sdcUnit
->sdcu_Bus
);
341 int FNAME_SDCBUS(SDUnitChangeFrequency
)(struct sdcard_Unit
*sdcUnit
)
343 unsigned int timeout
;
344 struct TagItem sdcChFreqTags
[] =
348 {SDCARD_TAG_RSPTYPE
, 0},
350 {TAG_DONE
, 0}, /* SDCARD_TAG_DATA */
351 {SDCARD_TAG_DATALEN
, 0},
352 {SDCARD_TAG_DATAFLAGS
, MMC_DATA_READ
},
356 /* Read the SCR to find out if higher speeds are supported ..*/
358 D(bug("[SDCard%02ld] %s: Attempt to send App Command ... \n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
359 sdcChFreqTags
[0].ti_Data
= MMC_CMD_APP_CMD
;
360 sdcChFreqTags
[1].ti_Data
= sdcUnit
->sdcu_CardRCA
<< 16;
361 sdcChFreqTags
[2].ti_Data
= MMC_RSP_R1
;
362 if (FNAME_SDCBUS(SendCmd
)(sdcChFreqTags
, sdcUnit
->sdcu_Bus
) != -1)
364 ULONG sdcardRespBuf
[2] = {0, 0};
366 sdcChFreqTags
[0].ti_Data
= SD_CMD_APP_SEND_SCR
;
367 sdcChFreqTags
[1].ti_Data
= 0;
368 sdcChFreqTags
[2].ti_Data
= MMC_RSP_R1
;
371 D(bug("[SDCard%02ld] %s: Attempt to Query SCR Register ... \n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
374 sdcChFreqTags
[4].ti_Tag
= SDCARD_TAG_DATA
;
375 sdcChFreqTags
[4].ti_Data
= sdcardRespBuf
;
376 sdcChFreqTags
[5].ti_Data
= 8;
378 if (FNAME_SDCBUS(SendCmd
)(sdcChFreqTags
, sdcUnit
->sdcu_Bus
) != -1)
380 } while (timeout
-- > 0);
384 if (AROS_BE2LONG(sdcardRespBuf
[0]) & SD_SCR_DATA4BIT
)
385 sdcUnit
->sdcu_Flags
|= AF_4bitData
;
387 /* v1.0 SDCards don't support switching */
388 if (((AROS_BE2LONG(sdcardRespBuf
[0]) >> 24) & 0xf) < 1)
390 D(bug("[SDCard%02ld] %s: Card doesnt support Switching\n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
395 while (timeout
-- > 0) {
396 if (FNAME_SDCBUS(SDUnitSwitch
)(TRUE
, 0, 1, sdcardRespBuf
, sdcUnit
) != -1)
398 /* The high-speed function is busy. Try again */
399 if (!(AROS_BE2LONG(sdcardRespBuf
[7]) & SD_SCR_HIGHSPEED
))
404 D(bug("[SDCard%02ld] %s: Switch failed\n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
411 /* Is high-speed supported? */
412 if (!(AROS_BE2LONG(sdcardRespBuf
[3]) & SD_SCR_HIGHSPEED
))
414 D(bug("[SDCard%02ld] %s: Card doesnt support Highspeed mode\n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
418 if (FNAME_SDCBUS(SDUnitSwitch
)(FALSE
, 0, 1, sdcardRespBuf
, sdcUnit
) != -1)
420 if ((AROS_BE2LONG(sdcardRespBuf
[4]) & 0x0F000000) == 0x01000000)
421 sdcUnit
->sdcu_Flags
|= AF_HighSpeed
;
427 D(bug("[SDCard%02ld] %s: Query Failed\n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
432 D(bug("[SDCard%02ld] %s: App Command Failed\n", sdcUnit
->sdcu_UnitNum
, __PRETTY_FUNCTION__
));
436 void FNAME_SDCBUS(BusTask
)(struct sdcard_Bus
*bus
)
438 struct SDCardBase
*SDCardBase
= bus
->sdcb_DeviceBase
;
439 struct sdcard_Unit
*unit
;
440 struct IORequest
*msg
;
444 D(bug("[SDCard**] Task started (bus: %u)\n", bus
->sdcb_BusNum
));
446 bus
->sdcb_Timer
= sdcard_OpenTimer(SDCardBase
);
448 /* Get the signal used for sleeping */
449 bus
->sdcb_Task
= FindTask(0);
450 bus
->sdcb_TaskSig
= AllocSignal(-1);
451 /* Failed to get it? Use SIGBREAKB_CTRL_E instead */
452 if (bus
->sdcb_TaskSig
< 0)
453 bus
->sdcb_TaskSig
= SIGBREAKB_CTRL_E
;
455 sig
= 1L << bus
->sdcb_MsgPort
->mp_SigBit
;
457 sdcReg
= FNAME_SDCBUS(MMIOReadLong
)(SDHCI_PRESENT_STATE
, bus
);
458 if (sdcReg
& SDHCI_PS_CARD_PRESENT
)
460 FNAME_SDC(RegisterVolume
)(bus
);
463 /* Wait forever and process messages */
468 /* Even if you get new signal, do not process it until Unit is not active */
469 if (!(bus
->sdcb_BusFlags
& UNITF_ACTIVE
))
471 bus
->sdcb_BusFlags
|= UNITF_ACTIVE
;
473 /* Empty the request queue */
474 while ((msg
= (struct IORequest
*)GetMsg(bus
->sdcb_MsgPort
)))
477 if (FNAME_SDC(HandleIO
)(msg
))
479 ReplyMsg((struct Message
*)msg
);
483 bus
->sdcb_BusFlags
&= ~(UNITF_INTASK
| UNITF_ACTIVE
);