1
0
Fork 0

phys fw: add reset

phys fw: change linerate to all channels

phys fw: refactor and update csr

phys fw: reorder reset csr

phys fw: set all gtx channel to be same linerate

phys fw: clenaup

phys fw: add csr control CH len
This commit is contained in:
morgan 2024-10-17 12:02:24 +08:00
parent 675c535812
commit 392f38ed7e
1 changed files with 88 additions and 79 deletions

View File

@ -4,6 +4,8 @@ use log::info;
use crate::pl::{csr, csr::CXP}; use crate::pl::{csr, csr::CXP};
const CHANNEL_LEN: usize = csr::CXP_LEN;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub enum CXP_SPEED { pub enum CXP_SPEED {
@ -19,36 +21,35 @@ pub enum CXP_SPEED {
pub fn setup(timer: &mut GlobalTimer) { pub fn setup(timer: &mut GlobalTimer) {
down_conn::setup(timer); down_conn::setup(timer);
up_conn::setup(); up_conn::setup();
change_linerate(CXP_SPEED::CXP_1);
} }
pub fn change_linerate(channel: usize, timer: &mut GlobalTimer, speed: CXP_SPEED) { pub fn change_linerate(speed: CXP_SPEED) {
info!("Changing channel {}'s datarate to {:?}", channel, speed); info!("Changing all channels datarate to {:?}", speed);
down_conn::change_linerate(channel, timer, speed); down_conn::change_linerate(speed);
up_conn::change_linerate(channel, speed); up_conn::change_linerate(speed);
} }
mod up_conn { mod up_conn {
use super::*; use super::*;
pub fn setup() { pub fn setup() {
// TODO: do a for loop for channel?
let channel: usize = 0;
unsafe { unsafe {
change_linerate(channel, CXP_SPEED::CXP_1); csr::cxp_phys::upconn_tx_enable_write(1);
(CXP[channel].upconn_tx_enable_write)(1);
} }
} }
pub fn change_linerate(channel: usize, speed: CXP_SPEED) { pub fn change_linerate(speed: CXP_SPEED) {
unsafe { unsafe {
(CXP[channel].upconn_clk_reset_write)(1);
match speed { match speed {
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => { CXP_SPEED::CXP_1 | CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 | CXP_SPEED::CXP_5 | CXP_SPEED::CXP_6 => {
(CXP[channel].upconn_bitrate2x_enable_write)(1); csr::cxp_phys::upconn_bitrate2x_enable_write(0);
}
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => {
csr::cxp_phys::upconn_bitrate2x_enable_write(1);
} }
_ => {}
}; };
(CXP[channel].upconn_clk_reset_write)(0); csr::cxp_phys::upconn_clk_reset_write(1);
} }
} }
} }
@ -57,11 +58,11 @@ mod down_conn {
use super::*; use super::*;
pub fn setup(timer: &mut GlobalTimer) { pub fn setup(timer: &mut GlobalTimer) {
// TODO: do a for loop for channel?
let channel: usize = 0;
unsafe { unsafe {
info!("turning on pmc loopback mode..."); info!("turning on pmc loopback mode...");
for channel in 0..CHANNEL_LEN {
(CXP[channel].downconn_loopback_mode_write)(0b010); // Near-End PMA Loopback (CXP[channel].downconn_loopback_mode_write)(0b010); // Near-End PMA Loopback
}
// QPLL setup // QPLL setup
csr::cxp_phys::downconn_qpll_reset_write(1); csr::cxp_phys::downconn_qpll_reset_write(1);
@ -69,43 +70,46 @@ mod down_conn {
while csr::cxp_phys::downconn_qpll_locked_read() != 1 {} while csr::cxp_phys::downconn_qpll_locked_read() != 1 {}
info!("QPLL locked"); info!("QPLL locked");
for channel in 0..CHANNEL_LEN {
// tx/rx setup // tx/rx setup
(CXP[channel].downconn_tx_start_init_write)(1); (CXP[channel].downconn_tx_start_init_write)(1);
(CXP[channel].downconn_rx_start_init_write)(1); (CXP[channel].downconn_rx_start_init_write)(1);
}
// DEBUG: printout
info!("waiting for tx & rx setup..."); info!("waiting for tx & rx setup...");
timer.delay_us(50_000); timer.delay_us(50_000);
for channel in 0..CHANNEL_LEN {
info!( info!(
"tx_phaligndone = {} | rx_phaligndone = {}", "tx_phaligndone = {} | rx_phaligndone = {}",
(CXP[channel].downconn_txinit_phaligndone_read)(), (CXP[channel].downconn_txinit_phaligndone_read)(),
(CXP[channel].downconn_rxinit_phaligndone_read)(), (CXP[channel].downconn_rxinit_phaligndone_read)(),
); );
} }
}
change_linerate(channel, timer, CXP_SPEED::CXP_1);
} }
pub fn change_linerate(channel: usize, timer: &mut GlobalTimer, speed: CXP_SPEED) { pub fn change_linerate(speed: CXP_SPEED) {
// DEBUG: DRP pll for TXUSRCLK = freq(linerate)/20 // DEBUG: DRP pll for TXUSRCLK = freq(linerate)/20
let settings = txusrclk::get_txusrclk_config(speed); let settings = txusrclk::get_txusrclk_config(speed);
txusrclk::setup(channel, timer, settings); txusrclk::setup(settings);
change_qpll_fb_divider(speed); change_qpll_fb_divider(speed);
change_gtx_divider(channel, speed); change_gtx_divider(speed);
change_cdr_cfg(channel, speed); change_cdr_cfg(speed);
unsafe { unsafe {
csr::cxp_phys::downconn_qpll_reset_write(1); csr::cxp_phys::downconn_qpll_reset_write(1);
info!("waiting for QPLL/CPLL to lock..."); info!("waiting for QPLL/CPLL to lock...");
while csr::cxp_phys::downconn_qpll_locked_read() != 1 {} while csr::cxp_phys::downconn_qpll_locked_read() != 1 {}
info!("QPLL locked"); info!("QPLL locked");
}
unsafe { for channel in 0..CHANNEL_LEN {
(CXP[channel].downconn_tx_restart_write)(1); (CXP[channel].downconn_tx_restart_write)(1);
(CXP[channel].downconn_rx_restart_write)(1); (CXP[channel].downconn_rx_restart_write)(1);
} }
} }
}
fn change_qpll_fb_divider(speed: CXP_SPEED) { fn change_qpll_fb_divider(speed: CXP_SPEED) {
let qpll_div_reg = match speed { let qpll_div_reg = match speed {
@ -118,7 +122,7 @@ mod down_conn {
println!("0x36 = {:#06x}", qpll_read(0x36)); println!("0x36 = {:#06x}", qpll_read(0x36));
} }
fn change_gtx_divider(channel: usize, speed: CXP_SPEED) { fn change_gtx_divider(speed: CXP_SPEED) {
let div_reg = match speed { let div_reg = match speed {
CXP_SPEED::CXP_1 => 0x33, // RXOUT_DIV = 8 CXP_SPEED::CXP_1 => 0x33, // RXOUT_DIV = 8
CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 => 0x22, // RXOUT_DIV = 4 CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 => 0x22, // RXOUT_DIV = 4
@ -126,12 +130,14 @@ mod down_conn {
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => 0x00, // RXOUT_DIV = 1 CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => 0x00, // RXOUT_DIV = 1
}; };
println!("0x88 = {:#06x}", gtx_read(channel, 0x88)); for channel in 0..CHANNEL_LEN {
println!("channel {}, 0x88 = {:#06x}", channel, gtx_read(channel, 0x88));
gtx_write(channel, 0x88, div_reg); gtx_write(channel, 0x88, div_reg);
println!("0x88 = {:#06x}", gtx_read(channel, 0x88)); println!("channel {}, 0x88 = {:#06x}", channel, gtx_read(channel, 0x88));
}
} }
fn change_cdr_cfg(channel: usize, speed: CXP_SPEED) { fn change_cdr_cfg(speed: CXP_SPEED) {
struct CdrConfig { struct CdrConfig {
pub cfg_reg0: u16, // addr = 0xA8 pub cfg_reg0: u16, // addr = 0xA8
pub cfg_reg1: u16, // addr = 0xA9 pub cfg_reg1: u16, // addr = 0xA9
@ -175,12 +181,14 @@ mod down_conn {
}, },
}; };
for channel in 0..CHANNEL_LEN {
gtx_write(channel, 0x0A8, cdr_cfg.cfg_reg0); gtx_write(channel, 0x0A8, cdr_cfg.cfg_reg0);
gtx_write(channel, 0x0A9, cdr_cfg.cfg_reg1); gtx_write(channel, 0x0A9, cdr_cfg.cfg_reg1);
gtx_write(channel, 0x0AA, cdr_cfg.cfg_reg2); gtx_write(channel, 0x0AA, cdr_cfg.cfg_reg2);
gtx_write(channel, 0x0AB, cdr_cfg.cfg_reg3); gtx_write(channel, 0x0AB, cdr_cfg.cfg_reg3);
gtx_write(channel, 0x0AC, cdr_cfg.cfg_reg4); gtx_write(channel, 0x0AC, cdr_cfg.cfg_reg4);
} }
}
#[allow(dead_code)] #[allow(dead_code)]
fn gtx_read(channel: usize, address: u16) -> u16 { fn gtx_read(channel: usize, address: u16) -> u16 {
@ -224,6 +232,7 @@ mod down_conn {
pub mod txusrclk { pub mod txusrclk {
use super::*; use super::*;
#[derive(Copy, Clone)]
pub struct PLLSetting { pub struct PLLSetting {
pub clkout0_reg1: u16, //0x08 pub clkout0_reg1: u16, //0x08
pub clkout0_reg2: u16, //0x09 pub clkout0_reg2: u16, //0x09
@ -317,7 +326,8 @@ mod down_conn {
} }
} }
pub fn setup(channel: usize, timer: &mut GlobalTimer, settings: PLLSetting) { pub fn setup(settings: PLLSetting) {
for channel in 0..CHANNEL_LEN {
if false { if false {
info!("0x08 = {:#06x}", read(channel, 0x08)); info!("0x08 = {:#06x}", read(channel, 0x08));
info!("0x09 = {:#06x}", read(channel, 0x09)); info!("0x09 = {:#06x}", read(channel, 0x09));
@ -347,11 +357,10 @@ mod down_conn {
write(channel, 0x4F, settings.filt_reg2); write(channel, 0x4F, settings.filt_reg2);
reset(channel, false); reset(channel, false);
// wait for the pll to lock info!("waiting for PLL of txusrclk to lock...");
timer.delay_us(100); while unsafe { (CXP[channel].downconn_txpll_locked_read)() == 0 } {}
info!("txusrclk locked :D");
let locked = unsafe { (CXP[channel].downconn_txpll_locked_read)() == 1 }; }
info!("txusrclk locked = {}", locked);
} }
} }