sdio-adma2-refactor #34
|
@ -1,89 +1,76 @@
|
|||
/// ADMA library
|
||||
use core::mem::MaybeUninit;
|
||||
use super::SDIO;
|
||||
use libcortex_a9::cache;
|
||||
use libregister::RegisterR;
|
||||
use libregister::{
|
||||
register, register_bit,
|
||||
RegisterR, RegisterW, RegisterRW, VolatileCell,
|
||||
};
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C, align(4))]
|
||||
pub struct Adma2Desc32 {
|
||||
attribute: u16,
|
||||
length: u16,
|
||||
address: u32,
|
||||
attribute: Desc32Attribute,
|
||||
length: VolatileCell<u16>,
|
||||
address: VolatileCell<u32>,
|
||||
}
|
||||
|
||||
// Default::default() cannot be used as it is not a constant function...
|
||||
static mut ADMA2_DESCR32_TABLE: [Adma2Desc32; 32] = [Adma2Desc32 {
|
||||
attribute: 0,
|
||||
length: 0,
|
||||
address: 0,
|
||||
}; 32];
|
||||
|
||||
#[allow(unused)]
|
||||
const DESC_MAX_LENGTH: u32 = 65536;
|
||||
#[allow(unused)]
|
||||
const DESC_TRANS: u16 = 0x2 << 4;
|
||||
#[allow(unused)]
|
||||
const DESC_INT: u16 = 0x1 << 2;
|
||||
#[allow(unused)]
|
||||
const DESC_END: u16 = 0x1 << 1;
|
||||
#[allow(unused)]
|
||||
const DESC_VALID: u16 = 0x1 << 0;
|
||||
|
||||
#[allow(unused)]
|
||||
impl Adma2Desc32 {
|
||||
pub fn set_attribute(&mut self, attribute: u16) {
|
||||
unsafe {
|
||||
core::ptr::write_volatile(&mut self.attribute as *mut u16, attribute);
|
||||
}
|
||||
register!(desc32_attribute, Desc32Attribute, VolatileCell, u16);
|
||||
register_bit!(desc32_attribute, trans, 5);
|
||||
register_bit!(desc32_attribute, int, 2);
|
||||
register_bit!(desc32_attribute, end, 1);
|
||||
register_bit!(desc32_attribute, valid, 0);
|
||||
|
||||
pub struct Adma2DescTable([Adma2Desc32; 32]);
|
||||
|
||||
impl Adma2DescTable {
|
||||
pub fn new() -> Self {
|
||||
let table = MaybeUninit::zeroed();
|
||||
let table = unsafe { table.assume_init() };
|
||||
Adma2DescTable(table)
|
||||
}
|
||||
|
||||
pub fn set_length(&mut self, length: u16) {
|
||||
unsafe {
|
||||
core::ptr::write_volatile(&mut self.length as *mut u16, length);
|
||||
}
|
||||
}
|
||||
/// Initialize the table and setup `adma_system_address`
|
||||
pub fn setup(&mut self, sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) {
|
||||
let descr_table = &mut self.0;
|
||||
let blk_size = sdio
|
||||
.regs
|
||||
.block_size_block_count
|
||||
.read()
|
||||
.transfer_block_size() as u32;
|
||||
|
||||
pub fn set_address(&mut self, address: u32) {
|
||||
unsafe {
|
||||
core::ptr::write_volatile(&mut self.address as *mut u32, address);
|
||||
let total_desc_lines = if blk_size * blk_cnt < DESC_MAX_LENGTH {
|
||||
1
|
||||
} else {
|
||||
blk_size * blk_cnt / DESC_MAX_LENGTH
|
||||
+ if (blk_size * blk_cnt) % DESC_MAX_LENGTH == 0 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
} as usize;
|
||||
|
||||
let ptr = buffer.as_ptr() as u32;
|
||||
for desc_num in 0..total_desc_lines {
|
||||
descr_table[desc_num].address.set(ptr + (desc_num as u32) * DESC_MAX_LENGTH);
|
||||
descr_table[desc_num].attribute.write(
|
||||
Desc32Attribute::zeroed()
|
||||
.trans(true)
|
||||
.valid(true)
|
||||
);
|
||||
// 0 is the max length (65536)
|
||||
descr_table[desc_num].length.set(0);
|
||||
}
|
||||
descr_table[total_desc_lines - 1].attribute.modify(|_, w| w.end(true));
|
||||
descr_table[total_desc_lines - 1].length.set(
|
||||
(blk_cnt * blk_size - ((total_desc_lines as u32) - 1) * DESC_MAX_LENGTH) as u16,
|
||||
);
|
||||
unsafe {
|
||||
sdio.regs
|
||||
.adma_system_address
|
||||
.write(descr_table.as_ptr() as u32);
|
||||
}
|
||||
cache::dcci_slice(descr_table);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_adma2_descr32(sdio: &mut SDIO, blk_cnt: u32, buffer: &[u8]) {
|
||||
let descr_table = unsafe { &mut ADMA2_DESCR32_TABLE };
|
||||
let blk_size = sdio
|
||||
.regs
|
||||
.block_size_block_count
|
||||
.read()
|
||||
.transfer_block_size() as u32;
|
||||
|
||||
let total_desc_lines = if blk_size * blk_cnt < DESC_MAX_LENGTH {
|
||||
1
|
||||
} else {
|
||||
blk_size * blk_cnt / DESC_MAX_LENGTH
|
||||
+ if (blk_size * blk_cnt) % DESC_MAX_LENGTH == 0 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
} as usize;
|
||||
|
||||
let ptr = buffer.as_ptr() as u32;
|
||||
for desc_num in 0..total_desc_lines {
|
||||
descr_table[desc_num].set_address(ptr + (desc_num as u32) * DESC_MAX_LENGTH);
|
||||
descr_table[desc_num].set_attribute(DESC_TRANS | DESC_VALID);
|
||||
// 0 is the max length (65536)
|
||||
descr_table[desc_num].set_length(0);
|
||||
}
|
||||
descr_table[total_desc_lines - 1].set_attribute(DESC_TRANS | DESC_VALID | DESC_END);
|
||||
descr_table[total_desc_lines - 1].set_length(
|
||||
(blk_cnt * blk_size - ((total_desc_lines as u32) - 1) * DESC_MAX_LENGTH) as u16,
|
||||
);
|
||||
unsafe {
|
||||
sdio.regs
|
||||
.adma_system_address
|
||||
.write(descr_table.as_ptr() as u32);
|
||||
}
|
||||
cache::dcci_slice(descr_table);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{adma::setup_adma2_descr32, cmd, CardType, CmdTransferError, SDIO};
|
||||
use super::{adma::Adma2DescTable, cmd, CardType, CmdTransferError, SDIO};
|
||||
use libcortex_a9::cache;
|
||||
use libregister::{RegisterR, RegisterRW, RegisterW};
|
||||
use log::debug;
|
||||
|
@ -25,6 +25,7 @@ enum CardVersion {
|
|||
|
||||
pub struct SdCard {
|
||||
sdio: SDIO,
|
||||
adma2_desc_table: Adma2DescTable,
|
||||
card_version: CardVersion,
|
||||
hcs: bool,
|
||||
card_id: [u32; 4],
|
||||
|
@ -165,6 +166,7 @@ impl SdCard {
|
|||
};
|
||||
let mut _self = SdCard {
|
||||
sdio,
|
||||
adma2_desc_table: Adma2DescTable::new(),
|
||||
card_version: CardVersion::SdVer1,
|
||||
hcs: false,
|
||||
card_id: [0, 0, 0, 0],
|
||||
|
@ -203,7 +205,7 @@ impl SdCard {
|
|||
self.sdio.set_block_size(512)?;
|
||||
}
|
||||
|
||||
setup_adma2_descr32(&mut self.sdio, block_cnt as u32, buffer);
|
||||
self.adma2_desc_table.setup(&mut self.sdio, block_cnt as u32, buffer);
|
||||
// invalidate D cache, required for ZC706, not sure for Cora Z7 10
|
||||
cache::dcci_slice(buffer);
|
||||
|
||||
|
@ -256,7 +258,7 @@ impl SdCard {
|
|||
self.sdio.set_block_size(512)?;
|
||||
}
|
||||
|
||||
setup_adma2_descr32(&mut self.sdio, block_cnt as u32, buffer);
|
||||
self.adma2_desc_table.setup(&mut self.sdio, block_cnt as u32, buffer);
|
||||
// invalidate D cache, required for ZC706, not sure for Cora Z7 10
|
||||
cache::dcci_slice(buffer);
|
||||
|
||||
|
@ -303,7 +305,7 @@ impl SdCard {
|
|||
.block_size_block_count
|
||||
.modify(|_, w| w.transfer_block_size(blk_size));
|
||||
|
||||
setup_adma2_descr32(&mut self.sdio, blk_cnt as u32, buf);
|
||||
self.adma2_desc_table.setup(&mut self.sdio, blk_cnt as u32, buf);
|
||||
cache::dcci_slice(buf);
|
||||
self.sdio.cmd_transfer_with_mode(
|
||||
ACMD51,
|
||||
|
|
Loading…
Reference in New Issue