#include #include #include "emmc.h" #include "mbox.h" int emmc_power_cycle(struct EMMCBase *EMMCBase) { struct ExecBase *SysBase = EMMCBase->emmc_SysBase; bug("[brcm-emmc] powerCycle\n"); bug("[brcm-emmc] power OFF\n"); set_power_state(0, 2, EMMCBase); set_extgpio_state(6, 0, EMMCBase); delay(500000, EMMCBase); bug("[brcm-emmc] power ON\n"); set_extgpio_state(6, 1, EMMCBase); return set_power_state(0, 3, EMMCBase); } void led(int on, struct EMMCBase *EMMCBase) { if (on) { wr32((APTR)0xf2200000, 0x20, 1 << 10); } else { wr32((APTR)0xf2200000, 0x2c, 1 << 10); } } void cmd_int(ULONG cmd, ULONG arg, ULONG timeout, struct EMMCBase *EMMCBase) { struct ExecBase *SysBase = EMMCBase->emmc_SysBase; ULONG tout = 0; EMMCBase->emmc_LastCMDSuccess = 0; // Check Command Inhibit while(rd32(EMMCBase->emmc_Regs, EMMC_STATUS) & 0x1) delay(10, EMMCBase); // Is the command with busy? if((cmd & SD_CMD_RSPNS_TYPE_MASK) == SD_CMD_RSPNS_TYPE_48B) { // With busy // Is is an abort command? if((cmd & SD_CMD_TYPE_MASK) != SD_CMD_TYPE_ABORT) { // Not an abort command // Wait for the data line to be free while(rd32(EMMCBase->emmc_Regs, EMMC_STATUS) & 0x2) delay(10, EMMCBase); } } uint32_t blksizecnt = EMMCBase->emmc_BlockSize | (EMMCBase->emmc_BlocksToTransfer << 16); wr32(EMMCBase->emmc_Regs, EMMC_BLKSIZECNT, blksizecnt); // Set argument 1 reg wr32(EMMCBase->emmc_Regs, EMMC_ARG1, arg); #if 0 { ULONG args[] = {cmd, arg}; RawDoFmt("[brcm-emmc] sending command %08lx, arg %08lx\n", args, (APTR)putch, NULL); } #endif // Set command reg wr32(EMMCBase->emmc_Regs, EMMC_CMDTM, cmd); asm volatile("nop"); //SDCardBase->sd_Delay(10, SDCardBase); // Wait for command complete interrupt TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT) & 0x8001), timeout); uint32_t irpts = rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT); // Clear command complete status wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffff0001); // Test for errors if((irpts & 0xffff0001) != 0x1) { bug("[brcm-emmc] Error occured whilst waiting for command complete interrupt (%08lx)\n", irpts); EMMCBase->emmc_LastError = irpts & 0xffff0000; EMMCBase->emmc_LastInterrupt = irpts; return; } // SDCardBase->sd_Delay(10, SDCardBase); asm volatile("nop"); // Get response data switch(cmd & SD_CMD_RSPNS_TYPE_MASK) { case SD_CMD_RSPNS_TYPE_48: case SD_CMD_RSPNS_TYPE_48B: EMMCBase->emmc_Res0 = rd32(EMMCBase->emmc_Regs, EMMC_RESP0); break; case SD_CMD_RSPNS_TYPE_136: EMMCBase->emmc_Res0 = rd32(EMMCBase->emmc_Regs, EMMC_RESP0); EMMCBase->emmc_Res1 = rd32(EMMCBase->emmc_Regs, EMMC_RESP1); EMMCBase->emmc_Res2 = rd32(EMMCBase->emmc_Regs, EMMC_RESP2); EMMCBase->emmc_Res3 = rd32(EMMCBase->emmc_Regs, EMMC_RESP3); break; } // If with data, wait for the appropriate interrupt if(cmd & SD_CMD_ISDATA) { uint32_t wr_irpt; int is_write = 0; if(cmd & SD_CMD_DAT_DIR_CH) wr_irpt = (1 << 5); // read else { is_write = 1; wr_irpt = (1 << 4); // write } int cur_block = 0; uint32_t *cur_buf_addr = (uint32_t *)EMMCBase->emmc_Buffer; while(cur_block < EMMCBase->emmc_BlocksToTransfer) { tout = timeout / 100; TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT) & (wr_irpt | 0x8000)), timeout); irpts = rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT); wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffff0000 | wr_irpt); if((irpts & (0xffff0000 | wr_irpt)) != wr_irpt) { bug("[brcm-emmc] Error occured whilst waiting for data ready interrupt (%08lx)\n", irpts); EMMCBase->emmc_LastError = irpts & 0xffff0000; EMMCBase->emmc_LastInterrupt = irpts; return; } // Transfer the block UWORD cur_byte_no = 0; while(cur_byte_no < EMMCBase->emmc_BlockSize) { if(is_write) { uint32_t data = *(ULONG*)cur_buf_addr; wr32be(EMMCBase->emmc_Regs, EMMC_DATA, data); } else { uint32_t data = rd32be(EMMCBase->emmc_Regs, EMMC_DATA); *(ULONG*)cur_buf_addr = data; } cur_byte_no += 4; cur_buf_addr++; } cur_block++; } } // Wait for transfer complete (set if read/write transfer or with busy) if((((cmd & SD_CMD_RSPNS_TYPE_MASK) == SD_CMD_RSPNS_TYPE_48B) || (cmd & SD_CMD_ISDATA))) { // First check command inhibit (DAT) is not already 0 if((rd32(EMMCBase->emmc_Regs, EMMC_STATUS) & 0x2) == 0) wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffff0002); else { TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT) & 0x8002), timeout); irpts = rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT); wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffff0002); // Handle the case where both data timeout and transfer complete // are set - transfer complete overrides data timeout: HCSS 2.2.17 if(((irpts & 0xffff0002) != 0x2) && ((irpts & 0xffff0002) != 0x100002)) { bug("[brcm-emmc] Error occured whilst waiting for transfer complete interrupt (%08lx)\n", irpts); EMMCBase->emmc_LastError = irpts & 0xffff0000; EMMCBase->emmc_LastInterrupt = irpts; return; } wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffff0002); } } EMMCBase->emmc_LastCMDSuccess = 1; } // Reset host static int emmc_reset_host(struct EMMCBase *EMMCBase) { int tout = 1000000; uint32_t control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= SD_RESET_ALL; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); while (tout && (rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & SD_RESET_ALL) != 0) { delay(1, EMMCBase); tout--; } if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & SD_RESET_ALL) != 0) { bug("[brcm-emmc] reset ALL timed out, Control1: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1)); return -1; } return 0; } // Reset the CMD line static int emmc_reset_cmd(struct EMMCBase *EMMCBase) { int tout = 1000000; uint32_t control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= SD_RESET_CMD; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); while (tout && (rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & SD_RESET_CMD) != 0) { delay(1, EMMCBase); tout--; } if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & SD_RESET_CMD) != 0) { bug("[brcm-emmc] reset CMD timed out, Control1: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1)); return -1; } return 0; } // Reset the CMD line static int emmc_reset_dat(struct EMMCBase *EMMCBase) { int tout = 1000000; uint32_t control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= SD_RESET_DAT; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); while (tout && (rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & SD_RESET_DAT) != 0) { delay(1, EMMCBase); tout--; } if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & SD_RESET_DAT) != 0) { bug("[brcm-emmc] reset DAT timed out, Control1: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1)); return -1; } return 0; } static void emmc_handle_card_interrupt(struct EMMCBase *EMMCBase) { struct ExecBase *SysBase = EMMCBase->emmc_SysBase; // Handle a card interrupt // Get the card status if(EMMCBase->emmc_CardRCA) { cmd_int(SEND_STATUS, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { } else { } } else { } } static void emmc_handle_interrupts(struct EMMCBase *EMMCBase) { struct ExecBase *SysBase = EMMCBase->emmc_SysBase; uint32_t irpts = rd32(EMMCBase->emmc_Regs, EMMC_INTERRUPT); uint32_t reset_mask = 0; if(irpts & SD_COMMAND_COMPLETE) { bug("[brcm-emmc] spurious command complete interrupt\n"); reset_mask |= SD_COMMAND_COMPLETE; } if(irpts & SD_TRANSFER_COMPLETE) { bug("[brcm-emmc] spurious transfer complete interrupt\n"); reset_mask |= SD_TRANSFER_COMPLETE; } if(irpts & SD_BLOCK_GAP_EVENT) { bug("[brcm-emmc] spurious block gap event interrupt\n"); reset_mask |= SD_BLOCK_GAP_EVENT; } if(irpts & SD_DMA_INTERRUPT) { bug("[brcm-emmc] spurious DMA interrupt\n"); reset_mask |= SD_DMA_INTERRUPT; } if(irpts & SD_BUFFER_WRITE_READY) { bug("[brcm-emmc] spurious buffer write ready interrupt\n"); reset_mask |= SD_BUFFER_WRITE_READY; emmc_reset_dat(EMMCBase); } if(irpts & SD_BUFFER_READ_READY) { bug("[brcm-emmc] spurious buffer read ready interrupt\n"); reset_mask |= SD_BUFFER_READ_READY; emmc_reset_dat(EMMCBase); } if(irpts & SD_CARD_INSERTION) { bug("[brcm-emmc] card insertion detected\n"); reset_mask |= SD_CARD_INSERTION; } if(irpts & SD_CARD_REMOVAL) { bug("[brcm-emmc] card removal detected\n"); reset_mask |= SD_CARD_REMOVAL; EMMCBase->emmc_CardRemoval = 1; } if(irpts & SD_CARD_INTERRUPT) { emmc_handle_card_interrupt(EMMCBase); reset_mask |= SD_CARD_INTERRUPT; } if(irpts & 0x8000) { reset_mask |= 0xffff0000; } wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, reset_mask); } void emmc_cmd(ULONG command, ULONG arg, ULONG timeout, struct EMMCBase *EMMCBase) { // First, handle any pending interrupts emmc_handle_interrupts(EMMCBase); // Stop the command issue if it was the card remove interrupt that was // handled if(EMMCBase->emmc_CardRemoval) { EMMCBase->emmc_LastCMDSuccess = 0; return; } // Now run the appropriate commands by calling sd_issue_command_int() if(command & IS_APP_CMD) { command &= 0x7fffffff; EMMCBase->emmc_LastCMD = APP_CMD; uint32_t rca = 0; if(EMMCBase->emmc_CardRCA) rca = EMMCBase->emmc_CardRCA << 16; cmd_int(APP_CMD, rca, timeout, EMMCBase); if(EMMCBase->emmc_LastCMDSuccess) { EMMCBase->emmc_LastCMD = command | IS_APP_CMD; cmd_int(command, arg, timeout, EMMCBase); } } else { EMMCBase->emmc_LastCMD = command; cmd_int(command, arg, timeout, EMMCBase); } } // Set the clock dividers to generate a target value static uint32_t emmc_get_clock_divider(uint32_t base_clock, uint32_t target_rate) { // TODO: implement use of preset value registers uint32_t targetted_divisor = 0; if(target_rate > base_clock) targetted_divisor = 1; else { targetted_divisor = base_clock / target_rate; uint32_t mod = base_clock % target_rate; if(mod) targetted_divisor--; } // Decide on the clock mode to use // Currently only 10-bit divided clock mode is supported // HCI version 3 or greater supports 10-bit divided clock mode // This requires a power-of-two divider // Find the first bit set int divisor = -1; for(int first_bit = 31; first_bit >= 0; first_bit--) { uint32_t bit_test = (1 << first_bit); if(targetted_divisor & bit_test) { divisor = first_bit; targetted_divisor &= ~bit_test; if(targetted_divisor) { // The divisor is not a power-of-two, increase it divisor++; } break; } } if(divisor == -1) divisor = 31; if(divisor >= 32) divisor = 31; if(divisor != 0) divisor = (1 << (divisor - 1)); if(divisor >= 0x400) divisor = 0x3ff; uint32_t freq_select = divisor & 0xff; uint32_t upper_bits = (divisor >> 8) & 0x3; uint32_t ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5); return ret; } // Switch the clock rate whilst running static int emmc_switch_clock_rate(uint32_t base_clock, uint32_t target_rate, struct EMMCBase *EMMCBase) { // Decide on an appropriate divider uint32_t divider = emmc_get_clock_divider(base_clock, target_rate); // Wait for the command inhibit (CMD and DAT) bits to clear while(rd32(EMMCBase->emmc_Regs, EMMC_STATUS) & 0x3) delay(1000, EMMCBase); // Set the SD clock off uint32_t control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 &= ~(1 << 2); wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); delay(2000, EMMCBase); // Write the new divider control1 &= ~0xffe0; // Clear old setting + clock generator select control1 |= divider; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); delay(2000, EMMCBase); // Enable the SD clock control1 |= (1 << 2); wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); delay(2000, EMMCBase); return 0; } int emmc_microsd_init(struct EMMCBase *EMMCBase) { ULONG tout; struct ExecBase *SysBase = EMMCBase->emmc_SysBase; bug("[brcm-emmc] Trying to initialise as SD device\n"); emmc_power_cycle(EMMCBase); emmc_reset_host(EMMCBase); uint32_t control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= (1 << 24); // Disable clock control1 &= ~(1 << 2); control1 &= ~(1 << 0); wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & (0x7 << 24)) == 0, 1000000); if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & (7 << 24)) != 0) { bug("[brcm-emmc] Controller did not reset properly\n"); return -1; } bug("[brcm-emmc] control0: %08lx, control1: %08lx, control2: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL2)); EMMCBase->emmc_Capabilities0 = rd32(EMMCBase->emmc_Regs, EMMC_CAPABILITIES_0); EMMCBase->emmc_Capabilities1 = rd32(EMMCBase->emmc_Regs, EMMC_CAPABILITIES_1); bug("[brcm-emmc] Capabilities: %08lx:%08lx\n", EMMCBase->emmc_Capabilities1, EMMCBase->emmc_Capabilities0); TIMEOUT_WAIT(rd32(EMMCBase->emmc_Regs, EMMC_STATUS) & (1 << 16), 500000); uint32_t status_reg = rd32(EMMCBase->emmc_Regs, EMMC_STATUS); if((status_reg & (1 << 16)) == 0) { bug("[brcm-emmc] No card inserted\n"); return -1; } bug("[brcm-emmc] Status: %08lx\n", status_reg); // Clear control2 wr32(EMMCBase->emmc_Regs, EMMC_CONTROL2, 0); // Set eMMC clock to 200MHz set_clock_rate(12, 250000000, EMMCBase); set_clock_rate(1, 250000000, EMMCBase); // Get the base clock rate uint32_t base_clock = 0; while (base_clock == 0) base_clock = get_clock_rate(12, EMMCBase); bug("[brcm-emmc] Base clock: %ld Hz\n", base_clock); control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= 1; // enable clock // Set to identification frequency (400 kHz) uint32_t f_id = emmc_get_clock_divider(base_clock, SD_CLOCK_ID); control1 |= f_id; control1 |= (7 << 16); // data timeout = TMCLK * 2^10 wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & 0x2), 1000000); if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & 0x2) == 0) { bug("[brcm-emmc] EMMC: controller's clock did not stabilise within 1 second\n"); return -1; } bug("[brcm-emmc] control0: %08lx, control1: %08lx, control2: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL2)); // Enable the SD clock delay(2000, EMMCBase); control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= 4; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); delay(2000, EMMCBase); // Mask off sending interrupts to the ARM wr32(EMMCBase->emmc_Regs, EMMC_IRPT_EN, 0); // Reset interrupts wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffffffff); // Have all interrupts sent to the INTERRUPT register uint32_t irpt_mask = 0xffffffff & (~SD_CARD_INTERRUPT); #ifdef SD_CARD_INTERRUPTS irpt_mask |= SD_CARD_INTERRUPT; #endif wr32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK, irpt_mask); delay(2000, EMMCBase); bug("[brcm-emmc] Clock enabled, control0: %08lx, control1: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1)); // Enable 3.3V on the bus uint32_t control0 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0); control0 &= 0xffff00ff; control0 |= 0x00000e00; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); delay(2000, EMMCBase); control0 |= 0x00000100; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); delay(2000, EMMCBase); // Send CMD0 to the card (reset to idle state) emmc_cmd(GO_IDLE_STATE, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] No CMD0 response\n"); bug("[brcm-emmc] Status: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_STATUS)); return -1; } // Send CMD8 to the card // Voltage supplied = 0x1 = 2.7-3.6V (standard) // Check pattern = 10101010b (as per PLSS 4.3.13) = 0xAA bug("[brcm-emmc] note a timeout error on the following command (CMD8) is normal " "and expected if the SD card version is less than 2.0\n"); emmc_cmd(SEND_IF_COND, 0x1aa, 500000, EMMCBase); int v2_later = 0; if(TIMEOUT(EMMCBase)) v2_later = 0; else if(CMD_TIMEOUT(EMMCBase)) { bug("[brcm-emmc] CMD8 timed out\n"); if(emmc_reset_cmd(EMMCBase) == -1) return -1; wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, SD_ERR_MASK_CMD_TIMEOUT); v2_later = 0; } else if(FAIL(EMMCBase)) { bug("[brcm-emmc] Failure sending CMD8 (%08lx)\n", EMMCBase->emmc_LastInterrupt); return -1; } else { if(((EMMCBase->emmc_Res0) & 0xfff) != 0x1aa) { bug("[brcm-emmc] Unusable card\n"); bug("[brcm-emmc] CMD8 response %08lx\n", EMMCBase->emmc_Res0); return -1; } else v2_later = 1; } bug("[brcm-emmc] CMD8 response %08lx\n", EMMCBase->emmc_Res0); // Here we are supposed to check the response to CMD5 (HCSS 3.6) // It only returns if the card is a SDIO card bug("[brcm-emmc] Note that a timeout error on the following command (CMD5) is " "normal and expected if the card is not a SDIO card.\n"); emmc_cmd(IO_SET_OP_COND, 0, 10000, EMMCBase); if(!TIMEOUT(EMMCBase)) { if(CMD_TIMEOUT(EMMCBase)) { if(emmc_reset_cmd(EMMCBase) == -1) return -1; wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, SD_ERR_MASK_CMD_TIMEOUT); } else { bug("[brcm-emmc] SDIO card detected - not currently supported\n"); return -1; } } // Call initialization ACMD41 int card_is_busy = 1; while(card_is_busy) { uint32_t v2_flags = 0; if(v2_later) { // Set SDHC support v2_flags |= (1 << 30); } emmc_cmd(ACMD_41 | IS_APP_CMD, 0x00ff8000 | v2_flags, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error issuing ACMD41\n"); return -1; } if((EMMCBase->emmc_Res0) & 0x80000000) { // Initialization is complete EMMCBase->emmc_CardOCR = (EMMCBase->emmc_Res0 >> 8) & 0xffff; EMMCBase->emmc_CardSupportsSDHC = (EMMCBase->emmc_Res0 >> 30) & 0x1; card_is_busy = 0; } else { //RawDoFmt("[brcm-emmc] card is busy, retrying\n", NULL, (APTR)putch, NULL); delay(500000, EMMCBase); } } bug("[brcm-emmc] card identified: OCR: %04lx, SDHC support: %ld\n", EMMCBase->emmc_CardOCR, EMMCBase->emmc_CardSupportsSDHC); // At this point, we know the card is definitely an SD card, so will definitely // support SDR12 mode which runs at 25 MHz emmc_switch_clock_rate(base_clock, SD_CLOCK_NORMAL, EMMCBase); // A small wait before the voltage switch delay(5000, EMMCBase); // Send CMD2 to get the cards CID emmc_cmd(ALL_SEND_CID, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending ALL_SEND_CID\n"); return -1; } uint32_t card_cid_0 = EMMCBase->emmc_Res0; uint32_t card_cid_1 = EMMCBase->emmc_Res1; uint32_t card_cid_2 = EMMCBase->emmc_Res2; uint32_t card_cid_3 = EMMCBase->emmc_Res3; bug("[brcm-emmc] card CID: %08lx%08lx%08lx%08lx\n", card_cid_3, card_cid_2, card_cid_1, card_cid_0); EMMCBase->emmc_CID[0] = card_cid_3; EMMCBase->emmc_CID[1] = card_cid_2; EMMCBase->emmc_CID[2] = card_cid_1; EMMCBase->emmc_CID[3] = card_cid_0; // Send CMD3 to enter the data state emmc_cmd(SEND_RELATIVE_ADDR, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending SEND_RELATIVE_ADDR\n"); return -1; } uint32_t cmd3_resp = EMMCBase->emmc_Res0; EMMCBase->emmc_CardRCA = (cmd3_resp >> 16) & 0xffff; uint32_t crc_error = (cmd3_resp >> 15) & 0x1; uint32_t illegal_cmd = (cmd3_resp >> 14) & 0x1; uint32_t error = (cmd3_resp >> 13) & 0x1; uint32_t status = (cmd3_resp >> 9) & 0xf; uint32_t ready = (cmd3_resp >> 8) & 0x1; bug("[brcm-emmc] Res0: %08lx\n", cmd3_resp); if(crc_error) { bug("[brcm-emmc] CRC error\n"); return -1; } if(illegal_cmd) { bug("[brcm-emmc] Illegal command\n"); return -1; } if(error) { bug("[brcm-emmc] generic error\n"); return -1; } if(!ready) { bug("[brcm-emmc] not ready for data\n"); return -1; } bug("[brcm-emmc] RCA: %04lx\n", EMMCBase->emmc_CardRCA); // Now select the card (toggles it to transfer state) emmc_cmd(SELECT_CARD, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending CMD7\n"); return -1; } uint32_t cmd7_resp = EMMCBase->emmc_Res0; status = (cmd7_resp >> 9) & 0xf; if((status != 3) && (status != 4)) { bug("[brcm-emmc] invalid status (%ld)\n", status); return -1; } // If not an SDHC card, ensure BLOCKLEN is 512 bytes if(!EMMCBase->emmc_CardSupportsSDHC) { emmc_cmd(SET_BLOCKLEN, 512, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending SET_BLOCKLEN\n"); return -1; } } uint32_t controller_block_size = rd32(EMMCBase->emmc_Regs, EMMC_BLKSIZECNT); controller_block_size &= (~0xfff); controller_block_size |= 0x200; wr32(EMMCBase->emmc_Regs, EMMC_BLKSIZECNT, controller_block_size); // Get the cards SCR register EMMCBase->emmc_Buffer = &EMMCBase->emmc_SCR; EMMCBase->emmc_BlocksToTransfer = 1; EMMCBase->emmc_BlockSize = 8; emmc_cmd(SEND_SCR, 0, 500000, EMMCBase); EMMCBase->emmc_BlockSize = 512; if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending SEND_SCR\n"); return -1; } // Determine card version // Note that the SCR is big-endian uint32_t scr0 = EMMCBase->emmc_SCR.scr[0]; EMMCBase->emmc_SCR.emmc_version = SD_VER_UNKNOWN; uint32_t sd_spec = (scr0 >> (56 - 32)) & 0xf; uint32_t sd_spec3 = (scr0 >> (47 - 32)) & 0x1; uint32_t sd_spec4 = (scr0 >> (42 - 32)) & 0x1; EMMCBase->emmc_SCR.emmc_bus_widths = (scr0 >> (48 - 32)) & 0xf; if(sd_spec == 0) EMMCBase->emmc_SCR.emmc_version = SD_VER_1; else if(sd_spec == 1) EMMCBase->emmc_SCR.emmc_version = SD_VER_1_1; else if(sd_spec == 2) { if(sd_spec3 == 0) EMMCBase->emmc_SCR.emmc_version = SD_VER_2; else if(sd_spec3 == 1) { if(sd_spec4 == 0) EMMCBase->emmc_SCR.emmc_version = SD_VER_3; else if(sd_spec4 == 1) EMMCBase->emmc_SCR.emmc_version = SD_VER_4; } } bug("[brcm-emmc] SCR: %08lx-%08lx\n", EMMCBase->emmc_SCR.scr[1], EMMCBase->emmc_SCR.scr[1]); bug("[brcm-emmc] SCR version %ld, bus_widths %01lx\n", EMMCBase->emmc_SCR.emmc_version, EMMCBase->emmc_SCR.emmc_bus_widths); if(EMMCBase->emmc_SCR.emmc_bus_widths & 0x4) { // Set 4-bit transfer mode (ACMD6) // See HCSS 3.4 for the algorithm bug("[brcm-emmc] Switching to 4-bit data mode\n"); // Disable card interrupt in host uint32_t old_irpt_mask = rd32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK); uint32_t new_iprt_mask = old_irpt_mask & ~(1 << 8); wr32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK, new_iprt_mask); // Send ACMD6 to change the card's bit mode emmc_cmd(SET_BUS_WIDTH, 0x2, 500000, EMMCBase); if(FAIL(EMMCBase)) bug("[brcm-emmc] Switch to 4-bit data mode failed\n"); else { // Change bit mode for Host uint32_t control0 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0); control0 |= 0x2; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); // Re-enable card interrupt in host wr32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK, old_irpt_mask); bug("[brcm-emmc] Switch to 4-bit complete\n"); } } // Get the CMD6 status register EMMCBase->emmc_Buffer = &EMMCBase->emmc_StatusReg; EMMCBase->emmc_BlocksToTransfer = 1; EMMCBase->emmc_BlockSize = 64; emmc_cmd(SWITCH_FUNC, 0, 500000, EMMCBase); if (EMMCBase->emmc_DisableHighSpeed == 0 && EMMCBase->emmc_StatusReg[13] & 2) { bug("[brcm-emmc] Card supports High Speed mode. Switching...\n"); EMMCBase->emmc_Buffer = &EMMCBase->emmc_StatusReg; EMMCBase->emmc_BlocksToTransfer = 1; EMMCBase->emmc_BlockSize = 64; emmc_cmd(SWITCH_FUNC, 0x80fffff1, 500000, EMMCBase); delay(10000, EMMCBase); if (EMMCBase->emmc_Overclock != 0) emmc_switch_clock_rate(base_clock, EMMCBase->emmc_Overclock, EMMCBase); else emmc_switch_clock_rate(base_clock, 50000000, EMMCBase); } EMMCBase->emmc_BlockSize = 512; bug("[brcm-emmc] Found a valid version %ld SD card\n", EMMCBase->emmc_SCR.emmc_version); EMMCBase->emmc_isMicroSD = 1; // Reset interrupt register wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffffffff); return 0; } int emmc_card_init(struct EMMCBase *EMMCBase) { ULONG tout; struct ExecBase *SysBase = EMMCBase->emmc_SysBase; EMMCBase->emmc_isMicroSD = 0; bug("[brcm-emmc] eMMC Card init\n"); emmc_power_cycle(EMMCBase); emmc_reset_host(EMMCBase); uint32_t ver = rd32(EMMCBase->emmc_Regs, EMMC_SLOTISR_VER); uint32_t vendor = ver >> 24; uint32_t sdversion = (ver >> 16) & 0xff; uint32_t slot_status = ver & 0xff; bug("[brcm-emmc] Vendor %lx, sdversion %lx, slot_status %lx\n", vendor, sdversion, slot_status); uint32_t control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= (1 << 24); // Disable clock control1 &= ~(1 << 2); control1 &= ~(1 << 0); wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & (0x7 << 24)) == 0, 1000000); if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & (7 << 24)) != 0) { bug("[brcm-emmc] Controller did not reset properly\n"); return -1; } bug("[brcm-emmc] control0: %08lx, control1: %08lx, control2: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL2)); EMMCBase->emmc_Capabilities0 = rd32(EMMCBase->emmc_Regs, EMMC_CAPABILITIES_0); EMMCBase->emmc_Capabilities1 = rd32(EMMCBase->emmc_Regs, EMMC_CAPABILITIES_1); bug("[brcm-emmc] Capabilities: %08lx:%08lx\n", EMMCBase->emmc_Capabilities1, EMMCBase->emmc_Capabilities0); TIMEOUT_WAIT(rd32(EMMCBase->emmc_Regs, EMMC_STATUS) & (1 << 16), 500000); uint32_t status_reg = rd32(EMMCBase->emmc_Regs, EMMC_STATUS); if((status_reg & (1 << 16)) == 0) { bug("[brcm-emmc] No card inserted\n"); return -1; } bug("[brcm-emmc] Status: %08lx\n", status_reg); // Clear control2 wr32(EMMCBase->emmc_Regs, EMMC_CONTROL2, 0); // Set eMMC clock to 200MHz set_clock_rate(12, 250000000, EMMCBase); set_clock_rate(1, 250000000, EMMCBase); // Get the base clock rate uint32_t base_clock = 0; while (base_clock == 0) base_clock = get_clock_rate(12, EMMCBase); bug("[brcm-emmc] Base clock: %ld Hz\n", base_clock); control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= 1; // enable clock // Set to identification frequency (400 kHz) uint32_t f_id = emmc_get_clock_divider(base_clock, SD_CLOCK_ID); control1 |= f_id; control1 |= (7 << 16); // data timeout = TMCLK * 2^10 wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); TIMEOUT_WAIT((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & 0x2), 1000000); if((rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1) & 0x2) == 0) { bug("[brcm-emmc] EMMC: controller's clock did not stabilise within 1 second\n"); return -1; } bug("[brcm-emmc] control0: %08lx, control1: %08lx, control2: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL2)); // Enable the SD clock delay(2000, EMMCBase); control1 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1); control1 |= 4; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL1, control1); delay(2000, EMMCBase); // Mask off sending interrupts to the ARM wr32(EMMCBase->emmc_Regs, EMMC_IRPT_EN, 0); // Reset interrupts wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffffffff); // Have all interrupts sent to the INTERRUPT register uint32_t irpt_mask = 0xffffffff & (~SD_CARD_INTERRUPT); #ifdef SD_CARD_INTERRUPTS irpt_mask |= SD_CARD_INTERRUPT; #endif wr32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK, irpt_mask); delay(2000, EMMCBase); bug("[brcm-emmc] Clock enabled, control0: %08lx, control1: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0), rd32(EMMCBase->emmc_Regs, EMMC_CONTROL1)); // Enable 3.3V on the bus uint32_t control0 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0); control0 &= 0xffff00ff; control0 |= 0x00000e00; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); delay(2000, EMMCBase); control0 |= 0x00000100; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); delay(2000, EMMCBase); // Send CMD0 to the card (reset to idle state) emmc_cmd(GO_IDLE_STATE, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] No CMD0 response\n"); bug("[brcm-emmc] Status: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_STATUS)); return -1; } /* Check if it is eMMC or microSD in eMMC slot. Send CMD1, report the host is operating at 3.3V window */ emmc_cmd(SEND_OP_COND, 0x40FF8000, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] No CMD1 response\n"); bug("[brcm-emmc] Status: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_STATUS)); return emmc_microsd_init(EMMCBase); } while ((EMMCBase->emmc_Res0 & 0x80000000) == 0) { bug("[brcm-emmc] Waiting for card to finish initializadion\n"); delay(10000, EMMCBase); emmc_cmd(SEND_OP_COND, 0x40FF8000, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] No CMD1 response\n"); bug("[brcm-emmc] Status: %08lx\n", rd32(EMMCBase->emmc_Regs, EMMC_STATUS)); return -1; } } bug("[brcm-emmc] CMD1 Response: %08lx\n", EMMCBase->emmc_Res0); // Send CMD2 to get the cards CID emmc_cmd(ALL_SEND_CID, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending ALL_SEND_CID\n"); return -1; } uint32_t card_cid_0 = EMMCBase->emmc_Res0; uint32_t card_cid_1 = EMMCBase->emmc_Res1; uint32_t card_cid_2 = EMMCBase->emmc_Res2; uint32_t card_cid_3 = EMMCBase->emmc_Res3; bug("[brcm-emmc] card CID: %08lx%08lx%08lx%08lx\n", card_cid_3, card_cid_2, card_cid_1, card_cid_0); // Send CMD3 to enter the data state emmc_cmd(SEND_RELATIVE_ADDR, 0x00010000, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending SEND_RELATIVE_ADDR\n"); return -1; } uint32_t cmd3_resp = EMMCBase->emmc_Res0; EMMCBase->emmc_CardRCA = 1; uint32_t crc_error = (cmd3_resp >> 15) & 0x1; uint32_t illegal_cmd = (cmd3_resp >> 14) & 0x1; uint32_t error = (cmd3_resp >> 13) & 0x1; uint32_t status = (cmd3_resp >> 9) & 0xf; uint32_t ready = (cmd3_resp >> 8) & 0x1; bug("[brcm-emmc] Res0: %08lx\n", cmd3_resp); if(crc_error) { bug("[brcm-emmc] CRC error\n"); return -1; } if(illegal_cmd) { bug("[brcm-emmc] Illegal command\n"); return -1; } if(error) { bug("[brcm-emmc] Generic error\n"); return -1; } if(!ready) { bug("[brcm-emmc] Not ready for data\n"); return -1; } bug("[brcm-emmc] RCA: %04lx\n", EMMCBase->emmc_CardRCA); // Now select the card (toggles it to transfer state) emmc_cmd(SELECT_CARD, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending CMD7\n"); return -1; } uint32_t cmd7_resp = EMMCBase->emmc_Res0; status = (cmd7_resp >> 9) & 0xf; if((status != 3) && (status != 4)) { bug("[brcm-emmc] Invalid status (%ld)\n", cmd7_resp); return -1; } bug("[brcm-emmc] Res0: %08lx\n", EMMCBase->emmc_Res0); // Set high-speed compatible mode emmc_cmd(SWITCH, (185 << 16) | (1 << 8) | (3 << 24), 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending CMD6\n"); return -1; } bug("[brcm-emmc] Res0: %08lx\n", EMMCBase->emmc_Res0); emmc_switch_clock_rate(base_clock, EMMC_CLOCK_HIGH, EMMCBase); control0 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0); control0 |= 0x4; wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); bug("[brcm-emmc] Clock set to %ld kHz\n", EMMC_CLOCK_HIGH / 1000); emmc_cmd(SEND_STATUS, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] Error sending CMD13\n"); return -1; } bug("[brcm-emmc] Res0: %08lx\n", EMMCBase->emmc_Res0); bug("[brcm-emmc] Switching to 8-bit data mode\n"); // Disable card interrupt in host uint32_t old_irpt_mask = rd32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK); uint32_t new_iprt_mask = old_irpt_mask & ~(1 << 8); wr32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK, new_iprt_mask); emmc_cmd(SWITCH, (183 << 16) | (2 << 8) | (3 << 24), 500000, EMMCBase); if(FAIL(EMMCBase)) bug("[brcm-emmc] switch to 8-bit data mode failed\n"); else { // Change bit mode for Host uint32_t control0 = rd32(EMMCBase->emmc_Regs, EMMC_CONTROL0); control0 |= 0x2 | (1 << 5); wr32(EMMCBase->emmc_Regs, EMMC_CONTROL0, control0); // Re-enable card interrupt in host wr32(EMMCBase->emmc_Regs, EMMC_IRPT_MASK, old_irpt_mask); bug("[brcm-emmc] switch to 8-bit data mode complete\n"); } // Reset interrupt register wr32(EMMCBase->emmc_Regs, EMMC_INTERRUPT, 0xffffffff); // Set block size EMMCBase->emmc_BlockSize = 512; emmc_cmd(SET_BLOCKLEN, 512, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] error sending SET_BLOCKLEN\n", NULL); return -1; } return 0; } int ensure_data_mode(struct EMMCBase *EMMCBase) { struct ExecBase *SysBase = EMMCBase->emmc_SysBase; if(EMMCBase->emmc_CardRCA == 0) { // Try again to initialise the card int ret = emmc_card_init(EMMCBase); if(ret != 0) return ret; } emmc_cmd(SEND_STATUS, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] ensure_data_mode() error sending CMD13\n"); EMMCBase->emmc_CardRCA = 0; return -1; } uint32_t status = EMMCBase->emmc_Res0; uint32_t cur_state = (status >> 9) & 0xf; if(cur_state == 3) { // Currently in the stand-by state - select it emmc_cmd(SELECT_CARD, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] ensure_data_mode() no response from CMD7\n"); EMMCBase->emmc_CardRCA = 0; return -1; } } else if(cur_state == 5) { // In the data transfer state - cancel the transmission emmc_cmd(STOP_TRANSMISSION, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("[brcm-emmc] ensure_data_mode() no response from CMD12\n"); EMMCBase->emmc_CardRCA = 0; return -1; } // Reset the data circuit emmc_reset_dat(EMMCBase); } else if(cur_state != 4) { // Not in the transfer state - re-initialise int ret = emmc_card_init(EMMCBase); if(ret != 0) return ret; } // Check again that we're now in the correct mode if(cur_state != 4) { bug("[brcm-emmc] ensure_data_mode() rechecking status: "); emmc_cmd(SEND_STATUS, EMMCBase->emmc_CardRCA << 16, 500000, EMMCBase); if(FAIL(EMMCBase)) { bug("no response from CMD13\n"); EMMCBase->emmc_CardRCA = 0; return -1; } status = EMMCBase->emmc_Res0; cur_state = (status >> 9) & 0xf; bug("%ld\n", cur_state); if(cur_state != 4) { bug("[brcm-emmc] unable to initialise SD card to " "data mode (state %ld)\n", cur_state); EMMCBase->emmc_CardRCA = 0; return -1; } } return 0; } static int emmc_do_data_command(int is_write, uint8_t *buf, uint32_t buf_size, uint32_t block_no, struct EMMCBase *EMMCBase) { struct ExecBase *SysBase = EMMCBase->emmc_SysBase; // This is as per HCSS 3.7.2.1 if(buf_size < EMMCBase->emmc_BlockSize) { bug("[brcm-emmc] do_data_command() called with buffer size (%ld) less than " "block size (%ld)\n", buf_size, EMMCBase->emmc_BlockSize); return -1; } EMMCBase->emmc_BlocksToTransfer = buf_size / EMMCBase->emmc_BlockSize; if(buf_size % EMMCBase->emmc_BlockSize) { bug("[brcm-emmc] do_data_command() called with buffer size (%ld) not an " "exact multiple of block size (%ld)\n", buf_size, EMMCBase->emmc_BlockSize); return -1; } EMMCBase->emmc_Buffer = buf; // Decide on the command to use int command; if(is_write) { if(EMMCBase->emmc_BlocksToTransfer > 1) command = WRITE_MULTIPLE_BLOCK; else command = WRITE_BLOCK; } else { if(EMMCBase->emmc_BlocksToTransfer > 1) command = READ_MULTIPLE_BLOCK; else command = READ_SINGLE_BLOCK; } int retry_count = 0; int max_retries = 5; while(retry_count < max_retries) { emmc_cmd(command, block_no, 5000000, EMMCBase); if(SUCCESS(EMMCBase)) break; else { // In the data transfer state - cancel the transmission emmc_cmd(STOP_TRANSMISSION, 0, 500000, EMMCBase); if(FAIL(EMMCBase)) { EMMCBase->emmc_CardRCA = 0; return -1; } // Reset the data circuit emmc_reset_dat(EMMCBase); //RawDoFmt("SD: error sending CMD%ld, ", &command, (APTR)putch, NULL); //RawDoFmt("error = %08lx. ", &SDCardBase->sd_LastError, (APTR)putch, NULL); retry_count++; /* if(retry_count < max_retries) RawDoFmt("Retrying...\n", NULL, (APTR)putch, NULL); else RawDoFmt("Giving up.\n", NULL, (APTR)putch, NULL); */ } } if(retry_count == max_retries) { EMMCBase->emmc_CardRCA = 0; return -1; } return 0; } int emmc_read(uint8_t *buf, uint32_t buf_size, uint32_t block_no, struct EMMCBase *EMMCBase) { // Check the status of the card if(ensure_data_mode(EMMCBase) != 0) return -1; if(emmc_do_data_command(0, buf, buf_size, block_no, EMMCBase) < 0) return -1; return buf_size; } int emmc_write(uint8_t *buf, uint32_t buf_size, uint32_t block_no, struct EMMCBase *EMMCBase) { // Check the status of the card if(ensure_data_mode(EMMCBase) != 0) return -1; if(emmc_do_data_command(1, buf, buf_size, block_no, EMMCBase) < 0) return -1; return buf_size; }