forked from M-Labs/zynq-rs
zynq::flash: start implementing Manual mode
This commit is contained in:
parent
dd3ad3be67
commit
7107244a6e
@ -1,15 +1,17 @@
|
|||||||
//! Quad-SPI Flash Controller
|
//! Quad-SPI Flash Controller
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use crate::regs::{RegisterW, RegisterRW};
|
use crate::regs::{RegisterR, RegisterW, RegisterRW};
|
||||||
use super::slcr;
|
use super::slcr;
|
||||||
use super::clocks::CpuClocks;
|
use super::clocks::CpuClocks;
|
||||||
|
|
||||||
pub mod regs;
|
pub mod regs;
|
||||||
|
|
||||||
const FLASH_BAUD_RATE: u32 = 50_000_000;
|
const FLASH_BAUD_RATE: u32 = 50_000_000;
|
||||||
|
const SINGLE_CAPACITY: u32 = 16 * 1024 * 1024;
|
||||||
|
|
||||||
pub struct LinearAddressing;
|
pub struct LinearAddressing;
|
||||||
|
pub struct Manual;
|
||||||
|
|
||||||
/// Flash Interface Driver
|
/// Flash Interface Driver
|
||||||
///
|
///
|
||||||
@ -196,6 +198,29 @@ impl Flash<()> {
|
|||||||
|
|
||||||
self.transition()
|
self.transition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn manual_mode(self, chip_index: usize) -> Flash<Manual> {
|
||||||
|
self.regs.config.modify(|_, w| w
|
||||||
|
.man_start_en(true)
|
||||||
|
.manual_cs(true)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.regs.lqspi_cfg.write(regs::LqspiCfg::zeroed()
|
||||||
|
.mode_bits(0xFF)
|
||||||
|
.dummy_byte(0x2)
|
||||||
|
.mode_en(true)
|
||||||
|
// 2 devices
|
||||||
|
.two_mem(true)
|
||||||
|
.u_page(chip_index != 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
self.regs.config.modify(|_, w| w
|
||||||
|
.pcs(false)
|
||||||
|
);
|
||||||
|
self.regs.enable.modify(|_, w| w.spi_en(true));
|
||||||
|
|
||||||
|
self.transition()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flash<LinearAddressing> {
|
impl Flash<LinearAddressing> {
|
||||||
@ -213,6 +238,53 @@ impl Flash<LinearAddressing> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
32 * 1024 * 1024
|
2 * (SINGLE_CAPACITY as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Flash<Manual> {
|
||||||
|
pub fn stop(self) -> Flash<()> {
|
||||||
|
self.regs.enable.modify(|_, w| w.spi_en(false));
|
||||||
|
// De-assert chip select.
|
||||||
|
self.regs.config.modify(|_, w| w.pcs(true));
|
||||||
|
|
||||||
|
self.transition()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self, offset: u32, dest: &mut [u8]) {
|
||||||
|
self.regs.config.modify(|_, w| w.man_start_com(true));
|
||||||
|
|
||||||
|
// Quad I/O Read
|
||||||
|
let instr = 0xEB;
|
||||||
|
unsafe {
|
||||||
|
self.regs.txd0.write(
|
||||||
|
instr |
|
||||||
|
(offset << 8)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
while self.regs.intr_status.read().tx_fifo_not_full() {
|
||||||
|
unsafe {
|
||||||
|
self.regs.txd0.write(0);
|
||||||
|
}
|
||||||
|
let rx = self.regs.rx_data.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
for d in dest {
|
||||||
|
while !self.regs.intr_status.read().rx_fifo_not_empty() {}
|
||||||
|
|
||||||
|
// TODO: drops data?
|
||||||
|
let rx = self.regs.rx_data.read();
|
||||||
|
*d = rx as u8;
|
||||||
|
|
||||||
|
// Output dummy byte to generate clock for further RX
|
||||||
|
unsafe {
|
||||||
|
self.regs.txd1.write(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_tx_not_full(&self) {
|
||||||
|
while self.regs.intr_status.read().tx_fifo_full() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use crate::{register, register_bit, register_bits};
|
|||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct RegisterBlock {
|
pub struct RegisterBlock {
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub intr_status: RW<u32>,
|
pub intr_status: IntrStatus,
|
||||||
pub intr_en: RW<u32>,
|
pub intr_en: RW<u32>,
|
||||||
pub intr_dis: RW<u32>,
|
pub intr_dis: RW<u32>,
|
||||||
pub intr_mask: RO<u32>,
|
pub intr_mask: RO<u32>,
|
||||||
@ -15,7 +15,7 @@ pub struct RegisterBlock {
|
|||||||
pub rx_data: RO<u32>,
|
pub rx_data: RO<u32>,
|
||||||
pub slave_idle_count: RW<u32>,
|
pub slave_idle_count: RW<u32>,
|
||||||
pub tx_thres: RW<u32>,
|
pub tx_thres: RW<u32>,
|
||||||
pub rx_thes: RW<u32>,
|
pub rx_thres: RW<u32>,
|
||||||
pub gpio: RW<u32>,
|
pub gpio: RW<u32>,
|
||||||
pub _unused1: RO<u32>,
|
pub _unused1: RO<u32>,
|
||||||
pub lpbk_dly_adj: RW<u32>,
|
pub lpbk_dly_adj: RW<u32>,
|
||||||
@ -77,6 +77,14 @@ register_bit!(config,
|
|||||||
/// false: legacy SPI mode, true: Flash memory interface mode
|
/// false: legacy SPI mode, true: Flash memory interface mode
|
||||||
leg_flsh, 31);
|
leg_flsh, 31);
|
||||||
|
|
||||||
|
register!(intr_status, IntrStatus, RW, u32);
|
||||||
|
register_bit!(intr_status, rx_overflow, 0);
|
||||||
|
register_bit!(intr_status, tx_fifo_not_full, 2);
|
||||||
|
register_bit!(intr_status, tx_fifo_full, 3);
|
||||||
|
register_bit!(intr_status, rx_fifo_not_empty, 4);
|
||||||
|
register_bit!(intr_status, rx_fifo_full, 5);
|
||||||
|
register_bit!(intr_status, tx_fifo_underflow, 6);
|
||||||
|
|
||||||
register!(enable, Enable, RW, u32);
|
register!(enable, Enable, RW, u32);
|
||||||
register_bit!(enable, spi_en, 0);
|
register_bit!(enable, spi_en, 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user