forked from M-Labs/artiq-zynq
cxp downconn firmware: GTX setup
testing: add loopmode mode & tsusrclk mmcm drp bitbang testing: add IDLE word printout downconn: add QPLL and GTX setup downconn: add DRP to support all CXP linerate up to 12.5Gbps
This commit is contained in:
parent
f8a2920033
commit
cc8ae30303
|
@ -0,0 +1,554 @@
|
||||||
|
use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs;
|
||||||
|
use libboard_zynq::{println, timer::GlobalTimer};
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
// use log::info;
|
||||||
|
use crate::pl::csr;
|
||||||
|
|
||||||
|
pub struct CXP_DownConn_Settings {
|
||||||
|
pub rxdiv: u8,
|
||||||
|
pub qpll_fbdiv: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum CXP_SPEED {
|
||||||
|
CXP_1,
|
||||||
|
CXP_2,
|
||||||
|
CXP_3,
|
||||||
|
CXP_5,
|
||||||
|
CXP_6,
|
||||||
|
CXP_10,
|
||||||
|
CXP_12,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loopback_testing(timer: &mut GlobalTimer, speed: CXP_SPEED) {
|
||||||
|
println!("==============================================================================");
|
||||||
|
CXP_GTX::change_linerate(timer, speed);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
info!("waiting for tx&rx setup...");
|
||||||
|
timer.delay_us(50_000);
|
||||||
|
info!(
|
||||||
|
"tx_phaligndone = {} | rx_phaligndone = {}",
|
||||||
|
csr::cxp::downconn_txinit_phaligndone_read(),
|
||||||
|
csr::cxp::downconn_rxinit_phaligndone_read(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// enable txdata tranmission thought MGTXTXP, required by PMA loopback
|
||||||
|
csr::cxp::downconn_txenable_write(1);
|
||||||
|
|
||||||
|
info!("waiting for rx to align...");
|
||||||
|
while csr::cxp::downconn_rx_ready_read() != 1 {}
|
||||||
|
info!("rx ready!");
|
||||||
|
|
||||||
|
// loop {
|
||||||
|
for _ in 0..20 {
|
||||||
|
// NOTE: raw bits
|
||||||
|
// let data0 = csr::cxp::downconn_rxdata_0_read();
|
||||||
|
// let data1 = csr::cxp::downconn_rxdata_1_read();
|
||||||
|
// let data2 = csr::cxp::downconn_rxdata_2_read();
|
||||||
|
// let data3 = csr::cxp::downconn_rxdata_3_read();
|
||||||
|
// let rxready = csr::cxp::downconn_rx_ready_read();
|
||||||
|
// timer.delay_us(100);
|
||||||
|
// if data0 == 0b0101111100 || data0 == 0b1010000011 {
|
||||||
|
// println!(
|
||||||
|
// "data[0] = {:#012b} comma = {} | rx ready = {}",
|
||||||
|
// data0,
|
||||||
|
// data0 == 0b0101111100 || data0 == 0b1010000011,
|
||||||
|
// rxready,
|
||||||
|
// );
|
||||||
|
// timer.delay_us(1_000_000);
|
||||||
|
// } else if data0 == 0b1001111100 || data0 == 0b0110000011 {
|
||||||
|
// println!(
|
||||||
|
// "data[0] = {:#012b} K28.1 | rx ready = {}",
|
||||||
|
// data0,
|
||||||
|
// rxready,
|
||||||
|
// );
|
||||||
|
// timer.delay_us(1_000_000);
|
||||||
|
// } else {
|
||||||
|
// println!(
|
||||||
|
// "data[0] = {:#012b} | rx ready = {}",
|
||||||
|
// data0,
|
||||||
|
// rxready,
|
||||||
|
// );
|
||||||
|
// timer.delay_us(1_000_000);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// timer.delay_us(1_000_000);
|
||||||
|
// NOTE: raw bits
|
||||||
|
// let data0 = csr::cxp::downconn_rxdata_0_read();
|
||||||
|
// let data1 = csr::cxp::downconn_rxdata_1_read();
|
||||||
|
// let data2 = csr::cxp::downconn_rxdata_2_read();
|
||||||
|
// let data3 = csr::cxp::downconn_rxdata_3_read();
|
||||||
|
// println!(
|
||||||
|
// "0b{:010b} {:010b} {:010b} {:010b}",
|
||||||
|
// data0, data1, data2, data3
|
||||||
|
// );
|
||||||
|
|
||||||
|
// NOTE:decode data
|
||||||
|
// let data0_k = csr::cxp::downconn_decoded_k_0_read();
|
||||||
|
// let data1_k = csr::cxp::downconn_decoded_k_1_read();
|
||||||
|
// let data2_k = csr::cxp::downconn_decoded_k_2_read();
|
||||||
|
// let data3_k = csr::cxp::downconn_decoded_k_3_read();
|
||||||
|
let data0_decoded = csr::cxp::downconn_decoded_data_0_read();
|
||||||
|
let data1_decoded = csr::cxp::downconn_decoded_data_1_read();
|
||||||
|
let data2_decoded = csr::cxp::downconn_decoded_data_2_read();
|
||||||
|
let data3_decoded = csr::cxp::downconn_decoded_data_3_read();
|
||||||
|
println!(
|
||||||
|
"{:#04x} {:#04x} {:#04x} {:#04x}",
|
||||||
|
data0_decoded, data1_decoded, data2_decoded, data3_decoded,
|
||||||
|
);
|
||||||
|
// println!(
|
||||||
|
// "decoded_data[0] = {:#04x} decoded_k[0] = {:#b} decoded_data[1] = {:#04x} decoded_k[1] = {:#b}",
|
||||||
|
// data0_decoded,
|
||||||
|
// data0_k,
|
||||||
|
// data1_decoded,
|
||||||
|
// data1_k,
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(timer: &mut GlobalTimer) {
|
||||||
|
unsafe {
|
||||||
|
info!("turning on pmc loopback mode...");
|
||||||
|
csr::cxp::downconn_loopback_mode_write(0b010); // Near-End PMA Loopback
|
||||||
|
|
||||||
|
// QPLL setup
|
||||||
|
csr::cxp::downconn_qpll_reset_write(1);
|
||||||
|
info!("waiting for QPLL/CPLL to lock...");
|
||||||
|
while csr::cxp::downconn_qpll_locked_read() != 1 {}
|
||||||
|
info!("QPLL locked");
|
||||||
|
|
||||||
|
// tx/rx setup
|
||||||
|
csr::cxp::downconn_tx_start_init_write(1);
|
||||||
|
csr::cxp::downconn_rx_start_init_write(1);
|
||||||
|
|
||||||
|
info!("waiting for tx & rx setup...");
|
||||||
|
timer.delay_us(50_000);
|
||||||
|
info!(
|
||||||
|
"tx_phaligndone = {} | rx_phaligndone = {}",
|
||||||
|
csr::cxp::downconn_txinit_phaligndone_read(),
|
||||||
|
csr::cxp::downconn_rxinit_phaligndone_read(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CXP_GTX::change_linerate(timer, CXP_SPEED::CXP_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod CXP_GTX {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
struct RX_CDR_CFG {
|
||||||
|
pub cfg_reg0: u16, //0x0A8
|
||||||
|
pub cfg_reg1: u16, //0x0A9
|
||||||
|
pub cfg_reg2: u16, //0x0AA
|
||||||
|
pub cfg_reg3: u16, //0x0AB
|
||||||
|
pub cfg_reg4: u16, //0x0AC
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change_linerate(timer: &mut GlobalTimer, speed: CXP_SPEED) {
|
||||||
|
info!("Changing datarate to {:?}", speed);
|
||||||
|
// DEBUG: DRP pll for TXUSRCLK = freq(linerate)/20
|
||||||
|
let settings = txusrclk::get_txusrclk_config(speed);
|
||||||
|
txusrclk::setup(timer, settings);
|
||||||
|
|
||||||
|
change_qpll_settings(speed);
|
||||||
|
change_cdr_cfg(speed);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_qpll_reset_write(1);
|
||||||
|
info!("waiting for QPLL/CPLL to lock...");
|
||||||
|
while csr::cxp::downconn_qpll_locked_read() != 1 {}
|
||||||
|
info!("QPLL locked");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_tx_restart_write(1);
|
||||||
|
csr::cxp::downconn_rx_restart_write(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_qpll_settings(speed: CXP_SPEED) {
|
||||||
|
// Change QPLL_FBDIV
|
||||||
|
let qpll_div_reg = match speed {
|
||||||
|
CXP_SPEED::CXP_1 | CXP_SPEED::CXP_2 | CXP_SPEED::CXP_5 | CXP_SPEED::CXP_10 => 0x0120, // FB_Divider = 80
|
||||||
|
CXP_SPEED::CXP_3 | CXP_SPEED::CXP_6 | CXP_SPEED::CXP_12 => 0x0170, // FB_Divider = 100
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("0x36 = {:#018b}", qpll_read(0x36));
|
||||||
|
qpll_write(0x36, qpll_div_reg);
|
||||||
|
println!("0x36 = {:#018b}", qpll_read(0x36));
|
||||||
|
|
||||||
|
let rxout_div = match speed {
|
||||||
|
CXP_SPEED::CXP_1 => 0b100, // 8
|
||||||
|
CXP_SPEED::CXP_2 | CXP_SPEED::CXP_3 => 0b011, // 4
|
||||||
|
CXP_SPEED::CXP_5 | CXP_SPEED::CXP_6 => 0b010, // 2
|
||||||
|
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => 0b001, // 1
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_rx_div_write(rxout_div);
|
||||||
|
csr::cxp::downconn_tx_div_write(rxout_div);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_cdr_cfg(speed: CXP_SPEED) {
|
||||||
|
let cdr_cfg = match speed {
|
||||||
|
// rxout_div = 8
|
||||||
|
CXP_SPEED::CXP_1 => {
|
||||||
|
RX_CDR_CFG {
|
||||||
|
cfg_reg0: 0x0020, //0x0A8
|
||||||
|
cfg_reg1: 0x1008, //0x0A9
|
||||||
|
cfg_reg2: 0x23FF, //0x0AA
|
||||||
|
cfg_reg3: 0x0000, //0x0AB
|
||||||
|
cfg_reg4: 0x0003, //0x0AC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// rxout_div = 4
|
||||||
|
CXP_SPEED::CXP_2 | CXP_SPEED::CXP_5 => {
|
||||||
|
RX_CDR_CFG {
|
||||||
|
cfg_reg0: 0x0020, //0x0A8
|
||||||
|
cfg_reg1: 0x1010, //0x0A9
|
||||||
|
cfg_reg2: 0x23FF, //0x0AA
|
||||||
|
cfg_reg3: 0x0000, //0x0AB
|
||||||
|
cfg_reg4: 0x0003, //0x0AC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// rxout_div = 2
|
||||||
|
CXP_SPEED::CXP_3 | CXP_SPEED::CXP_6 => {
|
||||||
|
RX_CDR_CFG {
|
||||||
|
cfg_reg0: 0x0020, //0x0A8
|
||||||
|
cfg_reg1: 0x1020, //0x0A9
|
||||||
|
cfg_reg2: 0x23FF, //0x0AA
|
||||||
|
cfg_reg3: 0x0000, //0x0AB
|
||||||
|
cfg_reg4: 0x0003, //0x0AC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// // Divided by 1
|
||||||
|
// CXP_SPEED::CXP_6 => {
|
||||||
|
// RX_CDR_CFG {
|
||||||
|
// cfg_reg0: 0x0020, //0x0A8
|
||||||
|
// cfg_reg1: 0x1040, //0x0A9
|
||||||
|
// cfg_reg2: 0x23FF, //0x0AA
|
||||||
|
// cfg_reg3: 0x0000, //0x0AB
|
||||||
|
// cfg_reg4: 0x0003, //0x0AC
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// rxout_div = 1
|
||||||
|
CXP_SPEED::CXP_10 | CXP_SPEED::CXP_12 => {
|
||||||
|
RX_CDR_CFG {
|
||||||
|
cfg_reg0: 0x0020, //0x0A8
|
||||||
|
cfg_reg1: 0x1040, //0x0A9
|
||||||
|
cfg_reg2: 0x23FF, //0x0AA
|
||||||
|
cfg_reg3: 0x0000, //0x0AB
|
||||||
|
cfg_reg4: 0x000B, //0x0AC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
gtx_write(0x0A8, cdr_cfg.cfg_reg0);
|
||||||
|
gtx_write(0x0A9, cdr_cfg.cfg_reg1);
|
||||||
|
gtx_write(0x0AA, cdr_cfg.cfg_reg2);
|
||||||
|
gtx_write(0x0AB, cdr_cfg.cfg_reg3);
|
||||||
|
gtx_write(0x0AC, cdr_cfg.cfg_reg4);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gtx_read(address: u16) -> u16 {
|
||||||
|
// DEBUG: DRPCLK need to be on for a few cycle before accessing other DRP ports
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_gtx_daddr_write(address);
|
||||||
|
csr::cxp::downconn_gtx_dread_write(1);
|
||||||
|
while (csr::cxp::downconn_gtx_dready_read() != 1) {}
|
||||||
|
csr::cxp::downconn_gtx_dout_read()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gtx_write(address: u16, value: u16) {
|
||||||
|
// DEBUG: DRPCLK need to be on for a few cycle before accessing other DRP ports
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_gtx_daddr_write(address);
|
||||||
|
csr::cxp::downconn_gtx_din_write(value);
|
||||||
|
csr::cxp::downconn_gtx_din_stb_write(1);
|
||||||
|
while (csr::cxp::downconn_gtx_dready_read() != 1) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn qpll_read(address: u8) -> u16 {
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_qpll_daddr_write(address);
|
||||||
|
csr::cxp::downconn_qpll_dread_write(1);
|
||||||
|
while (csr::cxp::downconn_qpll_dready_read() != 1) {}
|
||||||
|
csr::cxp::downconn_qpll_dout_read()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn qpll_write(address: u8, value: u16) {
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_qpll_daddr_write(address);
|
||||||
|
csr::cxp::downconn_qpll_din_write(value);
|
||||||
|
csr::cxp::downconn_qpll_din_stb_write(1);
|
||||||
|
while (csr::cxp::downconn_qpll_dready_read() != 1) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod txusrclk {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub struct PLLSetting {
|
||||||
|
pub clkout0_reg1: u16, //0x08
|
||||||
|
pub clkout0_reg2: u16, //0x09
|
||||||
|
pub clkfbout_reg1: u16, //0x14
|
||||||
|
pub clkfbout_reg2: u16, //0x15
|
||||||
|
pub div_reg: u16, //0x16
|
||||||
|
pub lock_reg1: u16, //0x18
|
||||||
|
pub lock_reg2: u16, //0x19
|
||||||
|
pub lock_reg3: u16, //0x1A
|
||||||
|
pub power_reg: u16, //0x28
|
||||||
|
pub filt_reg1: u16, //0x4E
|
||||||
|
pub filt_reg2: u16, //0x4F
|
||||||
|
}
|
||||||
|
|
||||||
|
fn one_clock_cycle() {
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_pll_dclk_write(1);
|
||||||
|
csr::cxp::downconn_pll_dclk_write(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_addr(address: u8) {
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_pll_daddr_write(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_data(value: u16) {
|
||||||
|
unsafe {
|
||||||
|
csr::cxp::downconn_pll_din_write(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_enable(en: bool) {
|
||||||
|
unsafe {
|
||||||
|
let val = if en { 1 } else { 0 };
|
||||||
|
csr::cxp::downconn_pll_den_write(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_write_enable(en: bool) {
|
||||||
|
unsafe {
|
||||||
|
let val = if en { 1 } else { 0 };
|
||||||
|
csr::cxp::downconn_pll_dwen_write(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_data() -> u16 {
|
||||||
|
unsafe { csr::cxp::downconn_pll_dout_read() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drp_ready() -> bool {
|
||||||
|
unsafe { csr::cxp::downconn_pll_dready_read() == 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn read(address: u8) -> u16 {
|
||||||
|
set_addr(address);
|
||||||
|
set_enable(true);
|
||||||
|
// Set DADDR on the mmcm and assert DEN for one clock cycle
|
||||||
|
one_clock_cycle();
|
||||||
|
|
||||||
|
set_enable(false);
|
||||||
|
while !drp_ready() {
|
||||||
|
// keep the clock signal until data is ready
|
||||||
|
one_clock_cycle();
|
||||||
|
}
|
||||||
|
get_data()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(address: u8, value: u16) {
|
||||||
|
set_addr(address);
|
||||||
|
set_data(value);
|
||||||
|
set_write_enable(true);
|
||||||
|
set_enable(true);
|
||||||
|
// Set DADDR, DI on the mmcm and assert DWE, DEN for one clock cycle
|
||||||
|
one_clock_cycle();
|
||||||
|
|
||||||
|
set_write_enable(false);
|
||||||
|
set_enable(false);
|
||||||
|
while !drp_ready() {
|
||||||
|
// keep the clock signal until write is finished
|
||||||
|
one_clock_cycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(rst: bool) {
|
||||||
|
unsafe {
|
||||||
|
let val = if rst { 1 } else { 0 };
|
||||||
|
csr::cxp::downconn_txpll_reset_write(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup(timer: &mut GlobalTimer, settings: PLLSetting) {
|
||||||
|
if false {
|
||||||
|
info!("0x08 = {:#06x}", read(0x08));
|
||||||
|
info!("0x09 = {:#06x}", read(0x09));
|
||||||
|
info!("0x14 = {:#06x}", read(0x14));
|
||||||
|
info!("0x15 = {:#06x}", read(0x15));
|
||||||
|
info!("0x16 = {:#06x}", read(0x16));
|
||||||
|
info!("0x18 = {:#06x}", read(0x18));
|
||||||
|
info!("0x19 = {:#06x}", read(0x19));
|
||||||
|
info!("0x1A = {:#06x}", read(0x1A));
|
||||||
|
info!("0x28 = {:#06x}", read(0x28));
|
||||||
|
info!("0x4E = {:#06x}", read(0x4E));
|
||||||
|
info!("0x4F = {:#06x}", read(0x4F));
|
||||||
|
} else {
|
||||||
|
// Based on "DRP State Machine" from XAPP888
|
||||||
|
// hold reset HIGH during pll config
|
||||||
|
reset(true);
|
||||||
|
write(0x08, settings.clkout0_reg1);
|
||||||
|
write(0x09, settings.clkout0_reg2);
|
||||||
|
write(0x14, settings.clkfbout_reg1);
|
||||||
|
write(0x15, settings.clkfbout_reg2);
|
||||||
|
write(0x16, settings.div_reg);
|
||||||
|
write(0x18, settings.lock_reg1);
|
||||||
|
write(0x19, settings.lock_reg2);
|
||||||
|
write(0x1A, settings.lock_reg3);
|
||||||
|
write(0x28, settings.power_reg);
|
||||||
|
write(0x4E, settings.filt_reg1);
|
||||||
|
write(0x4F, settings.filt_reg2);
|
||||||
|
reset(false);
|
||||||
|
|
||||||
|
// wait for the pll to lock
|
||||||
|
timer.delay_us(100);
|
||||||
|
|
||||||
|
let locked = unsafe { csr::cxp::downconn_txpll_locked_read() == 1 };
|
||||||
|
info!("txusrclk locked = {}", locked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_txusrclk_config(speed: CXP_SPEED) -> PLLSetting {
|
||||||
|
match speed {
|
||||||
|
CXP_SPEED::CXP_1 => {
|
||||||
|
// CLKFBOUT_MULT = 8, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 32
|
||||||
|
// TXUSRCLK=62.5MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1410, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1104, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x5801, //0x19
|
||||||
|
lock_reg3: 0xdbe9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9808, //0x4E
|
||||||
|
filt_reg2: 0x9100, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_2 => {
|
||||||
|
// CLKFBOUT_MULT = 8, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 16
|
||||||
|
// TXUSRCLK=62.5MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1208, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1104, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x5801, //0x19
|
||||||
|
lock_reg3: 0xdbe9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9808, //0x4E
|
||||||
|
filt_reg2: 0x9100, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_3 => {
|
||||||
|
// CLKFBOUT_MULT = 10, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 16
|
||||||
|
// TXUSRCLK=78.125MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1208, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1145, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x7001, //0x19
|
||||||
|
lock_reg3: 0xf3e9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9908, //0x4E
|
||||||
|
filt_reg2: 0x1900, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_5 => {
|
||||||
|
// CLKFBOUT_MULT = 8, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 8
|
||||||
|
// TXUSRCLK=125MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1104, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1104, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x5801, //0x19
|
||||||
|
lock_reg3: 0xdbe9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9808, //0x4E
|
||||||
|
filt_reg2: 0x9100, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_6 => {
|
||||||
|
// CLKFBOUT_MULT = 10, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 8
|
||||||
|
// TXUSRCLK=156.25MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1104, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1145, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x7001, //0x19
|
||||||
|
lock_reg3: 0xf3e9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9908, //0x4E
|
||||||
|
filt_reg2: 0x1900, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_10 => {
|
||||||
|
// CLKFBOUT_MULT = 8, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 4
|
||||||
|
// TXUSRCLK=250MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1082, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1104, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x5801, //0x19
|
||||||
|
lock_reg3: 0xdbe9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9808, //0x4E
|
||||||
|
filt_reg2: 0x9100, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CXP_SPEED::CXP_12 => {
|
||||||
|
// CLKFBOUT_MULT = 10, DIVCLK_DIVIDE = 1 , CLKOUT0_DIVIDE = 4
|
||||||
|
// TXUSRCLK=312.5MHz
|
||||||
|
PLLSetting {
|
||||||
|
clkout0_reg1: 0x1082, //0x08
|
||||||
|
clkout0_reg2: 0x0000, //0x09
|
||||||
|
clkfbout_reg1: 0x1145, //0x14
|
||||||
|
clkfbout_reg2: 0x0000, //0x15
|
||||||
|
div_reg: 0x1041, //0x16
|
||||||
|
lock_reg1: 0x03e8, //0x18
|
||||||
|
lock_reg2: 0x7001, //0x19
|
||||||
|
lock_reg3: 0xf3e9, //0x1A
|
||||||
|
power_reg: 0x0000, //0x28
|
||||||
|
filt_reg1: 0x9908, //0x4E
|
||||||
|
filt_reg2: 0x1900, //0x4F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,8 +42,11 @@ pub mod si5324;
|
||||||
pub mod si549;
|
pub mod si549;
|
||||||
use core::{cmp, str};
|
use core::{cmp, str};
|
||||||
|
|
||||||
|
#[cfg(has_cxp)]
|
||||||
|
pub mod cxp_downconn;
|
||||||
#[cfg(has_cxp)]
|
#[cfg(has_cxp)]
|
||||||
pub mod cxp_upconn;
|
pub mod cxp_upconn;
|
||||||
|
|
||||||
pub fn identifier_read(buf: &mut [u8]) -> &str {
|
pub fn identifier_read(buf: &mut [u8]) -> &str {
|
||||||
unsafe {
|
unsafe {
|
||||||
pl::csr::identifier::address_write(0);
|
pl::csr::identifier::address_write(0);
|
||||||
|
|
Loading…
Reference in New Issue