Skip to content

Commit

Permalink
sdmmc: some clean up before pull request
Browse files Browse the repository at this point in the history
Signed-off-by: Cheng <[email protected]>
  • Loading branch information
Cheng-Li1 committed Oct 21, 2024
1 parent b79d8ef commit a8080c6
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 65 deletions.
26 changes: 17 additions & 9 deletions drivers/blk/sdmmc/sdmmc_hal/meson/meson_gx_mmc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ use sel4_microkit::debug_println;

const SDIO_BASE: u64 = 0xffe05000; // Base address from DTS

macro_rules! div_round_up {
($n:expr, $d:expr) => {
(($n + $d - 1) / $d)
};
}

// Constants translated from the C version
// Clock related constant
const SD_EMMC_CLKSRC_24M: u32 = 24000000; // 24 MHz
const SD_EMMC_CLKSRC_DIV2: u32 = 1000000000; // 1 GHz

const CLK_MAX_DIV: u32 = 63;
const CLK_SRC_24M: u32 = 0 << 6;
const CLK_SRC_DIV2: u32 = 1 << 6;
Expand All @@ -21,12 +26,6 @@ const CLK_TX_PHASE_000: u32 = 0 << 10;
const CLK_TX_PHASE_180: u32 = 2 << 10;
const CLK_ALWAYS_ON: u32 = 1 << 24;

macro_rules! div_round_up {
($n:expr, $d:expr) => {
(($n + $d - 1) / $d)
};
}

