From 7107244a6ec56a81205e2cc0101d5330931144e2 Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 30 Nov 2019 02:48:39 +0100 Subject: [PATCH] zynq::flash: start implementing Manual mode --- src/zynq/flash/mod.rs | 76 ++++++++++++++++++++++++++++++++++++++++-- src/zynq/flash/regs.rs | 12 +++++-- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/zynq/flash/mod.rs b/src/zynq/flash/mod.rs index 2f886a4f..bc204807 100644 --- a/src/zynq/flash/mod.rs +++ b/src/zynq/flash/mod.rs @@ -1,15 +1,17 @@ //! Quad-SPI Flash Controller use core::marker::PhantomData; -use crate::regs::{RegisterW, RegisterRW}; +use crate::regs::{RegisterR, RegisterW, RegisterRW}; use super::slcr; use super::clocks::CpuClocks; pub mod regs; const FLASH_BAUD_RATE: u32 = 50_000_000; +const SINGLE_CAPACITY: u32 = 16 * 1024 * 1024; pub struct LinearAddressing; +pub struct Manual; /// Flash Interface Driver /// @@ -196,6 +198,29 @@ impl Flash<()> { self.transition() } + + pub fn manual_mode(self, chip_index: usize) -> Flash { + 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 { @@ -213,6 +238,53 @@ impl Flash { } pub fn size(&self) -> usize { - 32 * 1024 * 1024 + 2 * (SINGLE_CAPACITY as usize) + } +} + +impl Flash { + 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() {} } } diff --git a/src/zynq/flash/regs.rs b/src/zynq/flash/regs.rs index 0ea2cfde..197364f0 100644 --- a/src/zynq/flash/regs.rs +++ b/src/zynq/flash/regs.rs @@ -5,7 +5,7 @@ use crate::{register, register_bit, register_bits}; #[repr(C)] pub struct RegisterBlock { pub config: Config, - pub intr_status: RW, + pub intr_status: IntrStatus, pub intr_en: RW, pub intr_dis: RW, pub intr_mask: RO, @@ -15,7 +15,7 @@ pub struct RegisterBlock { pub rx_data: RO, pub slave_idle_count: RW, pub tx_thres: RW, - pub rx_thes: RW, + pub rx_thres: RW, pub gpio: RW, pub _unused1: RO, pub lpbk_dly_adj: RW, @@ -77,6 +77,14 @@ register_bit!(config, /// false: legacy SPI mode, true: Flash memory interface mode 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_bit!(enable, spi_en, 0);