use esp_rom_sys::rom::ets_delay_us;
use crate::{
ethernet::{RmiiClkIn, RmiiClkOut, RmiiClockConfig},
peripherals::{HP_SYS, HP_SYS_CLKRST, LP_AON_CLKRST},
private::Sealed,
};
const CLOCK_STABILIZE_US: u32 = 300;
pub struct ExternalRefClock<P>(P);
impl<P> ExternalRefClock<P> {
pub fn new(pin: P) -> Self {
Self(pin)
}
}
impl<P> Sealed for ExternalRefClock<P> {}
impl<P: RmiiClkIn> RmiiClockConfig for ExternalRefClock<P> {
fn configure(self) {
self.0.configure_iomux();
configure_rmii_input();
}
}
pub struct InternalRefClock<POut, PIn> {
ref_clk_out: POut,
ref_clk_in: PIn,
}
impl<POut, PIn> InternalRefClock<POut, PIn> {
pub fn new(ref_clk_out: POut, ref_clk_in: PIn) -> Self {
Self {
ref_clk_out,
ref_clk_in,
}
}
}
impl<POut, PIn> Sealed for InternalRefClock<POut, PIn> {}
impl<POut: RmiiClkOut, PIn: RmiiClkIn> RmiiClockConfig for InternalRefClock<POut, PIn> {
fn configure(self) {
self.ref_clk_out.configure_iomux();
self.ref_clk_in.configure_iomux();
enable_mpll_50m_output();
configure_rmii_input();
HP_SYS_CLKRST::regs()
.peri_clk_ctrl00()
.modify(|_, w| w.pad_emac_ref_clk_en().set_bit());
}
}
pub(crate) struct MiiClock;
impl MiiClock {
pub(super) fn configure(&self) {
configure_mii();
}
}
fn configure_rmii_input() {
HP_SYS::regs()
.gmac_ctrl0()
.modify(|_, w| unsafe { w.phy_intf_sel().bits(4) });
HP_SYS_CLKRST::regs()
.peri_clk_ctrl00()
.modify(|_, w| unsafe {
w.pad_emac_ref_clk_en().clear_bit();
w.emac_rmii_clk_src_sel().bits(0);
w.emac_rmii_clk_en().set_bit();
w.emac_rx_clk_src_sel().clear_bit(); w.emac_rx_clk_en().set_bit()
});
HP_SYS_CLKRST::regs()
.peri_clk_ctrl01()
.modify(|_, w| unsafe {
w.emac_tx_clk_src_sel().clear_bit(); w.emac_tx_clk_en().set_bit();
w.emac_rx_clk_div_num().bits(1); w.emac_tx_clk_div_num().bits(1)
});
LP_AON_CLKRST::regs()
.lp_aonclkrst_hp_clk_ctrl()
.modify(|_, w| {
w.lp_aonclkrst_hp_pad_emac_tx_clk_en().clear_bit();
w.lp_aonclkrst_hp_pad_emac_rx_clk_en().clear_bit();
w.lp_aonclkrst_hp_pad_emac_txrx_clk_en().set_bit()
});
deassert_reset();
clock_stabilize();
}
fn enable_mpll_50m_output() {
LP_AON_CLKRST::regs()
.lp_aonclkrst_hp_clk_ctrl()
.modify(|_, w| w.lp_aonclkrst_hp_mpll_500m_clk_en().set_bit());
HP_SYS_CLKRST::regs()
.ref_clk_ctrl0()
.modify(|_, w| unsafe { w.ref_50m_clk_div_num().bits(9) });
HP_SYS_CLKRST::regs()
.ref_clk_ctrl1()
.modify(|_, w| w.ref_50m_clk_en().set_bit());
}
fn configure_mii() {
HP_SYS::regs()
.gmac_ctrl0()
.modify(|_, w| unsafe { w.phy_intf_sel().bits(0) });
HP_SYS_CLKRST::regs()
.peri_clk_ctrl00()
.modify(|_, w| unsafe {
w.pad_emac_ref_clk_en().clear_bit();
w.emac_rmii_clk_en().clear_bit();
w.emac_rmii_clk_src_sel().bits(0);
w.emac_rx_clk_src_sel().set_bit(); w.emac_rx_clk_en().set_bit()
});
HP_SYS_CLKRST::regs()
.peri_clk_ctrl01()
.modify(|_, w| unsafe {
w.emac_tx_clk_src_sel().set_bit(); w.emac_tx_clk_en().set_bit();
w.emac_rx_clk_div_num().bits(0); w.emac_tx_clk_div_num().bits(0)
});
LP_AON_CLKRST::regs()
.lp_aonclkrst_hp_clk_ctrl()
.modify(|_, w| {
w.lp_aonclkrst_hp_pad_emac_tx_clk_en().set_bit();
w.lp_aonclkrst_hp_pad_emac_rx_clk_en().set_bit()
});
deassert_reset();
clock_stabilize();
}
fn deassert_reset() {
LP_AON_CLKRST::regs()
.lp_aonclkrst_hp_sdmmc_emac_rst_ctrl()
.modify(|_, w| {
w.lp_aonclkrst_rst_en_emac().set_bit();
w.lp_aonclkrst_force_norst_emac().clear_bit()
});
LP_AON_CLKRST::regs()
.lp_aonclkrst_hp_sdmmc_emac_rst_ctrl()
.modify(|_, w| w.lp_aonclkrst_rst_en_emac().clear_bit());
}
fn clock_stabilize() {
ets_delay_us(CLOCK_STABILIZE_US);
}