From c15b54f92b3d4e125ae47a0dce7abe4b2bc9e054 Mon Sep 17 00:00:00 2001 From: jmatyas Date: Thu, 27 Jul 2023 13:40:55 +0200 Subject: [PATCH] kasli-soc: add support for PHY_RST GPIO --- libboard_zynq/src/eth/mod.rs | 74 +++++++++++++++++++++++++++++++++++ libboard_zynq/src/eth/regs.rs | 43 ++++++++++++++++++++ 2 files changed, 117 insertions(+) diff --git a/libboard_zynq/src/eth/mod.rs b/libboard_zynq/src/eth/mod.rs index fa877f5..8349ba1 100644 --- a/libboard_zynq/src/eth/mod.rs +++ b/libboard_zynq/src/eth/mod.rs @@ -13,6 +13,9 @@ mod regs; pub mod rx; pub mod tx; +use super::time::Milliseconds; +use embedded_hal::timer::CountDown; + /// Size of all the buffers pub const MTU: usize = 1536; /// Maximum MDC clock @@ -300,11 +303,18 @@ impl Eth { fn gem_common(macaddr: [u8; 6]) -> Self { GEM::setup_clock(TX_1000); + #[cfg(feature="target_kasli_soc")] + { + let mut eth_reset_pin = PhyRst::rst_pin(); + eth_reset_pin.reset(); + } + let mut inner = EthInner { gem: PhantomData, link: None, }; inner.init(); + inner.configure(macaddr); let phy = Phy::find(&mut inner).expect("phy"); @@ -482,6 +492,70 @@ impl<'a, GEM: Gem> smoltcp::phy::Device<'a> for &mut Eth, +} + +impl PhyRst { + pub fn rst_pin() -> Self { + slcr::RegisterBlock::unlocked(|slcr| { + // Hardware Reset for PHY + slcr.mio_pin_47.write( + slcr::MioPin47::zeroed() + .l3_sel(0b000) + .io_type(slcr::IoBufferType::Lvcmos18) + .pullup(true) + .disable_rcvr(true) + ); + slcr.gpio_rst_ctrl.reset_gpio(); + }); + Self::eth_reset_common(0xFFFF - 0x8000) + } + + fn delay_ms(&mut self, ms: u64) { + self.count_down.start(Milliseconds(ms)); + nb::block!(self.count_down.wait()).unwrap(); + } + + fn eth_reset_common(gpio_output_mask: u16) -> Self { + let self_ = Self { + regs: regs::GpioRegisterBlock::regs(), + count_down: unsafe { super::timer::GlobalTimer::get() }.countdown(), + }; + + // Setup GPIO output mask + self_.regs.gpio_output_mask.modify(|_, w| { + w.mask(gpio_output_mask) + }); + + self_.regs.gpio_direction.modify(|_, w| { + w.phy_rst(true) + }); + + self_ + } + + fn oe(&mut self, oe: bool) { + self.regs.gpio_output_enable.modify(|_, w| { + w.phy_rst(oe) + }) + } + + fn toggle(&mut self, o: bool) { + self.regs.gpio_output_mask.modify(|_, w| { + w.phy_rst(o) + }) + } + + pub fn reset(&mut self) { + self.toggle(false); // drive phy_rst (active LOW) pin low + self.oe(true); // enable pin's output + self.delay_ms(10); + self.toggle(true); + } +} + struct EthInner { gem: PhantomData, diff --git a/libboard_zynq/src/eth/regs.rs b/libboard_zynq/src/eth/regs.rs index e0821b9..9c37eed 100644 --- a/libboard_zynq/src/eth/regs.rs +++ b/libboard_zynq/src/eth/regs.rs @@ -110,6 +110,49 @@ pub struct RegisterBlock { pub design_cfg5: RO, } +pub struct GpioRegisterBlock { + pub gpio_output_mask: &'static mut OutputMask, + pub gpio_direction: &'static mut Direction, + pub gpio_output_enable: &'static mut OutputEnable, +} + +impl GpioRegisterBlock { + pub fn regs() -> Self { + Self { + gpio_output_mask: OutputMask::new(), + gpio_direction: Direction::new(), + gpio_output_enable: OutputEnable::new(), + } + } +} + +register!(gpio_output_mask, + /// MASK_DATA_1_SW: + /// Maskable output data for MIO[47:32] + OutputMask, RW, u32); +register_at!(OutputMask, 0xE000A008, new); +register_bit!(gpio_output_mask, + /// Output for PHY_RST (MIO[47]) + phy_rst, 15); +register_bits!(gpio_output_mask, + mask, u16, 16, 31); +register!(gpio_direction, + /// DIRM_1: + /// Direction mode for MIO[53:32]; 0/1 = in/out + Direction, RW, u32); +register_at!(Direction, 0xE000A244, new); +register_bit!(gpio_direction, + /// Direction for PHY_RST + phy_rst, 15); +register!(gpio_output_enable, + /// OEN_1: + /// Output enable for MIO[53:32] + OutputEnable, RW, u32); +register_at!(OutputEnable, 0xE000A248, new); +register_bit!(gpio_output_enable, + /// Output enable for PHY_RST + phy_rst, 15); + register_at!(RegisterBlock, 0xE000B000, gem0); register_at!(RegisterBlock, 0xE000C000, gem1);