#ifndef __EMMC_H #define __EMMC_H #include #include #include #include #include #include #include #include #include #if defined(__INTELLISENSE__) #define asm(x) /* x */ #endif #define EMMC_VERSION 1 #define EMMC_REVISION 0 #define EMMC_PRIORITY 20 #define USE_BUSY_TIMER 1 struct emmc_scr { uint32_t scr[2]; uint32_t emmc_bus_widths; int emmc_version; int emmc_commands; }; struct EMMCUnit; struct EMMCBase { struct Device emmc_Device; struct ExecBase * emmc_SysBase; APTR emmc_ROMBase; APTR emmc_DeviceTreeBase; APTR emmc_MailBox; APTR emmc_Regs; ULONG * emmc_Request; APTR emmc_RequestBase; ULONG emmc_SDHCClock; struct ConfigDev * emmc_ConfigDev; struct EMMCUnit * emmc_Units[5]; /* 5 units at most for the case where SDCard has 4 primary partitions type 0x76 */ UWORD emmc_UnitCount; struct SignalSemaphore emmc_Lock; struct timerequest emmc_TimeReq; struct MsgPort emmc_Port; struct emmc_scr emmc_SCR; UWORD emmc_BlockSize; UWORD emmc_BlocksToTransfer; APTR emmc_Buffer; ULONG emmc_Res0; ULONG emmc_Res1; ULONG emmc_Res2; ULONG emmc_Res3; ULONG emmc_CID[4]; UBYTE emmc_StatusReg[64]; CONST_STRPTR emmc_ManuID[255]; ULONG emmc_Capabilities0; ULONG emmc_Capabilities1; ULONG emmc_LastCMD; ULONG emmc_LastCMDSuccess; ULONG emmc_LastError; ULONG emmc_LastInterrupt; ULONG emmc_CardRCA; ULONG emmc_CardRemoval; ULONG emmc_FailedVoltageSwitch; ULONG emmc_CardOCR; ULONG emmc_CardSupportsSDHC; ULONG emmc_Overclock; UBYTE emmc_DisableHighSpeed; UBYTE emmc_InCommand; UBYTE emmc_AppCommand; UBYTE emmc_HideUnit0; UBYTE emmc_ReadOnlyUnit0; UBYTE emmc_Verbose; UBYTE emmc_isMicroSD; struct Interrupt emmc_Interrupt; }; struct EMMCUnit { struct Unit su_Unit; struct EMMCBase * su_Base; uint32_t su_StartBlock; uint32_t su_BlockCount; uint8_t su_UnitNum; uint8_t su_ReadOnly; struct Task * su_Caller; }; void UnitTask(); #define UNIT_TASK_PRIORITY 10 #define UNIT_TASK_STACKSIZE 16384 #define BASE_NEG_SIZE (6 * 6) #define BASE_POS_SIZE (sizeof(struct EMMCBase)) /* EMMC regs */ #define EMMC_ARG2 0 #define EMMC_BLKSIZECNT 4 #define EMMC_ARG1 8 #define EMMC_CMDTM 0xC #define EMMC_RESP0 0x10 #define EMMC_RESP1 0x14 #define EMMC_RESP2 0x18 #define EMMC_RESP3 0x1C #define EMMC_DATA 0x20 #define EMMC_STATUS 0x24 #define EMMC_CONTROL0 0x28 #define EMMC_CONTROL1 0x2C #define EMMC_INTERRUPT 0x30 #define EMMC_IRPT_MASK 0x34 #define EMMC_IRPT_EN 0x38 #define EMMC_CONTROL2 0x3C #define EMMC_CAPABILITIES_0 0x40 #define EMMC_CAPABILITIES_1 0x44 #define EMMC_FORCE_IRPT 0x50 #define EMMC_BOOT_TIMEOUT 0x70 #define EMMC_DBG_SEL 0x74 #define EMMC_EXRDFIFO_CFG 0x80 #define EMMC_EXRDFIFO_EN 0x84 #define EMMC_TUNE_STEP 0x88 #define EMMC_TUNE_STEPS_STD 0x8C #define EMMC_TUNE_STEPS_DDR 0x90 #define EMMC_SPI_INT_SPT 0xF0 #define EMMC_SLOTISR_VER 0xFC #define SD_CLOCK_ID 400000 #define SD_CLOCK_NORMAL 25000000 #define SD_CLOCK_HIGH 50000000 #define EMMC_CLOCK_ID 400000 #define EMMC_CLOCK_NORMAL 26000000 #define EMMC_CLOCK_HIGH 75000000 #define SD_CMD_INDEX(a) ((a) << 24) #define SD_CMD_TYPE_NORMAL 0x0 #define SD_CMD_TYPE_SUSPEND (1 << 22) #define SD_CMD_TYPE_RESUME (2 << 22) #define SD_CMD_TYPE_ABORT (3 << 22) #define SD_CMD_TYPE_MASK (3 << 22) #define SD_CMD_ISDATA (1 << 21) #define SD_CMD_IXCHK_EN (1 << 20) #define SD_CMD_CRCCHK_EN (1 << 19) #define SD_CMD_RSPNS_TYPE_NONE 0 // For no response #define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC) #define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC) #define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC) #define SD_CMD_RSPNS_TYPE_MASK (3 << 16) #define SD_CMD_MULTI_BLOCK (1 << 5) #define SD_CMD_DAT_DIR_HC 0 #define SD_CMD_DAT_DIR_CH (1 << 4) #define SD_CMD_AUTO_CMD_EN_NONE 0 #define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2) #define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2) #define SD_CMD_BLKCNT_EN (1 << 1) #define SD_CMD_DMA 1 #define SD_ERR_CMD_TIMEOUT 0 #define SD_ERR_CMD_CRC 1 #define SD_ERR_CMD_END_BIT 2 #define SD_ERR_CMD_INDEX 3 #define SD_ERR_DATA_TIMEOUT 4 #define SD_ERR_DATA_CRC 5 #define SD_ERR_DATA_END_BIT 6 #define SD_ERR_CURRENT_LIMIT 7 #define SD_ERR_AUTO_CMD12 8 #define SD_ERR_ADMA 9 #define SD_ERR_TUNING 10 #define SD_ERR_RSVD 11 #define SD_ERR_MASK_CMD_TIMEOUT (1 << (16 + SD_ERR_CMD_TIMEOUT)) #define SD_ERR_MASK_CMD_CRC (1 << (16 + SD_ERR_CMD_CRC)) #define SD_ERR_MASK_CMD_END_BIT (1 << (16 + SD_ERR_CMD_END_BIT)) #define SD_ERR_MASK_CMD_INDEX (1 << (16 + SD_ERR_CMD_INDEX)) #define SD_ERR_MASK_DATA_TIMEOUT (1 << (16 + SD_ERR_CMD_TIMEOUT)) #define SD_ERR_MASK_DATA_CRC (1 << (16 + SD_ERR_CMD_CRC)) #define SD_ERR_MASK_DATA_END_BIT (1 << (16 + SD_ERR_CMD_END_BIT)) #define SD_ERR_MASK_CURRENT_LIMIT (1 << (16 + SD_ERR_CMD_CURRENT_LIMIT)) #define SD_ERR_MASK_AUTO_CMD12 (1 << (16 + SD_ERR_CMD_AUTO_CMD12)) #define SD_ERR_MASK_ADMA (1 << (16 + SD_ERR_CMD_ADMA)) #define SD_ERR_MASK_TUNING (1 << (16 + SD_ERR_CMD_TUNING)) #define SD_COMMAND_COMPLETE 1 #define SD_TRANSFER_COMPLETE (1 << 1) #define SD_BLOCK_GAP_EVENT (1 << 2) #define SD_DMA_INTERRUPT (1 << 3) #define SD_BUFFER_WRITE_READY (1 << 4) #define SD_BUFFER_READ_READY (1 << 5) #define SD_CARD_INSERTION (1 << 6) #define SD_CARD_REMOVAL (1 << 7) #define SD_CARD_INTERRUPT (1 << 8) #define SUCCESS(a) (a->emmc_LastCMDSuccess) #define FAIL(a) (a->emmc_LastCMDSuccess == 0) #define TIMEOUT(a) (FAIL(a) && (a->emmc_LastError == 0)) #define CMD_TIMEOUT(a) (FAIL(a) && (a->emmc_LastError & (1 << 16))) #define CMD_CRC(a) (FAIL(a) && (a->emmc_LastError & (1 << 17))) #define CMD_END_BIT(a) (FAIL(a) && (a->emmc_LastError & (1 << 18))) #define CMD_INDEX(a) (FAIL(a) && (a->emmc_LastError & (1 << 19))) #define DATA_TIMEOUT(a) (FAIL(a) && (a->emmc_LastError & (1 << 20))) #define DATA_CRC(a) (FAIL(a) && (a->emmc_LastError & (1 << 21))) #define DATA_END_BIT(a) (FAIL(a) && (a->emmc_LastError & (1 << 22))) #define CURRENT_LIMIT(a) (FAIL(a) && (a->emmc_LastError & (1 << 23))) #define ACMD12_ERROR(a) (FAIL(a) && (a->emmc_LastError & (1 << 24))) #define ADMA_ERROR(a) (FAIL(a) && (a->emmc_LastError & (1 << 25))) #define TUNING_ERROR(a) (FAIL(a) && (a->emmc_LastError & (1 << 26))) #define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE #define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) #define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN) #define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136 | SD_CMD_CRCCHK_EN) #define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48 #define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136 #define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) #define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN) #define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) #define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) #define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH) #define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC) #define SD_CMD_RESERVED(a) 0xffffffff #define ACMD_6 (SD_CMD_INDEX(6) | SD_RESP_R1) #define ACMD_13 (SD_CMD_INDEX(13) | SD_RESP_R1) #define ACMD_22 (SD_CMD_INDEX(22) | SD_RESP_R1 | SD_DATA_READ) #define ACMD_23 (SD_CMD_INDEX(23) | SD_RESP_R1) #define ACMD_41 (SD_CMD_INDEX(41) | SD_RESP_R3) #define ACMD_42 (SD_CMD_INDEX(42) | SD_RESP_R1) #define ACMD_51 (SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ) #define IS_APP_CMD 0x80000000 #define ACMD(a) (a | IS_APP_CMD) #define SET_BUS_WIDTH (ACMD_6 | IS_APP_CMD) #define SD_STATUS (ACMD_13 | IS_APP_CMD) #define SEND_NUM_WR_BLOCKS (ACMD_22 | IS_APP_CMD) #define SET_WR_BLK_ERASE_COUNT (ACMD_23 | IS_APP_CMD) #define SD_SEND_OP_COND (ACMD_41 | IS_APP_CMD) #define SET_CLR_CARD_DETECT (ACMD_42 | IS_APP_CMD) #define SEND_SCR (ACMD_51 | IS_APP_CMD) #define CMD_0 (SD_CMD_INDEX(0)) #define CMD_1 (SD_CMD_INDEX(1) | SD_RESP_R3) #define CMD_2 (SD_CMD_INDEX(2) | SD_RESP_R2) #define CMD_3 (SD_CMD_INDEX(3) | SD_RESP_R6) #define CMD_4 (SD_CMD_INDEX(4)) #define CMD_5 (SD_CMD_INDEX(5) | SD_RESP_R4) #define CMD_6 (SD_CMD_INDEX(6) | SD_RESP_R1b) #define CMD_6_SD (SD_CMD_INDEX(6) | SD_RESP_R1 | SD_DATA_READ) #define CMD_7 (SD_CMD_INDEX(7) | SD_RESP_R1b) #define CMD_7nr (SD_CMD_INDEX(7)) #define CMD_8 (SD_CMD_INDEX(8) | SD_RESP_R7) #define CMD_9 (SD_CMD_INDEX(9) | SD_RESP_R2) #define CMD_10 (SD_CMD_INDEX(10) | SD_RESP_R2) #define CMD_11 (SD_CMD_INDEX(11) | SD_RESP_R1) #define CMD_12 (SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT) #define CMD_13 (SD_CMD_INDEX(13) | SD_RESP_R1) #define CMD_14 (SD_CMD_RESERVED(14)) #define CMD_15 (SD_CMD_INDEX(15)) #define CMD_16 (SD_CMD_INDEX(16) | SD_RESP_R1) #define CMD_17 (SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ) #define CMD_18 (SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN | SD_CMD_AUTO_CMD_EN_CMD12) #define CMD_19 (SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ) #define CMD_20 (SD_CMD_INDEX(20) | SD_RESP_R1b) #define CMD_23 (SD_CMD_INDEX(23) | SD_RESP_R1) #define CMD_24 (SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE) #define CMD_25 (SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN | SD_CMD_AUTO_CMD_EN_CMD12) #define CMD_27 (SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE) #define CMD_28 (SD_CMD_INDEX(28) | SD_RESP_R1b) #define CMD_29 (SD_CMD_INDEX(29) | SD_RESP_R1b) #define CMD_30 (SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ) #define CMD_32 (SD_CMD_INDEX(32) | SD_RESP_R1) #define CMD_33 (SD_CMD_INDEX(33) | SD_RESP_R1) #define CMD_38 (SD_CMD_INDEX(38) | SD_RESP_R1b) #define CMD_42 (SD_CMD_RESERVED(42) | SD_RESP_R1) #define CMD_55 (SD_CMD_INDEX(55) | SD_RESP_R1) #define CMD_56 (SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA) #define GO_IDLE_STATE CMD_0 #define SEND_OP_COND CMD_1 #define ALL_SEND_CID CMD_2 #define SEND_RELATIVE_ADDR CMD_3 #define SET_DSR CMD_4 #define IO_SET_OP_COND CMD_5 #define SWITCH_FUNC CMD_6_SD #define SWITCH CMD_6 #define SELECT_CARD CMD_7 #define DESELECT_CARD CMD_7nr #define SELECT_DESELECT_CARD CMD_7 #define SEND_IF_COND CMD_8 #define SEND_EXT_CSD (SD_CMD_INDEX(8) | SD_RESP_R1 | SD_DATA_READ) #define SEND_CSD CMD_9 #define SEND_CID CMD_10 #define VOLTAGE_SWITCH CMD_11 #define STOP_TRANSMISSION CMD_12 #define SEND_STATUS CMD_13 #define GO_INACTIVE_STATE CMD_15 #define SET_BLOCKLEN CMD_16 #define READ_SINGLE_BLOCK CMD_17 #define READ_MULTIPLE_BLOCK CMD_18 #define SEND_TUNING_BLOCK CMD_19 #define SPEED_CLASS_CONTROL CMD_20 #define SET_BLOCK_COUNT CMD_23 #define WRITE_BLOCK CMD_24 #define WRITE_MULTIPLE_BLOCK CMD_25 #define PROGRAM_CSD CMD_27 #define SET_WRITE_PROT CMD_28 #define CLR_WRITE_PROT CMD_29 #define SEND_WRITE_PROT CMD_30 #define ERASE_WR_BLK_START CMD_32 #define ERASE_WR_BLK_END CMD_33 #define ERASE CMD_38 #define LOCK_UNLOCK CMD_42 #define APP_CMD CMD_55 #define GEN_CMD CMD_56 #define SD_VER_UNKNOWN 0 #define SD_VER_1 1 #define SD_VER_1_1 2 #define SD_VER_2 3 #define SD_VER_3 4 #define SD_VER_4 5 #define SD_VER_5 6 #define SD_VER_6 7 #define SD_VER_7 8 #define SD_VER_8 9 #define SD_CMD20_SUPP 1 #define SD_CMD23_SUPP 2 #define SD_CMD48_49_SUPP 4 #define SD_CMD58_59_SUPP 8 #define SD_RESET_CMD (1 << 25) #define SD_RESET_DAT (1 << 26) #define SD_RESET_ALL (1 << 24) /* Endian support */ static inline uint64_t LE64(uint64_t x) { return __builtin_bswap64(x); } static inline uint32_t LE32(uint32_t x) { return __builtin_bswap32(x); } static inline uint16_t LE16(uint16_t x) { return __builtin_bswap16(x); } static inline ULONG rd32(APTR addr, ULONG offset) { APTR addr_off = (APTR)((ULONG)addr + offset); ULONG val = LE32(*(volatile ULONG *)addr_off); asm volatile("nop"); return val; } static inline void wr32(APTR addr, ULONG offset, ULONG val) { APTR addr_off = (APTR)((ULONG)addr + offset); *(volatile ULONG *)addr_off = LE32(val); asm volatile("nop"); } static inline ULONG rd32be(APTR addr, ULONG offset) { APTR addr_off = (APTR)((ULONG)addr + offset); ULONG val = *(volatile ULONG *)addr_off; asm volatile("nop"); return val; } static inline void wr32be(APTR addr, ULONG offset, ULONG val) { APTR addr_off = (APTR)((ULONG)addr + offset); *(volatile ULONG *)addr_off = val; asm volatile("nop"); } /* Misc */ static inline void putch(UBYTE data asm("d0"), APTR ignore asm("a3")) { *(UBYTE*)0xdeadbeef = data; } void kprintf(const char * msg asm("a0"), void * args asm("a1")); void delay(ULONG us, struct EMMCBase *EMMCBase); ULONG EMMC_Expunge(struct EMMCBase * EMMCBase asm("a6")); APTR EMMC_ExtFunc(struct EMMCBase * EMMCBase asm("a6")); void EMMC_Open(struct IORequest * io asm("a1"), LONG unitNumber asm("d0"), ULONG flags asm("d1")); ULONG EMMC_Close(struct IORequest * io asm("a1")); void EMMC_BeginIO(struct IORequest *io asm("a1")); LONG EMMC_AbortIO(struct IORequest *io asm("a1")); #define bug(string, ...) \ do { ULONG args[] = {0, __VA_ARGS__}; kprintf(string, &args[1]); } while(0) #define TIMEOUT_WAIT(check_func, tout) \ do { ULONG cnt = (tout) / 2; if (cnt == 0) cnt = 1; while(cnt != 0) { if (check_func) break; \ cnt = cnt - 1; delay(2, EMMCBase); } } while(0) void led(int on, struct EMMCBase *EMMCBase); void int_do_io(struct IORequest *io , struct EMMCBase * EMMCBase); void emmc_cmd(ULONG command, ULONG arg, ULONG timeout, struct EMMCBase *EMMCBase); int emmc_card_init(struct EMMCBase *EMMCBase); int emmc_read(uint8_t *buf, uint32_t buf_size, uint32_t block_no, struct EMMCBase *EMMCBase); int emmc_write(uint8_t *buf, uint32_t buf_size, uint32_t block_no, struct EMMCBase *EMMCBase); #endif /* __EMMC_H */