mirror of https://github.com/wolfSSL/wolfBoot.git
Progress with eMMC/SD driver
parent
f89704d7e1
commit
ab614a93c8
|
|
@ -111,7 +111,8 @@ jobs:
|
|||
- name: Build wolfboot (riscv32)
|
||||
if: ${{ inputs.arch == 'riscv' }}
|
||||
run: |
|
||||
make CROSS_COMPILE=riscv32-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}}
|
||||
# using riscv64 for now since riscv32 is missing "zicsr" extension
|
||||
make CROSS_COMPILE=riscv64-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}}
|
||||
|
||||
- name: Build wolfboot (riscv64))
|
||||
if: ${{ inputs.arch == 'riscv64' }}
|
||||
|
|
|
|||
|
|
@ -876,6 +876,40 @@ set architecture riscv:rv64
|
|||
#thread apply all set $pc=_start
|
||||
```
|
||||
|
||||
### PolarFire Example Boot Output
|
||||
|
||||
```
|
||||
disk_open: drv = 0
|
||||
mmc_set_timeout: timeout_us: 500000, tcfclk_khz: -824320848 (mhz: 3470646), timeout_val: 500000, dtcv: 15
|
||||
mmc_set_clock: clock_khz: 400, freq_khz: 400
|
||||
mmc_send_cmd: cmd_index: 0, cmd_arg: 00000000, resp_type: 0
|
||||
mmc_send_cmd: cmd_index: 8, cmd_arg: 00000100, resp_type: 9
|
||||
mmc_init: xpc:0, si8r:1, max_ma (3.3v:128 1.8v:128)
|
||||
mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1
|
||||
mmc_send_cmd: cmd_index: 41, cmd_arg: 00000000, resp_type: 4
|
||||
ocr_reg: 0x40FF8000
|
||||
mmc_init: sending OCR arg: 0x41200000
|
||||
mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1
|
||||
mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4
|
||||
ocr_reg: 0x40FF8000
|
||||
mmc_send_cmd: cmd_index: 55, cmd_arg: 00000000, resp_type: 1
|
||||
mmc_send_cmd: cmd_index: 41, cmd_arg: 41200000, resp_type: 4
|
||||
ocr_reg: 0xC1FF8000
|
||||
mmc_send_cmd: cmd_index: 11, cmd_arg: 00000000, resp_type: 1
|
||||
mmc_send_cmd: cmd_index: 2, cmd_arg: 00000000, resp_type: 3
|
||||
mmc_send_cmd: cmd_index: 3, cmd_arg: 00000000, resp_type: 8
|
||||
mmc_init: rca: 43690
|
||||
mmc_send_cmd: cmd_index: 9, cmd_arg: AAAA0000, resp_type: 3
|
||||
mmc_init: sector size: 512
|
||||
mmc_init: sector count: 62333952
|
||||
mmc_send_cmd: cmd_index: 7, cmd_arg: AAAA0000, resp_type: 2
|
||||
Checking primary OS image in 0,1...
|
||||
Checking secondary OS image in 0,2...
|
||||
No valid OS image found in either partition 1 or 2
|
||||
wolfBoot: PANIC!
|
||||
```
|
||||
|
||||
|
||||
### PolarFire TODO
|
||||
|
||||
1) Add support for full HSS replacement using wolfboot.
|
||||
|
|
|
|||
419
hal/mpfs250.c
419
hal/mpfs250.c
|
|
@ -43,6 +43,8 @@
|
|||
#include "loader.h"
|
||||
#include "disk.h"
|
||||
|
||||
#define DEBUG_MMC
|
||||
|
||||
/* Placeholder functions - to be implemented */
|
||||
void hal_init(void)
|
||||
{
|
||||
|
|
@ -132,6 +134,16 @@ void* hal_get_dts_address(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static uint32_t g_sector_count;
|
||||
static uint32_t g_sector_size;
|
||||
static uint32_t g_bus_width = 1;
|
||||
static uint32_t g_rca = 0; /* SD Card Relative Address */
|
||||
|
||||
#ifndef DEFAULT_DELAY
|
||||
#define DEFAULT_DELAY 0xFFFF
|
||||
#endif
|
||||
|
||||
int mmc_set_timeout(uint32_t timeout_us)
|
||||
{
|
||||
uint32_t reg, i, tcfclk, tcfclk_mhz, tcfclk_khz, timeout_val, dtcv;
|
||||
|
|
@ -170,17 +182,21 @@ int mmc_set_timeout(uint32_t timeout_us)
|
|||
}
|
||||
dtcv *= 2;
|
||||
}
|
||||
dtcv = i;
|
||||
|
||||
/* set the data timeout counter value */
|
||||
/* set the data timeout counter value - CHECK: 0xc0207 */
|
||||
reg = EMMC_SD_SRS11;
|
||||
reg &= ~EMMC_SD_SRS11_DTCV_MASK;
|
||||
reg |= (timeout_val << EMMC_SD_SRS11_DTCV_SHIFT) & EMMC_SD_SRS11_DTCV_MASK;
|
||||
reg |= (dtcv << EMMC_SD_SRS11_DTCV_SHIFT) & EMMC_SD_SRS11_DTCV_MASK;
|
||||
EMMC_SD_SRS11 = reg;
|
||||
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_set_timeout: dtcv 0x%08X, srs11 0x%08X\n", dtcv, reg);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DEFAULT_DELAY 0x00FFFFFF
|
||||
void mmc_delay(uint32_t delay)
|
||||
{
|
||||
while (delay--) {
|
||||
|
|
@ -213,15 +229,16 @@ int mmc_set_power(uint32_t voltage)
|
|||
reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_1_8V;
|
||||
}
|
||||
else if (voltage == EMMC_SD_SRS10_BVS_3_0V && (cap2 & EMMC_SD_SRS16_VS30)) {
|
||||
reg |= EMMC_SD_SRS10_BVS_3_0V;
|
||||
reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_3_0V;
|
||||
}
|
||||
else if (voltage == EMMC_SD_SRS10_BVS_3_3V && (cap2 & EMMC_SD_SRS16_VS33)) {
|
||||
reg |= EMMC_SD_SRS10_BVS_3_3V;
|
||||
reg |= EMMC_SD_SRS10_BP | EMMC_SD_SRS10_BVS_3_3V;
|
||||
}
|
||||
else {
|
||||
/* voltage not supported */
|
||||
return -1;
|
||||
}
|
||||
/* should be - 0xf06 */
|
||||
EMMC_SD_SRS10 = reg;
|
||||
mmc_delay(DEFAULT_DELAY); /* delay after bus power is applied */
|
||||
}
|
||||
|
|
@ -231,8 +248,14 @@ int mmc_set_power(uint32_t voltage)
|
|||
/* returns actual frequency in kHz */
|
||||
uint32_t mmc_set_clock(uint32_t clock_khz)
|
||||
{
|
||||
static uint32_t last_clock_khz = 0;
|
||||
uint32_t reg, base_clk_khz, i, mclk, freq_khz;
|
||||
|
||||
if (last_clock_khz != 0 && last_clock_khz == clock_khz) {
|
||||
/* clock already set */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* disable clock */
|
||||
EMMC_SD_SRS11 &= ~EMMC_SD_SRS11_SDCE;
|
||||
|
||||
|
|
@ -243,6 +266,7 @@ uint32_t mmc_set_clock(uint32_t clock_khz)
|
|||
/* error getting base clock */
|
||||
return 0;
|
||||
}
|
||||
base_clk_khz *= 1000; /* convert MHz to kHz */
|
||||
|
||||
/* select clock frequency */
|
||||
reg = EMMC_SD_SRS11;
|
||||
|
|
@ -254,18 +278,25 @@ uint32_t mmc_set_clock(uint32_t clock_khz)
|
|||
break;
|
||||
}
|
||||
}
|
||||
mclk = ((i / 2) << EMMC_SD_SRS11_SDCFSL_SHIFT);
|
||||
reg |= (mclk & EMMC_SD_SRS11_SDCFSL_MASK) | ((mclk & 0x30000) >> 10);
|
||||
mclk = (i / 2);
|
||||
reg |= ((mclk << EMMC_SD_SRS11_SDCFSL_SHIFT) & EMMC_SD_SRS11_SDCFSL_MASK) /* lower 8 bits */
|
||||
| ((mclk << EMMC_SD_SRS11_SDCFSH_SHIFT) & EMMC_SD_SRS11_SDCFSH_SHIFT); /* upper 2 bits */
|
||||
reg |= EMMC_SD_SRS11_ICE; /* clock enable */
|
||||
reg &= ~EMMC_SD_SRS11_CGS; /* select clock */
|
||||
EMMC_SD_SRS11 = reg;
|
||||
freq_khz = base_clk_khz / i;
|
||||
|
||||
/* wait for clock to stabilize */
|
||||
while ((EMMC_SD_SRS11 & EMMC_SD_SRS11_ICE) == 0);
|
||||
while ((EMMC_SD_SRS11 & EMMC_SD_SRS11_ICS) == 0);
|
||||
|
||||
/* enable clock */
|
||||
EMMC_SD_SRS11 |= EMMC_SD_SRS11_SDCE;
|
||||
last_clock_khz = clock_khz;
|
||||
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_set_clock: clock_khz: %d, freq_khz: %d\n",
|
||||
clock_khz, freq_khz);
|
||||
#endif
|
||||
|
||||
mmc_delay(DEFAULT_DELAY); /* delay after clock changed */
|
||||
|
||||
|
|
@ -316,8 +347,10 @@ static uint32_t mmc_get_response_type(uint8_t resp_type)
|
|||
return cmd_reg;
|
||||
}
|
||||
|
||||
#define DEVICE_BUSY 1
|
||||
int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t cmd_reg;
|
||||
uint32_t cmd_type = EMMC_SD_SRS03_CMD_NORMAL; /* TODO: Add support for suspend and resume */
|
||||
|
||||
|
|
@ -338,15 +371,22 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
|
|||
/* set command argument and command transfer registers */
|
||||
EMMC_SD_SRS02 = cmd_arg;
|
||||
cmd_reg =
|
||||
((cmd_index & EMMC_SD_SRS03_CIDX_MASK) << EMMC_SD_SRS03_CIDX_SHIFT) |
|
||||
((cmd_type & EMMC_SD_SRS03_CT_MASK) << EMMC_SD_SRS03_CT_SHIFT) |
|
||||
((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) & EMMC_SD_SRS03_CIDX_MASK) |
|
||||
((cmd_type << EMMC_SD_SRS03_CT_SHIFT) & EMMC_SD_SRS03_CT_MASK) |
|
||||
mmc_get_response_type(resp_type);
|
||||
|
||||
EMMC_SD_SRS03 = cmd_reg;
|
||||
|
||||
if (resp_type != EMMC_SD_RESP_NONE) {
|
||||
/* wait for command complete or error - TODO: Add timeout */
|
||||
while ((EMMC_SD_SRS12 & (EMMC_SD_SRS12_CC | EMMC_SD_SRS12_ERR_STAT)) == 0);
|
||||
/* wait for command complete or error - TODO: Add timeout */
|
||||
while ((EMMC_SD_SRS12 & (EMMC_SD_SRS12_CC | EMMC_SD_SRS12_EINT)) == 0);
|
||||
|
||||
/* check for device busy */
|
||||
if (resp_type == EMMC_SD_RESP_R1 || resp_type == EMMC_SD_RESP_R1B) {
|
||||
uint32_t resp = EMMC_SD_SRS04;
|
||||
#define CARD_STATUS_READY_FOR_DATA (0x1 << 8)
|
||||
if ((resp & CARD_STATUS_READY_FOR_DATA) == 0) {
|
||||
status = DEVICE_BUSY; /* card is busy */
|
||||
}
|
||||
}
|
||||
|
||||
/* clear all status interrupts (except current limit, card interrupt/removal/insert) */
|
||||
|
|
@ -355,11 +395,25 @@ int mmc_send_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type)
|
|||
EMMC_SD_SRS12_CR |
|
||||
EMMC_SD_SRS12_CIN);
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* TODO: Add timeout */
|
||||
int mmc_wait_busy(int check_dat0)
|
||||
{
|
||||
uint32_t status;
|
||||
if (check_dat0) {
|
||||
/* wait for DATA0 not busy */
|
||||
while ((EMMC_SD_SRS09 & EMMC_SD_SRS09_DAT0_LVL) == 0);
|
||||
}
|
||||
/* wait for CMD13 */
|
||||
while ((status = mmc_send_cmd(MMC_CMD13_SEND_STATUS,
|
||||
(g_rca << SD_RCA_SHIFT), EMMC_SD_RESP_R1)) == DEVICE_BUSY);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set power and send initialization commands */
|
||||
/* voltage: 0=off or EMMC_SD_SRS10_BVS_ */
|
||||
/* voltage: 0=off or EMMC_SD_SRS10_BVS_[X_X]V */
|
||||
int mmc_power_init_seq(uint32_t voltage)
|
||||
{
|
||||
/* Set power to specified voltage */
|
||||
|
|
@ -383,11 +437,169 @@ int mmc_card_init(uint32_t acmd41_arg, uint32_t *ocr_reg)
|
|||
{
|
||||
int status = mmc_send_cmd(SD_CMD55_APP_CMD, 0, EMMC_SD_RESP_R1);
|
||||
if (status == 0) {
|
||||
status = mmc_send_cmd(SD_ACMD41_SD_SEND_OP, acmd41_arg,
|
||||
status = mmc_send_cmd(SD_ACMD41_SEND_OP_COND, acmd41_arg,
|
||||
EMMC_SD_RESP_R3);
|
||||
if (status == 0) {
|
||||
*ocr_reg = EMMC_SD_SRS04;
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("ocr_reg: 0x%08X\n", *ocr_reg);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* MMC_CMD17_READ_SINGLE */
|
||||
int mmc_block_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst,
|
||||
uint32_t sz)
|
||||
{
|
||||
int status;
|
||||
uint32_t reg;
|
||||
|
||||
/* wait for idle */
|
||||
status = mmc_wait_busy(0);
|
||||
|
||||
/* reset data and command lines */
|
||||
EMMC_SD_SRS11 |= EMMC_SD_SRS11_RESET_DAT_CMD;
|
||||
mmc_delay(0xFF);
|
||||
|
||||
/* set transfer block count */
|
||||
EMMC_SD_SRS01 = (1 << EMMC_SD_SRS01_BCCT_SHIFT) | sz;
|
||||
|
||||
/* wait for command and data line busy to clear */
|
||||
while ((EMMC_SD_SRS09 & (EMMC_SD_SRS09_CICMD | EMMC_SD_SRS09_CIDAT)) != 0);
|
||||
|
||||
EMMC_SD_SRS01 = block_addr; /* cmd argument */
|
||||
/* execute command */
|
||||
EMMC_SD_SRS03 = ((cmd_index << EMMC_SD_SRS03_CIDX_SHIFT) |
|
||||
EMMC_SD_SRS03_DPS | EMMC_SD_SRS03_DTDS |
|
||||
EMMC_SD_SRS03_BCE | EMMC_SD_SRS03_RECE | EMMC_SD_SRS03_RID |
|
||||
EMMC_SD_SRS03_RECT | EMMC_SD_SRS03_RESP_48 | EMMC_SD_SRS03_CRCCE |
|
||||
EMMC_SD_SRS03_CICE);
|
||||
|
||||
/* wait for buffer read ready */
|
||||
while (((reg = EMMC_SD_SRS12) & (EMMC_SD_SRS12_BRR | EMMC_SD_SRS12_EINT)) == 0);
|
||||
|
||||
/* read in buffer - read 4 bytes at a time */
|
||||
if (reg & EMMC_SD_SRS12_BRR) {
|
||||
uint32_t i;
|
||||
for (i=0; i<sz; i+=4) {
|
||||
*dst = EMMC_SD_SRS08;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for any errors */
|
||||
reg = EMMC_SD_SRS12;
|
||||
if (reg & EMMC_SD_SRS12_ERR_STAT) {
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_block_read: error: 0x%08X\n", reg);
|
||||
#endif
|
||||
/* wait for idle */
|
||||
mmc_delay(0xFF);
|
||||
status = mmc_wait_busy(0);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int mmc_set_bus_width(uint32_t bus_width)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (bus_width == g_bus_width) {
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set bus width */
|
||||
status = mmc_send_cmd(SD_CMD55_APP_CMD, g_rca << SD_RCA_SHIFT,
|
||||
EMMC_SD_RESP_R1);
|
||||
if (status == 0) {
|
||||
*ocr_reg = EMMC_SD_SRS04;
|
||||
uint32_t cmd_arg = (bus_width == 4) ? 2 : 0;
|
||||
status = mmc_send_cmd(SD_ACMD6_SET_BUS_WIDTH, cmd_arg, EMMC_SD_RESP_R1);
|
||||
if (status == 0) {
|
||||
/* change host bus width */
|
||||
if (bus_width == 4) {
|
||||
EMMC_SD_SRS10 |= EMMC_SD_SRS10_DTW;
|
||||
}
|
||||
else {
|
||||
EMMC_SD_SRS10 &= ~EMMC_SD_SRS10_DTW;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint32_t get_srs_bits(int from, int count)
|
||||
{
|
||||
volatile uint32_t *resp = ((volatile uint32_t*)(EMMC_SD_BASE + 0x210));
|
||||
uint32_t mask, ret;
|
||||
int off, shft;
|
||||
|
||||
from -= 8;
|
||||
mask = (count < 32 ? 1 << count : 0) - 1;
|
||||
off = from / 32;
|
||||
shft = from & 31;
|
||||
ret = resp[off] >> shft;
|
||||
if (from + shft > 32) {
|
||||
ret |= resp[off + 1] << (32 - shft) % 32;
|
||||
}
|
||||
return ret & mask;
|
||||
}
|
||||
|
||||
int mmc_send_switch_function(uint32_t mode, uint32_t function_number, uint32_t group_number)
|
||||
{
|
||||
int status;
|
||||
uint32_t timeout = 4; /* up to 5 tries */
|
||||
uint32_t cmd_arg;
|
||||
uint32_t func_status[64/sizeof(uint32_t)]; /* fixed 512 bits */
|
||||
uint8_t* p_func_status = (uint8_t*)func_status;
|
||||
|
||||
if (group_number > 6 || function_number > 15) {
|
||||
return -1; /* Invalid group or function number */
|
||||
}
|
||||
|
||||
cmd_arg = (function_number << ((group_number - 1) * 4));
|
||||
do {
|
||||
/* first run check to see if function is supported */
|
||||
status = mmc_block_read(SD_CMD_6_SWITCH_FUNC,
|
||||
(mode | cmd_arg),
|
||||
func_status, sizeof(func_status));
|
||||
if (status == 0) {
|
||||
/* check if busy */
|
||||
/* data structure version 368:375
|
||||
* (0=supported only, 1=supported and busy) */
|
||||
if (p_func_status[17] == 1) {
|
||||
/* busy status: group 1 272:287 */
|
||||
if ((p_func_status[29 -
|
||||
((group_number-1)*2)] & (1 << function_number))) {
|
||||
continue; /* busy */
|
||||
}
|
||||
}
|
||||
|
||||
/* supported: group 1 415:400 */
|
||||
if ((p_func_status[13 -
|
||||
((group_number-1)*2)] & (1 << function_number))) {
|
||||
break; /* supported */
|
||||
}
|
||||
else {
|
||||
return -1; /* not supported */
|
||||
}
|
||||
}
|
||||
} while (status == 0 && --timeout > 0); /* retry until function not busy */
|
||||
return status;
|
||||
}
|
||||
|
||||
int mmc_set_function(uint32_t function_number, uint32_t group_number)
|
||||
{
|
||||
/* send check first */
|
||||
int status = mmc_send_switch_function(SDCARD_SWITCH_FUNC_MODE_CHECK,
|
||||
function_number, group_number);
|
||||
if (status == 0) {
|
||||
/* send switch function */
|
||||
status = mmc_send_switch_function(SDCARD_SWITCH_FUNC_MODE_SWITCH,
|
||||
function_number, group_number);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
@ -396,19 +608,22 @@ int mmc_init(void)
|
|||
{
|
||||
int status = 0;
|
||||
uint32_t reg, cap;
|
||||
uint32_t ctrl_volts = EMMC_SD_SRS10_BVS_3_3V; /* default to 3.3v */
|
||||
uint32_t card_volts;
|
||||
int is_xpc, is_si8r;
|
||||
uint32_t ctrl_volts, card_volts;
|
||||
uint32_t irq_restore;
|
||||
int xpc, si8r;
|
||||
|
||||
/* Reset the MMC controller */
|
||||
SYSREG_SOFT_RESET_CR &= ~SYSREG_SOFT_RESET_CR_MMC;
|
||||
/* Disable the EMMC/SD IRQ */
|
||||
|
||||
/* Reset the host controller */
|
||||
EMMC_SD_HRS00 |= EMMC_SD_HRS00_SWR;
|
||||
/* Bit will clear when reset is done */
|
||||
while ((EMMC_SD_HRS00 & EMMC_SD_HRS00_SWR) != 0);
|
||||
|
||||
/* Set debounce period to ~15ms (at 200MHz) */
|
||||
EMMC_SD_HRS01 = (EMMC_SD_DEBOUNCE_TIME & EMMC_SD_HRS01_DP_MASK);
|
||||
EMMC_SD_HRS01 = ((EMMC_SD_DEBOUNCE_TIME << EMMC_SD_HRS01_DP_SHIFT) &
|
||||
EMMC_SD_HRS01_DP_MASK);
|
||||
|
||||
/* Select SDCard Mode */
|
||||
reg = EMMC_SD_HRS06;
|
||||
|
|
@ -427,8 +642,19 @@ int mmc_init(void)
|
|||
reg |= EMMC_SD_SRS15_HV4E;
|
||||
EMMC_SD_SRS15 = reg;
|
||||
}
|
||||
/* Set all status enables */
|
||||
EMMC_SD_SRS13 = 0xFFFFFFFF;
|
||||
/* Set all status enables - 0xbff40ff */
|
||||
EMMC_SD_SRS13 = (
|
||||
EMMC_SD_SRS13_ETUNE_SE | EMMC_SD_SRS13_EADMA_SE | EMMC_SD_SRS13_EAC_SE |
|
||||
EMMC_SD_SRS13_ECL_SE | EMMC_SD_SRS13_EDEB_SE |
|
||||
EMMC_SD_SRS13_EDCRC_SE | EMMC_SD_SRS13_EDT_SE |
|
||||
EMMC_SD_SRS13_ECI_SE | EMMC_SD_SRS13_ECEB_SE | EMMC_SD_SRS13_ECCRC_SE |
|
||||
EMMC_SD_SRS13_ECT_SE | EMMC_SD_SRS13_RTUNE_SE |
|
||||
EMMC_SD_SRS13_INT_ONC | EMMC_SD_SRS13_INT_ONB | EMMC_SD_SRS13_INT_ONA |
|
||||
EMMC_SD_SRS13_CR_SE | EMMC_SD_SRS13_CIN_SE |
|
||||
EMMC_SD_SRS13_BRR_SE | EMMC_SD_SRS13_BWR_SE | EMMC_SD_SRS13_DMAINT_SE |
|
||||
EMMC_SD_SRS13_BGE_SE | EMMC_SD_SRS13_TC_SE | EMMC_SD_SRS13_CC_SE |
|
||||
EMMC_SD_SRS13_ERSP_SE | EMMC_SD_SRS13_CQINT_SE
|
||||
);
|
||||
/* Clear all signal enables */
|
||||
EMMC_SD_SRS14 = 0;
|
||||
/* Set initial timeout to 500ms */
|
||||
|
|
@ -452,32 +678,35 @@ int mmc_init(void)
|
|||
}
|
||||
|
||||
/* Start in 1-bit bus mode */
|
||||
reg = EMMC_SD_SRS10;
|
||||
reg &= ~EMMC_SD_SRS10_DTW;
|
||||
reg &= ~EMMC_SD_SRS10_EDTW;
|
||||
EMMC_SD_SRS10 = reg;
|
||||
EMMC_SD_SRS10 &= ~(EMMC_SD_SRS10_EDTW | EMMC_SD_SRS10_DTW);
|
||||
|
||||
/* Setup 400khz starting clock */
|
||||
mmc_set_clock(EMMC_SD_CLK_400KHZ);
|
||||
|
||||
/* Set power to 3.3v and send init commands */
|
||||
ctrl_volts = EMMC_SD_SRS10_BVS_3_3V; /* default to 3.3v */
|
||||
status = mmc_power_init_seq(ctrl_volts);
|
||||
if (status == 0) {
|
||||
uint32_t max_ma_3_3v, max_ma_1_8v;
|
||||
/* determine host controller capabilities */
|
||||
reg = EMMC_SD_SRS18;
|
||||
max_ma_3_3v = (reg & EMMC_SD_SRS18_MC33_MASK) >> EMMC_SD_SRS18_MC33_SHIFT;
|
||||
max_ma_1_8v = (reg & EMMC_SD_SRS18_MC18_MASK) >> EMMC_SD_SRS18_MC18_SHIFT;
|
||||
/* does it support eXtended Power Control (XPC)? */
|
||||
is_xpc = (max_ma_1_8v >= 150) && (max_ma_3_3v >= 150) ? 1 : 0;
|
||||
/* does it support UHS-I (Ultra High Speed Interface) v1.8 signaling? */
|
||||
is_si8r =((EMMC_SD_SRS16 & EMMC_SD_SRS16_VS18) && /* 1.8v supported */
|
||||
(EMMC_SD_SRS17 & (EMMC_SD_SRS17_DDR50 | /* DDR50, SDR104, SDR50 or supported */
|
||||
EMMC_SD_SRS17_SDR104 |
|
||||
EMMC_SD_SRS17_SDR50))) ? 1: 0;
|
||||
max_ma_3_3v = ((reg & EMMC_SD_SRS18_MC33_MASK) >> EMMC_SD_SRS18_MC33_SHIFT) * 4;
|
||||
max_ma_1_8v = ((reg & EMMC_SD_SRS18_MC18_MASK) >> EMMC_SD_SRS18_MC18_SHIFT) * 4;
|
||||
/* does controller support eXtended Power Control (XPC)? */
|
||||
xpc = (max_ma_1_8v >= 150) && (max_ma_3_3v >= 150) ? 1 : 0;
|
||||
/* does controller support UHS-I (Ultra High Speed Interface) v1.8 signaling? */
|
||||
si8r =((EMMC_SD_SRS16 & EMMC_SD_SRS16_VS18) && /* 1.8v supported */
|
||||
(EMMC_SD_SRS17 & (EMMC_SD_SRS17_DDR50 | /* DDR50, SDR104 or SDR50 supported */
|
||||
EMMC_SD_SRS17_SDR104 |
|
||||
EMMC_SD_SRS17_SDR50))) ? 1: 0;
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_init: xpc:%d, si8r:%d, max_ma (3.3v:%d 1.8v:%d)\n",
|
||||
xpc, si8r, max_ma_3_3v, max_ma_1_8v);
|
||||
#endif
|
||||
}
|
||||
if (status == 0) {
|
||||
reg = 0;
|
||||
/* get operating conditions */
|
||||
status = mmc_card_init(0, ®);
|
||||
if (status == 0) {
|
||||
/* pick host and card operating voltages */
|
||||
|
|
@ -503,6 +732,9 @@ int mmc_init(void)
|
|||
}
|
||||
/* if needed change operating volage and re-init */
|
||||
if (ctrl_volts != EMMC_SD_SRS10_BVS_3_3V) {
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_init: changing operating voltage to 3.0v\n");
|
||||
#endif
|
||||
status = mmc_power_init_seq(ctrl_volts);
|
||||
}
|
||||
}
|
||||
|
|
@ -511,19 +743,130 @@ int mmc_init(void)
|
|||
/* configure operating conditions */
|
||||
uint32_t cmd_arg = SDCARD_ACMD41_HCS;
|
||||
cmd_arg |= card_volts;
|
||||
if (is_si8r) {
|
||||
if (si8r) {
|
||||
cmd_arg |= SDCARD_REG_OCR_S18RA;
|
||||
}
|
||||
if (is_xpc) {
|
||||
if (xpc) {
|
||||
cmd_arg |= SDCARD_REG_OCR_XPC;
|
||||
}
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_init: sending OCR arg: 0x%08X\n", cmd_arg);
|
||||
#endif
|
||||
|
||||
/* retry until OCR ready */
|
||||
do {
|
||||
status = mmc_card_init(cmd_arg, ®);
|
||||
} while (status == 0 && (reg & SDCARD_REG_OCR_READY) == 0);
|
||||
}
|
||||
if (status == 0) {
|
||||
/* Get card identification */
|
||||
status = mmc_send_cmd(MMC_CMD2_ALL_SEND_CID, 0, EMMC_SD_RESP_R2);
|
||||
}
|
||||
if (status == 0) {
|
||||
/* Set relative address */
|
||||
status = mmc_send_cmd(MMC_CMD3_SET_REL_ADDR, 0, EMMC_SD_RESP_R6);
|
||||
}
|
||||
if (status == 0) {
|
||||
g_rca = ((EMMC_SD_SRS04 >> SD_RCA_SHIFT) & 0xFFFF);
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_init: rca: %d\n", g_rca);
|
||||
#endif
|
||||
}
|
||||
if (status == 0) {
|
||||
/* read CSD register from device */
|
||||
status = mmc_send_cmd(MMC_CMD9_SEND_CSD, g_rca << SD_RCA_SHIFT,
|
||||
EMMC_SD_RESP_R2);
|
||||
}
|
||||
if (status == 0) {
|
||||
/* Get sector size and count */
|
||||
uint32_t csd_struct;
|
||||
uint32_t c_size = 0;
|
||||
#define SECT_SIZE_CSD_MASK 0x03C000
|
||||
#define SECT_SIZE_CSD_SHIFT 14
|
||||
c_size = (EMMC_SD_SRS04 & SECT_SIZE_CSD_MASK) >> SECT_SIZE_CSD_SHIFT;
|
||||
if (c_size < 32) {
|
||||
g_sector_size = (1 << c_size);
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_init: sector size: %d\n", g_sector_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
csd_struct = get_srs_bits(126,2);
|
||||
switch (csd_struct) {
|
||||
case 0:
|
||||
c_size = get_srs_bits(62, 12);
|
||||
g_sector_count = (c_size + 1) << (get_srs_bits(47, 3) + 2);
|
||||
break;
|
||||
case 1:
|
||||
c_size = get_srs_bits(48, 22);
|
||||
g_sector_count = (c_size + 1) << 10;
|
||||
break;
|
||||
default:
|
||||
/* invalid CSR structure */
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_MMC
|
||||
wolfBoot_printf("mmc_init: sector count: %d\n", g_sector_count);
|
||||
#endif
|
||||
}
|
||||
if (status == 0) {
|
||||
/* select card */
|
||||
status = mmc_send_cmd(MMC_CMD7_SELECT_CARD, g_rca << SD_RCA_SHIFT,
|
||||
EMMC_SD_RESP_R1B);
|
||||
if (status == DEVICE_BUSY) {
|
||||
status = mmc_wait_busy(1);
|
||||
}
|
||||
}
|
||||
if (status == 0) {
|
||||
/* disable card insert interrupt while changing bus width to avoid false triggers */
|
||||
irq_restore = EMMC_SD_SRS13;
|
||||
EMMC_SD_SRS13 = (irq_restore & ~EMMC_SD_SRS13_CINT_SE);
|
||||
mmc_delay(DEFAULT_DELAY);
|
||||
|
||||
status = mmc_set_bus_width(4);
|
||||
}
|
||||
if (status == 0) {
|
||||
/* Get SCR registers - 8 bytes */
|
||||
uint32_t scr_reg[SCR_REG_DATA_SIZE/sizeof(uint32_t)];
|
||||
|
||||
status = mmc_send_cmd(SD_CMD_16, sizeof(scr_reg), EMMC_SD_RESP_R1);
|
||||
if (status == 0) {
|
||||
status = mmc_send_cmd(SD_CMD55_APP_CMD, (g_rca << SD_RCA_SHIFT),
|
||||
EMMC_SD_RESP_R1);
|
||||
}
|
||||
if (status == 0) {
|
||||
status = mmc_block_read(SD_ACMD51_SEND_SCR, 0, scr_reg,
|
||||
sizeof(scr_reg));
|
||||
}
|
||||
}
|
||||
if (status == 0) {
|
||||
/* set UHS mode to SDR25 and driver strength to Type B */
|
||||
uint32_t card_access_mode = SDCARD_SWITCH_ACCESS_MODE_SDR25;
|
||||
status = mmc_set_function(card_access_mode, 1);
|
||||
if (status == 0) {
|
||||
/* set driver strength */
|
||||
reg = EMMC_SD_SRS15;
|
||||
reg &= ~EMMC_SD_SRS15_DSS_MASK;
|
||||
reg |= EMMC_SD_SRS15_DSS_TYPE_B; /* default */
|
||||
EMMC_SD_SRS15 = reg;
|
||||
|
||||
/* eanble high speed */
|
||||
EMMC_SD_SRS10 |= EMMC_SD_SRS10_HSE;
|
||||
|
||||
/* set UHS mode */
|
||||
reg = EMMC_SD_SRS15;
|
||||
reg &= ~EMMC_SD_SRS15_UMS_MASK;
|
||||
reg |= EMMC_SD_SRS15_UMS_SDR25;
|
||||
EMMC_SD_SRS15 = reg;
|
||||
}
|
||||
}
|
||||
if (status == 0) {
|
||||
mmc_set_clock(EMMC_SD_CLK_50MHZ);
|
||||
|
||||
/* TODO: Phy training at SDR25 (50MHz) */
|
||||
|
||||
EMMC_SD_SRS13 = irq_restore; /* re-enable interrupt */
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,10 @@
|
|||
#define SIE_STIE (1 << IRQ_S_TIMER)
|
||||
#define SIE_SEIE (1 << IRQ_S_EXT)
|
||||
|
||||
#define MCAUSE64_INT 0x8000000000000000LLU
|
||||
#define MCAUSE64_CAUSE 0x7FFFFFFFFFFFFFFFLLU
|
||||
|
||||
|
||||
|
||||
/* UART */
|
||||
#define MSS_UART0_LO_BASE 0x20000000UL
|
||||
|
|
@ -401,6 +405,7 @@
|
|||
#define EMMC_SD_SRS09_DAT2_LVL (1U << 22) /* 22: RO - DAT2 signal level */
|
||||
#define EMMC_SD_SRS09_DAT1_LVL (1U << 21) /* 21: RO - DAT1 signal level */
|
||||
#define EMMC_SD_SRS09_DAT0_LVL (1U << 20) /* 20: RO - DAT0 signal level */
|
||||
#define EMMC_SD_SRS09_DATS_LVL (EMMC_SD_SRS09_DAT0_LVL | EMMC_SD_SRS09_DAT1_LVL | EMMC_SD_SRS09_DAT2_LVL | EMMC_SD_SRS09_DAT3_LVL)
|
||||
#define EMMC_SD_SRS09_WPSL (1U << 19) /* 19: RO - Write Protect Switch Level */
|
||||
#define EMMC_SD_SRS09_CDSL (1U << 18) /* 18: RO - Card Detect Pin Level */
|
||||
#define EMMC_SD_SRS09_CSS (1U << 17) /* 17: RO - Card State Stable */
|
||||
|
|
@ -462,7 +467,6 @@
|
|||
#define EMMC_SD_SRS11_SDCFSL_MASK (0xFFU << 8)
|
||||
#define EMMC_SD_SRS11_SDCFSH_SHIFT 6 /* 7:6: RW - SDCLK Freq Select (upper 2 bits) */
|
||||
#define EMMC_SD_SRS11_SDCFSH_MASK (0x3U << 6)
|
||||
#define EMMC_SD_SRS11_SDCFS_MASK (0xFF00U | 0x00C0U) /* Full SDCLK Freq Select mask */
|
||||
#define EMMC_SD_SRS11_CGS (1U << 5) /* 5: RW - Clock Generator Select */
|
||||
#define EMMC_SD_SRS11_SDCE (1U << 2) /* 2: RW - SD Clock Enable */
|
||||
#define EMMC_SD_SRS11_ICS (1U << 1) /* 1: RO - Internal Clock Stable */
|
||||
|
|
@ -501,6 +505,7 @@
|
|||
|
||||
#define EMMC_SD_SRS13 *((volatile uint32_t*)(EMMC_SD_BASE + 0x234)) /* Error/Normal Status Enable */
|
||||
#define EMMC_SD_SRS13_ERSP_SE (1U << 27) /* 27: RW - Response Error Status Enable (SD mode only) */
|
||||
#define EMMC_SD_SRS13_ETUNE_SE (1U << 26) /* 26: RW - Tuning Error Status Enable (SD mode only) */
|
||||
#define EMMC_SD_SRS13_EADMA_SE (1U << 25) /* 25: RW - ADMA Error Status Enable (SD mode only) */
|
||||
#define EMMC_SD_SRS13_EAC_SE (1U << 24) /* 24: RW - Auto CMD Error Status Enable (SD mode only) */
|
||||
#define EMMC_SD_SRS13_ECL_SE (1U << 23) /* 23: RW - Current Limit Error Status Enable (SD mode only) */
|
||||
|
|
@ -512,6 +517,10 @@
|
|||
#define EMMC_SD_SRS13_ECCRC_SE (1U << 17) /* 17: RW - Command CRC Error Status Enable (SD mode only) */
|
||||
#define EMMC_SD_SRS13_ECT_SE (1U << 16) /* 16: RW - Command Timeout Error Status Enable (SD mode only) */
|
||||
#define EMMC_SD_SRS13_CQINT_SE (1U << 14) /* 14: RW - Command Queuing Status Enable */
|
||||
#define EMMC_SD_SRS13_RTUNE_SE (1U << 12) /* 12: RW - Retuning event status enable */
|
||||
#define EMMC_SD_SRS13_INT_ONC (1U << 11) /* 11: RW - Interrupt On Line C status enable */
|
||||
#define EMMC_SD_SRS13_INT_ONB (1U << 10) /* 10: RW - Interrupt On Line B status enable */
|
||||
#define EMMC_SD_SRS13_INT_ONA (1U << 9) /* 9: RW - Interrupt On Line A status enable */
|
||||
#define EMMC_SD_SRS13_CINT_SE (1U << 8) /* 8: RW - Card Interrupt Status Enable */
|
||||
#define EMMC_SD_SRS13_CR_SE (1U << 7) /* 7: RW - Card Removal Status Enable */
|
||||
#define EMMC_SD_SRS13_CIN_SE (1U << 6) /* 6: RW - Card Insertion Status Enable */
|
||||
|
|
@ -804,7 +813,7 @@
|
|||
#define EMMC_SD_BLOCK_SIZE 512U /* Standard block size */
|
||||
|
||||
/* SD Interface Conditions */
|
||||
#define IF_COND_27V_33V (1u << 8u)
|
||||
#define IF_COND_27V_33V (1U << 8)
|
||||
|
||||
/* SD OCR register bits definitions */
|
||||
#define SDCARD_REG_OCR_2_7_2_8 (1U << 15)
|
||||
|
|
@ -830,20 +839,24 @@
|
|||
#define MMC_CMD3_SET_REL_ADDR 3 /* MMC: Set relative address */
|
||||
#define SD_CMD3_SEND_REL_ADDR 3 /* SD: Get relative address */
|
||||
#define MMC_CMD_4_SET_DSR 4
|
||||
#define MMC_CMD6_SWITCH 6 /* Switch/set EXT_CSD */
|
||||
#define SD_CMD_6_SWITCH_FUNC 6 /* SD: Switch function */
|
||||
#define MMC_CMD7_SELECT_CARD 7 /* Select/deselect card */
|
||||
#define MMC_CMD8_SEND_EXT_CSD 8 /* MMC: Get EXT_CSD */
|
||||
#define SD_CMD8_SEND_IF_COND 8 /* SD: Send interface condition */
|
||||
#define MMC_CMD9_SEND_CSD 9 /* Get card-specific data */
|
||||
#define SD_CMD11_VOLAGE_SWITCH 11 /* R1 Rsp */
|
||||
#define MMC_CMD12_STOP_TRANS 12 /* Stop transmission */
|
||||
#define MMC_CMD13_SEND_STATUS 13 /* Get card status */
|
||||
#define MMC_CMD_15_GOTO_INACT_ST 15
|
||||
#define SD_CMD_16 16 /* R1 Rsp */
|
||||
#define MMC_CMD17_READ_SINGLE 17 /* Read single block */
|
||||
#define MMC_CMD18_READ_MULTIPLE 18 /* Read multiple blocks */
|
||||
#define MMC_CMD24_WRITE_SINGLE 24 /* Write single block */
|
||||
#define MMC_CMD25_WRITE_MULTIPLE 25 /* Write multiple blocks */
|
||||
|
||||
#define SD_CMD55_APP_CMD 55 /* Prefix for ACMD */
|
||||
#define SD_ACMD41_SD_SEND_OP 41 /* SD: Send operating conditions */
|
||||
#define SD_ACMD6_SET_BUS_WIDTH 6 /* SD: Set bus width */
|
||||
#define SD_ACMD41_SEND_OP_COND 41 /* SD: Send operating conditions */
|
||||
#define SD_ACMD51_SEND_SCR 51 /* SD: Get SCR register */
|
||||
|
||||
/* Debouncing time for card detect */
|
||||
|
|
@ -860,15 +873,24 @@
|
|||
|
||||
#define MAX_CURRENT_MA 150 /* mA */
|
||||
|
||||
#if 0
|
||||
EMMC MSSIO_B4
|
||||
EMMC_DATA_7_4 MSSIO_B4
|
||||
EMMC_SD_CLK_SOURCE MSS_PLL
|
||||
EMMC_SD_SDIO_FREQ 200
|
||||
EMMC_SD_SWITCHING ENABLED_SD
|
||||
EMMC_SPEED_MODE HIGH_SPEED_200
|
||||
#endif
|
||||
#define SD_RCA_SHIFT 16
|
||||
|
||||
#define SCR_REG_DATA_SIZE 8
|
||||
|
||||
/* Switch Function Command Arguments */
|
||||
#define SDCARD_SWITCH_FUNC_MODE_SWITCH (0x1u << 31) /* Set function mode */
|
||||
#define SDCARD_SWITCH_FUNC_MODE_CHECK (0x0u << 31) /* Check mode */
|
||||
/* group 1 - function 1 */
|
||||
#define SDCARD_SWITCH_ACCESS_MODE_SDR12 0x0U /* Card access mode - SDR12 default */
|
||||
#define SDCARD_SWITCH_ACCESS_MODE_SDR25 0x1U /* Card access mode - SDR25 high speed */
|
||||
#define SDCARD_SWITCH_ACCESS_MODE_SDR50 0x2U /* Card access mode - SDR50 */
|
||||
#define SDCARD_SWITCH_ACCESS_MODE_SDR104 0x3U /* Card access mode - SDR104 */
|
||||
#define SDCARD_SWITCH_ACCESS_MODE_DDR50 0x4U /* Card access mode - DDR50 */
|
||||
|
||||
#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_B 0x0U /* Card driver strength - Type B default */
|
||||
#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_A 0x1U /* Card driver strength - Type A */
|
||||
#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_C 0x2U /* Card driver strength - Type C */
|
||||
#define SDCARD_SWITCH_DRIVER_STRENGTH_TYPE_D 0x3U /* Card driver strength - Type D */
|
||||
|
||||
|
||||
/* Crypto Engine: Athena F5200 TeraFire Crypto Processor (1x), 200 MHz */
|
||||
|
|
|
|||
|
|
@ -47,9 +47,15 @@ extern void (* const trap_vector_table[])(void);
|
|||
/* reloc_trap_vector is implemented in boot_riscv64_start.S */
|
||||
extern void reloc_trap_vector(const uint32_t *address);
|
||||
|
||||
unsigned long handle_trap(unsigned long cause, unsigned long epc, unsigned long tval)
|
||||
static uint64_t last_cause = 0;
|
||||
static uint64_t last_epc = 0;
|
||||
static uint64_t last_tval = 0;
|
||||
|
||||
unsigned long WEAKFUNCTION handle_trap(unsigned long cause, unsigned long epc, unsigned long tval)
|
||||
{
|
||||
/* TODO: Implement trap handling */
|
||||
last_cause = cause;
|
||||
last_epc = epc;
|
||||
last_tval = tval;
|
||||
return epc;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue