Firmware: satman WRPLL

satman: enable WRPLL interrupt
satman: add WRPLL interrupt handler
satman: add main & helper si549 setup
satman: add WRPLL select_recovered_clock
This commit is contained in:
morgan 2024-05-24 11:16:15 +08:00 committed by Sébastien Bourdeauducq
parent 0ac0e08170
commit a10dd0520c
1 changed files with 70 additions and 15 deletions

View File

@ -17,6 +17,8 @@ use core::convert::TryFrom;
use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp};
#[cfg(has_si5324)] #[cfg(has_si5324)]
use board_artiq::si5324; use board_artiq::si5324;
#[cfg(has_si549)]
use board_artiq::si549;
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
use board_misoc::irq; use board_misoc::irq;
use board_artiq::{spi, drtioaux, drtio_routing}; use board_artiq::{spi, drtioaux, drtio_routing};
@ -597,6 +599,36 @@ const SI5324_SETTINGS: si5324::FrequencySettings
crystal_as_ckin2: true crystal_as_ckin2: true
}; };
#[cfg(all(has_si549, rtio_frequency = "125.0"))]
const SI549_SETTINGS: si549::FrequencySetting = si549::FrequencySetting {
main: si549::DividerConfig {
hsdiv: 0x058,
lsdiv: 0,
fbdiv: 0x04815791F25,
},
helper: si549::DividerConfig {
// 125MHz*32767/32768
hsdiv: 0x058,
lsdiv: 0,
fbdiv: 0x04814E8F442,
},
};
#[cfg(all(has_si549, rtio_frequency = "100.0"))]
const SI549_SETTINGS: si549::FrequencySetting = si549::FrequencySetting {
main: si549::DividerConfig {
hsdiv: 0x06C,
lsdiv: 0,
fbdiv: 0x046C5F49797,
},
helper: si549::DividerConfig {
// 100MHz*32767/32768
hsdiv: 0x06C,
lsdiv: 0,
fbdiv: 0x046C5670BBD,
},
};
#[cfg(not(soc_platform = "efc"))] #[cfg(not(soc_platform = "efc"))]
fn sysclk_setup() { fn sysclk_setup() {
let switched = unsafe { let switched = unsafe {
@ -609,6 +641,9 @@ fn sysclk_setup() {
else { else {
#[cfg(has_si5324)] #[cfg(has_si5324)]
si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324"); si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324");
#[cfg(has_si549)]
si549::main_setup(&SI549_SETTINGS).expect("cannot initialize main Si549");
info!("Switching sys clock, rebooting..."); info!("Switching sys clock, rebooting...");
// delay for clean UART log, wait until UART FIFO is empty // delay for clean UART log, wait until UART FIFO is empty
clock::spin_us(3000); clock::spin_us(3000);
@ -634,6 +669,8 @@ pub extern fn main() -> i32 {
} }
#[cfg(soc_platform = "kasli")] #[cfg(soc_platform = "kasli")]
irq::enable_interrupts(); irq::enable_interrupts();
#[cfg(has_wrpll)]
irq::enable(csr::WRPLL_INTERRUPT);
clock::init(); clock::init();
uart_logger::ConsoleLogger::register(); uart_logger::ConsoleLogger::register();
@ -669,6 +706,9 @@ pub extern fn main() -> i32 {
#[cfg(not(soc_platform = "efc"))] #[cfg(not(soc_platform = "efc"))]
sysclk_setup(); sysclk_setup();
#[cfg(has_si549)]
si549::helper_setup(&SI549_SETTINGS).expect("cannot initialize helper Si549");
#[cfg(soc_platform = "efc")] #[cfg(soc_platform = "efc")]
let mut io_expander; let mut io_expander;
#[cfg(soc_platform = "efc")] #[cfg(soc_platform = "efc")]
@ -758,6 +798,9 @@ pub extern fn main() -> i32 {
si5324::siphaser::calibrate_skew().expect("failed to calibrate skew"); si5324::siphaser::calibrate_skew().expect("failed to calibrate skew");
} }
#[cfg(has_wrpll)]
si549::wrpll::select_recovered_clock(true);
// various managers created here, so when link is dropped, DMA traces, // various managers created here, so when link is dropped, DMA traces,
// analyzer logs, kernels are cleared and/or stopped for a clean slate // analyzer logs, kernels are cleared and/or stopped for a clean slate
// on subsequent connections, without a manual intervention. // on subsequent connections, without a manual intervention.
@ -825,6 +868,8 @@ pub extern fn main() -> i32 {
info!("uplink is down, switching to local oscillator clock"); info!("uplink is down, switching to local oscillator clock");
#[cfg(has_si5324)] #[cfg(has_si5324)]
si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks"); si5324::siphaser::select_recovered_clock(false).expect("failed to switch clocks");
#[cfg(has_wrpll)]
si549::wrpll::select_recovered_clock(false);
} }
} }
@ -864,23 +909,33 @@ fn enable_error_led() {
pub extern fn exception(_regs: *const u32) { pub extern fn exception(_regs: *const u32) {
let pc = mepc::read(); let pc = mepc::read();
let cause = mcause::read().cause(); let cause = mcause::read().cause();
match cause {
fn hexdump(addr: u32) { mcause::Trap::Interrupt(_source) => {
let addr = (addr - addr % 4) as *const u32; #[cfg(has_wrpll)]
let mut ptr = addr; if irq::is_pending(csr::WRPLL_INTERRUPT) {
println!("@ {:08p}", ptr); si549::wrpll::interrupt_handler();
for _ in 0..4 { }
print!("+{:04x}: ", ptr as usize - addr as usize); },
print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1);
print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); mcause::Trap::Exception(e) => {
print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); fn hexdump(addr: u32) {
print!("{:08x}\n", unsafe { *ptr }); ptr = ptr.wrapping_offset(1); let addr = (addr - addr % 4) as *const u32;
let mut ptr = addr;
println!("@ {:08p}", ptr);
for _ in 0..4 {
print!("+{:04x}: ", ptr as usize - addr as usize);
print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1);
print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1);
print!("{:08x} ", unsafe { *ptr }); ptr = ptr.wrapping_offset(1);
print!("{:08x}\n", unsafe { *ptr }); ptr = ptr.wrapping_offset(1);
}
}
hexdump(u32::try_from(pc).unwrap());
let mtval = mtval::read();
panic!("exception {:?} at PC 0x{:x}, trap value 0x{:x}", e, u32::try_from(pc).unwrap(), mtval)
} }
} }
hexdump(u32::try_from(pc).unwrap());
let mtval = mtval::read();
panic!("exception {:?} at PC 0x{:x}, trap value 0x{:x}", cause, u32::try_from(pc).unwrap(), mtval)
} }
#[no_mangle] #[no_mangle]