1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 16:16:16 +04:00
This commit is contained in:
BenjaminPMLovegood 2019-05-20 03:14:37 +08:00
parent 8c3323c4d4
commit e9588086be

View File

@ -257,6 +257,9 @@ const APP_CMD: u32 = 55;
const GEN_CMD: u32 = 56;
const IS_APP_CMD: u32 = 0x80000000;
macro_rules! ACMD {
($a: expr) => ((($a) | (IS_APP_CMD)));
}
const SET_BUS_WIDTH: u32 = (6 | IS_APP_CMD);
const SD_STATUS: u32 = (13 | IS_APP_CMD);
const SEND_NUM_WR_BLOCKS: u32 = (22 | IS_APP_CMD);
@ -273,7 +276,7 @@ const SD_RESET_ALL: u32 = (1 << 24);
pub struct SDScr {
scr: [u32; 2],
sd_bus_widths: u32,
sd_version: i32
sd_version: u32
}
impl SDScr {
@ -315,6 +318,10 @@ fn usleep(cnt: u32) {
thread::sleep(Duration::from_micros(cnt.into()));
}
fn byte_swap(b: u32) -> u32 {
(b >> 24) | ((b & 0xFF0000) >> 8) | ((b & 0xFF00) << 8) | ((b & 0xFF) << 24)
}
/*
* TODO:
* ++ static void sd_power_off()
@ -335,7 +342,7 @@ fn usleep(cnt: u32) {
* ++ static int sd_ensure_data_mode(struct emmc_block_dev *edev)
* -- static int sd_suitable_for_dma(void *buf)
* -- static int sd_do_data_command(struct emmc_block_dev *edev, int is_write, uint8_t *buf, size_t buf_size, uint32_t block_no)
* int sd_card_init(struct block_device **dev)
* ++ int sd_card_init(struct block_device **dev)
* ++ int sd_read(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no)
* ++ int sd_write(struct block_device *dev, uint8_t *buf, size_t buf_size, uint32_t block_no)
* Other Constants
@ -403,6 +410,11 @@ impl EmmcCtl {
self.emmc.registers.CONTROL0.write(ctl0 & !(1 << 8));
}
pub fn sd_get_base_clock_hz(&mut self) -> u32 {
// todo: use mailbox instead
0
}
pub fn sd_get_clock_divider(&mut self, base_clock: u32, target_rate: u32) -> u32 {
let targetted_divisor: u32 = if (target_rate > base_clock) { 1 }
else {
@ -692,6 +704,332 @@ impl EmmcCtl {
0
}
pub fn sd_card_init(&mut self) -> bool {
let ver = self.emmc.registers.SLOTISR_VER.read();
let vendor = ver >> 24;
let sdversion = (ver >> 16) & 0xff;
let slot_status = ver & 0xff;
let mut control0 = self.emmc.registers.CONTROL0.read();
let mut control1 = self.emmc.registers.CONTROL1.read();
control1 |= (1 << 24);
// Disable clock
control1 &= !(1 << 2);
control1 &= !(1 << 0);
self.emmc.registers.CONTROL1.write(control1);
if !timeout_wait!((self.emmc.registers.CONTROL1.read() & (0x7 << 24)) == 0) {
return false;
}
// Check for a valid card
if !timeout_wait!(self.emmc.registers.STATUS.read() & (1 << 16) != 0, 500000) {
return false;
}
// Clear control2
self.emmc.registers.CONTROL2.write(0);
let clk = self.sd_get_base_clock_hz();
let base_clock = if clk > 0 { clk } else { 100000000 };
// Set clock rate to something slow
control1 = self.emmc.registers.CONTROL1.read();
control1 |= 1;
let f_id = self.sd_get_clock_divider(base_clock, 400000);
control1 |= f_id;
control1 |= (7 << 16); // data timeout = TMCLK * 2^10
self.emmc.registers.CONTROL1.write(control1);
if !timeout_wait!(self.emmc.registers.CONTROL1.read() & 0x2 != 0) {
return false;
}
// Enable the SD clock
usleep(2000);
control1 = self.emmc.registers.CONTROL1.read();
control1 |= 4;
self.emmc.registers.CONTROL1.write(control1);
usleep(2000);
// Mask off sending interrupts to the ARM
self.emmc.registers.IRPT_EN.write(0);
// Reset interrupts
self.emmc.registers.INTERRUPT.write(0xffffffff);
// Have all interrupts sent to the INTERRUPT register
let irpt_mask = 0xffffffff & (!SD_CARD_INTERRUPT);
self.emmc.registers.IRPT_MASK.write(0xffffffff);
usleep(2000);
self.block_size = 512;
self.base_clock = base_clock;
// Send CMD0 to the card (reset to idle state)
if !self.sd_issue_command(0 /* GO_IDLE_STATE */, 0, 500000) {
return false;
}
// Send CMD8 to the card
// Voltage supplied = 0x1 = 2.7-3.6V (standard)
// Check pattern = 10101010b (as per PLSS 4.3.13) = 0xAA
let v2_later = if !self.sd_issue_command(8 /* SEND_IF_COND */, 0x1aa, 500000) {
if self.last_error == 0 {
false
} else if self.last_error & (1 << 16) != 0 {
if !self.sd_reset_cmd() {
return false;
}
self.emmc.registers.INTERRUPT.write(SD_ERR_MASK_CMD_TIMEOUT);
false
} else {
return false;
}
} else {
if self.last_r[0] & 0xfff != 0x1aa {
return false;
}
true
};
// Here we are supposed to check the response to CMD5 (HCSS 3.6)
// It only returns if the card is a SDIO card
let _t = self.sd_issue_command(5 /* IO_SET_OP_COND */, 0, 10000);
if !((!_t) && self.last_error == 0) {
if (!_t) && self.last_error & (1 << 16) != 0 {
if !self.sd_reset_cmd() {
return false;
}
self.emmc.registers.INTERRUPT.write(SD_ERR_MASK_CMD_TIMEOUT);
} else {
return false;
}
}
if !self.sd_issue_command(ACMD!(41), 0, 500000) {
return false;
}
let mut card_is_busy = true;
while card_is_busy {
let v2_flags = if v2_later {
(1 << 30) | if self.failed_voltage_switch == 0 {
(1 << 24)
} else {
0
}
} else {
0
};
if !self.sd_issue_command(ACMD!(41), 0x00ff8000 | v2_flags, 500000) {
return false;
}
if (self.last_r[0] >> 31) & 0x1 != 0 {
self.card_ocr = (self.last_r[0] >> 8) & 0xffff;
self.card_supports_sdhc = (self.last_r[0] >> 30) & 0x1 != 0;
if self.failed_voltage_switch == 0 {
self.card_supports_18v = (self.last_r[0] >> 24) & 0x1 != 0;
}
card_is_busy = false;
} else {
usleep(500000);
}
}
// At this point, we know the card is definitely an SD card, so will definitely
// support SDR12 mode which runs at 25 MHz
self.sd_switch_clock_rate(base_clock, 25000000 /* SD_CLOCK_NORMAL */);
// A small wait before the voltage switch
usleep(5000);
// Switch to 1.8V mode if possible
if (self.card_supports_18v) {
// As per HCSS 3.6.1
// Send VOLTAGE_SWITCH
if !self.sd_issue_command(11 /* VOLTAGE_SWITCH */, 0, 500000) {
self.failed_voltage_switch = 1;
self.sd_power_off();
return self.sd_card_init();
}
// Disable SD clock
control1 = self.emmc.registers.CONTROL1.read();
control1 &= !(1 << 2);
self.emmc.registers.CONTROL1.write(control1);
// Check DAT[3:0]
let status_reg = self.emmc.registers.STATUS.read();
if ((status_reg >> 20) & 0xf) != 0 {
self.failed_voltage_switch = 1;
self.sd_power_off();
return self.sd_card_init();
}
// Set 1.8V signal enable to 1
control0 = self.emmc.registers.CONTROL0.read();
control0 |= (1 << 8);
self.emmc.registers.CONTROL0.write(control0);
usleep(5000);
// Check the 1.8V signal enable is set
control0 = self.emmc.registers.CONTROL0.read();
if ((control0 >> 8) & 0x1) == 0 {
self.failed_voltage_switch = 1;
self.sd_power_off();
return self.sd_card_init();
}
// Re-enable SD clock
control1 = self.emmc.registers.CONTROL1.read();
control1 |= (1 << 2);
self.emmc.registers.CONTROL1.write(control1);
// Wait 1 ms
usleep(10000);
// Check DAT[3:0]
let status_reg = self.emmc.registers.STATUS.read();
if ((status_reg >> 20) & 0xf) != 0xf {
self.failed_voltage_switch = 1;
self.sd_power_off();
return self.sd_card_init();
}
}
if !self.sd_issue_command(2 /* ALL_SEND_CID */, 0, 500000) {
return false;
}
let card_cid = [ self.last_r[0], self.last_r[1], self.last_r[2], self.last_r[3] ];
if ! self.sd_issue_command(3 /* SEND_RELATIVE_ADDR */, 0, 500000) {
return false;
}
let cmd3_resp = self.last_r[0];
self.card_rca = (cmd3_resp >> 16) & 0xffff;
if (cmd3_resp >> 15) & 0x1 != 0 { // CRC error
return false;
}
if (cmd3_resp >> 14) & 0x1 != 0 { // illegal command
return false;
}
if (cmd3_resp >> 13) & 0x1 != 0 { // generic error
return false;
}
if (cmd3_resp >> 8) & 0x1 == 0 { // not ready for data
return false;
}
if !self.sd_issue_command(7 /* SELECT_CARD */, self.card_rca << 16 , 500000) {
return false;
}
// Now select the card (toggles it to transfer state)
let cmd7_resp = self.last_r[0];
let status = (cmd7_resp >> 9) & 0xf;
if status != 3 && status != 4 {
return false;
}
// If not an SDHC card, ensure BLOCKLEN is 512 bytes
if !self.card_supports_sdhc {
if !self.sd_issue_command(16 /* SET_BLOCKLEN */, 512, 500000) {
return false;
}
}
self.block_size = 512;
let mut controller_block_size = self.emmc.registers.BLKSIZECNT.read();
controller_block_size &= (!0xfff);
controller_block_size |= 0x200;
self.emmc.registers.BLKSIZECNT.write(controller_block_size);
self.block_size = 8;
self.blocks_to_transfer = 1;
if !self.sd_issue_command(SEND_SCR, 0, 500000) {
self.block_size = 512;
return false;
}
self.block_size = 512;
// Determine card version
// Note that the SCR is big-endian
let scr0 = byte_swap(self.sd_scr.scr[0]);
self.sd_scr.sd_version = SD_VER_UNKNOWN;
let sd_spec = (scr0 >> (56 - 32)) & 0xf;
let sd_spec3 = (scr0 >> (47 - 32)) & 0x1;
let sd_spec4 = (scr0 >> (42 - 32)) & 0x1;
self.sd_scr.sd_bus_widths = (scr0 >> (48 - 32)) & 0xf;
self.sd_scr.sd_version = if sd_spec == 0 {
SD_VER_1
} else if sd_spec == 1 {
SD_VER_1_1
} else if sd_spec == 2 {
if sd_spec3 == 0 {
SD_VER_2
} else if sd_spec3 == 1 {
if sd_spec4 == 0 {
SD_VER_3
} else if sd_spec4 == 1 {
SD_VER_4
} else {
SD_VER_UNKNOWN
}
} else {
SD_VER_UNKNOWN
}
} else {
SD_VER_UNKNOWN
};
if self.sd_scr.sd_bus_widths & 0x4 != 0 {
// Set 4-bit transfer mode (ACMD6)
// See HCSS 3.4 for the algorithm
// Disable card interrupt in host
let old_irpt_mask = self.emmc.registers.IRPT_MASK.read();
let new_irpt_mask = old_irpt_mask & !(1 << 8);
self.emmc.registers.IRPT_MASK.write(new_irpt_mask);
// Send ACMD6 to change the card's bit mode
if self.sd_issue_command(SET_BUS_WIDTH, 0x2, 500000) {
// Change bit mode for Host
control0 = self.emmc.registers.CONTROL0.read();
control0 |= 0x2;
self.emmc.registers.CONTROL0.write(control0);
// Re-enable card interrupt in host
self.emmc.registers.IRPT_MASK.write(old_irpt_mask);
}
}
// Reset interrupt register
self.emmc.registers.INTERRUPT.write(0xffffffff);
true
}
pub fn read(&mut self, block_no_arg: u32, count: usize, buf: &mut[u32]) -> Result<(), ()> {
let mut block_no = block_no_arg;
if self.card_supports_sdhc {