sdio-adma2-refactor #34

Merged
sb10q merged 5 commits from sdio-adma2-refactor into master 2020-06-11 10:07:19 +08:00
2 changed files with 67 additions and 78 deletions

View File

@ -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);
}

View File

@ -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,