use crate::target::{dport, DPORT};
use xtensa_lx::mutex::mutex_trait::Mutex;
use xtensa_lx::mutex::CriticalSectionSpinLockMutex;
pub struct ClockControl {}
impl ClockControl {
pub(crate) fn cpu_per_conf(&self) -> &dport::CPU_PER_CONF {
unsafe { &(*DPORT::ptr()).cpu_per_conf }
}
pub(crate) fn appcpu_ctrl_a(&self) -> &dport::APPCPU_CTRL_A {
unsafe { &(*DPORT::ptr()).appcpu_ctrl_a }
}
pub(crate) fn appcpu_ctrl_b(&self) -> &dport::APPCPU_CTRL_B {
unsafe { &(*DPORT::ptr()).appcpu_ctrl_b }
}
pub(crate) fn appcpu_ctrl_c(&self) -> &dport::APPCPU_CTRL_C {
unsafe { &(*DPORT::ptr()).appcpu_ctrl_c }
}
pub(crate) fn appcpu_ctrl_d(&self) -> &dport::APPCPU_CTRL_D {
unsafe { &(*DPORT::ptr()).appcpu_ctrl_d }
}
pub(crate) fn app_cache_ctrl(&self) -> &dport::APP_CACHE_CTRL {
unsafe { &(*DPORT::ptr()).app_cache_ctrl }
}
pub(crate) fn pro_cache_ctrl(&self) -> &dport::PRO_CACHE_CTRL {
unsafe { &(*DPORT::ptr()).pro_cache_ctrl }
}
}
pub trait Split {
fn split(self) -> (DPORT, ClockControl);
}
impl Split for DPORT {
fn split(self) -> (DPORT, ClockControl) {
(self, ClockControl {})
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Peripheral {
TIMERS = 0,
SPI0_SPI1 = 1,
UART0 = 2,
WDG = 3,
I2S0 = 4,
UART1 = 5,
SPI2 = 6,
I2C0 = 7,
UHCI0 = 8,
RMT = 9,
PCNT = 10,
LEDC = 11,
UHCI1 = 12,
TIMERGROUP0 = 13,
EFUSE = 14,
TIMERGROUP1 = 15,
SPI3 = 16,
PWM0 = 17,
I2C1 = 18,
CAN = 19,
PWM1 = 20,
I2S1 = 21,
SPI_DMA = 22,
UART2 = 23,
UART_MEM = 24,
PWM2 = 25,
PWM3 = 26,
AES = 32 + 0,
SHA = 32 + 1,
RSA = 32 + 2,
SECUREBOOT = 32 + 3,
SIGNATURE = 32 + 4,
SDIO_SLAVE = 64 + 4,
SDIO_HOST = 64 + 13,
EMAC = 64 + 14,
RNG = 64 + 15,
WIFI = 96,
BT = 97,
WIFI_BT_COMMON = 98,
BT_LC = 99,
BT_BASEBAND = 100,
}
static PERIPHERAL_MUTEX: CriticalSectionSpinLockMutex<()> = CriticalSectionSpinLockMutex::new(());
const WIFI_CLK_MASK: u32 = 0x406; const BT_CLK_MASK: u32 = 0x61; const WIFI_BT_CLK_MASK: u32 = 0x3c9; const BT_LC_CLK_MASK: u32 = 0x3000; const BT_BASEBAND_CLK_MASK: u32 = 0x0800;
const EMAC_RST_MASK: u32 = 0x80; const SDIO_HOST_RST_MASK: u32 = 0x40; const SDIO_SLAVE_RST_MASK: u32 = 0x20;
const UART_MASK: u32 = 1 << (Peripheral::UART0 as u32)
| 1 << (Peripheral::UART1 as u32)
| 1 << (Peripheral::UART2 as u32);
pub fn enable_peripheral(peripheral: Peripheral) {
let bitnr = peripheral as u32;
let dport = unsafe { &(*DPORT::ptr()) };
(&PERIPHERAL_MUTEX).lock(|_| unsafe {
if bitnr < 32 {
let mut mask = 1 << bitnr;
match peripheral {
Peripheral::UART0 | Peripheral::UART1 | Peripheral::UART2 => {
mask |= 1 << (Peripheral::UART_MEM as u32)
}
_ => {}
}
dport.perip_clk_en.modify(|r, w| w.bits(r.bits() | mask));
dport.perip_rst_en.modify(|r, w| w.bits(r.bits() & !mask));
} else if bitnr < 64 {
let mut mask = 1 << (bitnr - 32);
match peripheral {
Peripheral::AES => {
mask |= 1 << (Peripheral::SIGNATURE as u32 - 32)
| 1 << (Peripheral::SECUREBOOT as u32 - 32);
}
Peripheral::SHA => {
mask |= 1 << (Peripheral::SECUREBOOT as u32 - 32);
}
Peripheral::RSA => {
mask |= 1 << (Peripheral::SIGNATURE as u32 - 32);
}
_ => {}
}
dport.peri_clk_en.modify(|r, w| w.bits(r.bits() | mask));
dport.peri_rst_en.modify(|r, w| w.bits(r.bits() & !mask));
} else if bitnr < 96 {
let mask = 1 << (bitnr - 64);
dport.wifi_clk_en.modify(|r, w| w.bits(r.bits() | mask));
let rst_mask = match peripheral {
Peripheral::EMAC => EMAC_RST_MASK,
Peripheral::SDIO_HOST => SDIO_HOST_RST_MASK,
Peripheral::SDIO_SLAVE => SDIO_SLAVE_RST_MASK,
_ => 0,
};
dport
.core_rst_en
.modify(|r, w| w.bits(r.bits() & !rst_mask));
} else {
let mask = match peripheral {
Peripheral::WIFI => WIFI_CLK_MASK,
Peripheral::BT => BT_CLK_MASK,
Peripheral::WIFI_BT_COMMON => WIFI_BT_CLK_MASK,
Peripheral::BT_BASEBAND => BT_BASEBAND_CLK_MASK,
Peripheral::BT_LC => BT_LC_CLK_MASK,
_ => 0,
};
dport.wifi_clk_en.modify(|r, w| w.bits(r.bits() | mask));
}
});
}
pub fn disable_peripheral(peripheral: Peripheral) {
let bitnr = peripheral as u32;
let dport = unsafe { &(*DPORT::ptr()) };
(&PERIPHERAL_MUTEX).lock(|_| unsafe {
if bitnr < 32 {
let mut mask = 1 << bitnr;
dport.perip_clk_en.modify(|r, w| {
if r.bits() & !mask & UART_MASK == 0 {
mask &= !(1 << (Peripheral::UART_MEM as u32));
}
w.bits(r.bits() & !mask)
});
dport.perip_rst_en.modify(|r, w| w.bits(r.bits() | mask));
} else if bitnr < 64 {
let mask = 1 << (bitnr - 32);
dport.peri_clk_en.modify(|r, w| w.bits(r.bits() & !mask));
dport.peri_rst_en.modify(|r, w| w.bits(r.bits() | mask));
} else if bitnr < 96 {
let mask = 1 << (bitnr - 64);
dport.wifi_clk_en.modify(|r, w| w.bits(r.bits() & !mask));
let rst_mask = match peripheral {
Peripheral::EMAC => EMAC_RST_MASK,
Peripheral::SDIO_HOST => SDIO_HOST_RST_MASK,
Peripheral::SDIO_SLAVE => SDIO_SLAVE_RST_MASK,
_ => 0,
};
dport.core_rst_en.modify(|r, w| w.bits(r.bits() | rst_mask));
} else {
let mask = match peripheral {
Peripheral::WIFI => WIFI_CLK_MASK,
Peripheral::BT => BT_CLK_MASK,
Peripheral::WIFI_BT_COMMON => WIFI_BT_CLK_MASK,
Peripheral::BT_BASEBAND => BT_BASEBAND_CLK_MASK,
Peripheral::BT_LC => BT_LC_CLK_MASK,
_ => 0,
};
dport.wifi_clk_en.modify(|r, w| w.bits(r.bits() & !mask));
}
});
}
pub fn reset_peripheral(peripheral: Peripheral) {
let bitnr = peripheral as u32;
let dport = unsafe { &(*DPORT::ptr()) };
(&PERIPHERAL_MUTEX).lock(|_| unsafe {
if bitnr < 32 {
let mask = 1 << bitnr;
dport.perip_rst_en.modify(|r, w| w.bits(r.bits() | mask));
dport.perip_rst_en.modify(|r, w| w.bits(r.bits() & !mask));
} else if bitnr < 64 {
let mask = 1 << (bitnr - 32);
dport.peri_rst_en.modify(|r, w| w.bits(r.bits() | mask));
dport.peri_rst_en.modify(|r, w| w.bits(r.bits() & !mask));
} else if bitnr < 96 {
let rst_mask = match peripheral {
Peripheral::EMAC => EMAC_RST_MASK,
Peripheral::SDIO_HOST => SDIO_HOST_RST_MASK,
Peripheral::SDIO_SLAVE => SDIO_SLAVE_RST_MASK,
_ => 0,
};
dport.core_rst_en.modify(|r, w| w.bits(r.bits() | rst_mask));
dport
.core_rst_en
.modify(|r, w| w.bits(r.bits() & !rst_mask));
} else {
}
});
}