// CMD_CFG constants
const CMD_CFG_CMD_INDEX_SHIFT: u32 = 24;
const CMD_CFG_RESP_128: u32 = 1 << 21;
Expand Down Expand Up @@ -167,7 +166,7 @@ impl MesonSdmmcRegisters {
/// * `mmc_clock` - The desired clock frequency in Hz.
/// * `is_sm1_soc` - A boolean indicating whether the SoC is an SM1 variant.
/// * For odorid C4, this is_sm1_soc is true
pub fn meson_mmc_config_clock(&mut self) {
fn meson_mmc_config_clock(&mut self, frequency: u32) {
// #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
let mut meson_mmc_clk:u32 = 0;

Expand All @@ -177,7 +176,7 @@ impl MesonSdmmcRegisters {
let clk: u32;
let clk_src: u32;
// 400 khz for init the card
let clock_freq: u32 = 400000;
let clock_freq: u32 = frequency;
if clock_freq > 16000000 {
clk = SD_EMMC_CLKSRC_DIV2;
clk_src = CLK_SRC_DIV2;
Expand All @@ -194,6 +193,7 @@ impl MesonSdmmcRegisters {
* Other SoCs use CLK_CO_PHASE_180 by default.
* It needs to find what is a proper value about each SoCs.
* Since we are using Odroid C4, we set phase to 270
* TODO: Config it as what Linux driver are doing
*/
meson_mmc_clk |= CLK_CO_PHASE_270;
meson_mmc_clk |= CLK_TX_PHASE_000;
Expand All @@ -204,6 +204,14 @@ impl MesonSdmmcRegisters {
unsafe { ptr::write_volatile(&mut self.clock, meson_mmc_clk); }
}

// Incomplete placeholder function, need regulator system to configure voltage
pub fn meson_set_ios(&mut self) {
/*
* This function should be able to adjust the voltage, frequency and number of data lanes in use
*
*/
}

// This function can be seen as a Rust version of meson_mmc_setup_cmd function in uboot
fn meson_mmc_set_up_cmd_cfg_and_cfg(&mut self, cmd: &SdmmcCmd, data: Option<&MmcData>) {
let mut meson_mmc_cmd: u32 = 0u32;
Expand Down
3 changes: 3 additions & 0 deletions drivers/blk/sdmmc/sdmmc_protocol/sdmmc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub trait SdmmcHardware {
}
}

// Not used right now, but would be useful in the future once we want to execute some command synchronously
fn send_cmd_and_receive_resp<T: SdmmcHardware>(
hardware: &mut T,
cmd: &SdmmcCmd,
Expand Down Expand Up @@ -143,8 +144,10 @@ impl<'a, T: SdmmcHardware> SdmmcProtocol<'a, T> {
}
}

// Funtion that is not completed
pub fn reset_card(&mut self) -> Result<(), SdmmcHalError> {
let all: u32 = InterruptType::Success as u32 | InterruptType::Error as u32 | InterruptType::SDIO as u32;
todo!();
self.hardware.sdmmc_ack_interrupt(&all)
}

Expand Down
61 changes: 5 additions & 56 deletions drivers/blk/sdmmc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ const SDDF_TO_REAL_SECTOR: u32 = SDDF_TRANSFER_SIZE/SDCARD_SECTOR_SIZE;

const RETRY_CHANCE: u16 = 5;

// Debug function for printing out content in one block
#[allow(dead_code)]
fn print_one_block(ptr: *const u8) {
unsafe {
// Iterate over the 512 bytes and print each one in hexadecimal format
Expand Down Expand Up @@ -129,13 +131,12 @@ impl<'a, T: SdmmcHardware> Handler for HandlerImpl<'a, T> {
if request.count == 0 {
let resp_status = BlkStatus::BlkRespOk;
notify_virt = true;
// Have to divide the SDDF_TO_REAL_SECTOR here, we should really use real sector
unsafe { blk_enqueue_resp_helper(resp_status, request.success_count / SDDF_TO_REAL_SECTOR, request.id); }
unsafe { blk_enqueue_resp_helper(resp_status, request.success_count, request.id); }
self.request = None;
} else if self.retry == 0 {
let resp_status = BlkStatus::BlkRespSeekError;
notify_virt = true;
unsafe { blk_enqueue_resp_helper(resp_status, request.success_count / SDDF_TO_REAL_SECTOR, request.id); }
unsafe { blk_enqueue_resp_helper(resp_status, request.success_count, request.id); }
self.request = None;
}
}
Expand Down Expand Up @@ -239,56 +240,4 @@ impl<'a, T: SdmmcHardware> Handler for HandlerImpl<'a, T> {
}
Ok(())
}
}

/*
// Code block to test block read
{
let test_hal: &mut MesonSdmmcRegisters = MesonSdmmcRegisters::new();
let test: SdmmcProtocol<'static, MesonSdmmcRegisters> = SdmmcProtocol::new(test_hal);
debug_println!("Read and Print out the content in sector 0, sector 1");
let mut future = Box::pin(test.read_block(2, 0, 0x50000000));
let waker = create_dummy_waker();
let mut cx = Context::from_waker(&waker);
let future_ref = &mut future;
// TODO: I can get rid of this loop once I configure out how to enable interrupt from Linux kernel driver
loop {
match future_ref.as_mut().poll(&mut cx) {
Poll::Ready((result, sdmmc)) => {
// debug_println!("SDMMC_DRIVER: Future completed with result");
if result.is_err() {
debug_println!("SDMMC_DRIVER: DISK ERROR ENCOUNTERED, possiblely retry!");
}
else {
debug_println!("Content in sector 0:");
print_one_block(0x50000000 as *const u8);
debug_println!("Content in sector 1:");
print_one_block((0x50000000 + 512) as *const u8);
}
break;
}
Poll::Pending => {
// debug_println!("SDMMC_DRIVER: Future is not ready, polling again...");
}
}
}
}
// Poll on the future once to start it up
let waker = create_dummy_waker();
let mut cx = Context::from_waker(&waker);
if let Some(new_future) = self.future {
let res = new_future.as_mut().poll(&mut cx);
// If the first poll on the future is not pending, why are you even use async then?
match res {
Poll::Pending => {
// The future is pending, this is the desired case
}
Poll::Ready(_) => {
// The future is ready, handle the result here if needed
panic!("Expected Poll::Pending but got Poll::Ready. Why are you even use async if the first poll on the future is not pending?");
}
}
}
*/
}

0 comments on commit a8080c6

Please sign in to comment.