Ready CPU CLK and start DRAM

master

@ -16,5 +16,5 @@ opt-level = 0
[profile.release] [profile.release]
panic = "abort" panic = "abort"
opt-level = "z" opt-level = "s"
lto = true lto = true

@ -1,20 +1,25 @@
use crate::{ use crate::{
ccu, ccu,
io::{read32, write32}, io::{read32, write32,sdelay},
print,
}; };
fn set_pll_cpux_axi() { fn set_pll_cpux_axi() {
let mut val:u32; let mut val:u32;
/* Select cpux clock src to osc24m, axi divide ratio is 3, system apb clk ratio is 4 */ /* Select cpux clock src to osc24m, axi divide ratio is 3, system apb clk ratio is 4 */
val = (0 << 24) | (3 << 8) | (1 << 0);
write32( write32(
ccu::BASE + ccu::CPU_AXI_CFG_REG, ccu::BASE + ccu::CPU_AXI_CFG_REG,
(0 << 24) | (3 << 8) | (1 << 0), val
); );
// // sdelay(1); sdelay(1);
// /* Disable pll gating */ // /* Disable pll gating */
val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG);
// print!("v={:#?}\r\n",val);
val &= !(1 << 27); val &= !(1 << 27);
write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val); write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val);
@ -22,7 +27,7 @@ fn set_pll_cpux_axi() {
val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG);
val |= 1 << 30; val |= 1 << 30;
write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val); write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val);
// sdelay(5); sdelay(5);
// /* Set default clk to 1008mhz */ // /* Set default clk to 1008mhz */
val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG);
@ -42,7 +47,7 @@ fn set_pll_cpux_axi() {
/* Wait pll stable */ /* Wait pll stable */
while (!(read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG) & (0x1 << 28)))==0{} while (!(read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG) & (0x1 << 28)))==0{}
// sdelay(20); sdelay(20);
// /* Enable pll gating */ // /* Enable pll gating */
val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG);
@ -53,14 +58,14 @@ fn set_pll_cpux_axi() {
val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG);
val &= !(1 << 29); val &= !(1 << 29);
write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val); write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val);
// // sdelay(1); sdelay(1);
// /* set and change cpu clk src to PLL_CPUX, PLL_CPUX:AXI0 = 1008M:504M */ // /* set and change cpu clk src to PLL_CPUX, PLL_CPUX:AXI0 = 1008M:504M */
val = read32(ccu::BASE + ccu::CPU_AXI_CFG_REG); val = read32(ccu::BASE + ccu::CPU_AXI_CFG_REG);
val &= !(0x07 << 24 | 0x3 << 16 | 0x3 << 8 | 0xf << 0); val &= !(0x07 << 24 | 0x3 << 16 | 0x3 << 8 | 0xf << 0);
val |= 0x03 << 24 | 0x0 << 16 | 0x0 << 8 | 0x1 << 0; val |= 0x03 << 24 | 0x0 << 16 | 0x0 << 8 | 0x1 << 0;
write32(ccu::BASE + ccu::CPU_AXI_CFG_REG, val); write32(ccu::BASE + ccu::CPU_AXI_CFG_REG, val);
// // sdelay(1); sdelay(1);
} }
fn set_pll_periph0() fn set_pll_periph0()
@ -100,7 +105,7 @@ fn set_pll_periph0()
}; };
} }
// sdelay(20); sdelay(20);
/* Lock disable */ /* Lock disable */
val = read32(ccu::BASE + ccu::PLL_PERI0_CTRL_REG); val = read32(ccu::BASE + ccu::PLL_PERI0_CTRL_REG);
@ -112,21 +117,21 @@ fn set_ahb()
{ {
write32(ccu::BASE + ccu::PSI_CLK_REG, (2 << 0) | (0 << 8)); write32(ccu::BASE + ccu::PSI_CLK_REG, (2 << 0) | (0 << 8));
write32(ccu::BASE + ccu::PSI_CLK_REG, read32(ccu::BASE + ccu::PSI_CLK_REG) | (0x03 << 24)); write32(ccu::BASE + ccu::PSI_CLK_REG, read32(ccu::BASE + ccu::PSI_CLK_REG) | (0x03 << 24));
// sdelay(1); sdelay(1);
} }
fn set_apb() fn set_apb()
{ {
write32(ccu::BASE + ccu::APB0_CLK_REG, (2 << 0) | (1 << 8)); write32(ccu::BASE + ccu::APB0_CLK_REG, (2 << 0) | (1 << 8));
write32(ccu::BASE + ccu::APB0_CLK_REG, (0x03 << 24) | read32(ccu::BASE + ccu::APB0_CLK_REG)); write32(ccu::BASE + ccu::APB0_CLK_REG, (0x03 << 24) | read32(ccu::BASE + ccu::APB0_CLK_REG));
// sdelay(1); sdelay(1);
} }
fn set_dma() fn set_dma()
{ {
/* Dma reset */ /* Dma reset */
write32(ccu::BASE + ccu::DMA_BGR_REG, read32(ccu::BASE + ccu::DMA_BGR_REG) | (1 << 16)); write32(ccu::BASE + ccu::DMA_BGR_REG, read32(ccu::BASE + ccu::DMA_BGR_REG) | (1 << 16));
// sdelay(20); sdelay(20);
/* Enable gating clock for dma */ /* Enable gating clock for dma */
write32(ccu::BASE + ccu::DMA_BGR_REG, read32(ccu::BASE + ccu::DMA_BGR_REG) | (1 << 0)); write32(ccu::BASE + ccu::DMA_BGR_REG, read32(ccu::BASE + ccu::DMA_BGR_REG) | (1 << 0));
} }
@ -139,7 +144,7 @@ fn set_mbus()
val = read32(ccu::BASE + ccu::MBUS_CLK_REG); val = read32(ccu::BASE + ccu::MBUS_CLK_REG);
val |= 0x1 << 30; val |= 0x1 << 30;
write32(ccu::BASE + ccu::MBUS_CLK_REG, val); write32(ccu::BASE + ccu::MBUS_CLK_REG, val);
// sdelay(1); sdelay(1);
/* Enable mbus master clock gating */ /* Enable mbus master clock gating */
write32(ccu::BASE + ccu::MBUS_MAT_CLK_GATING_REG, 0x00000d87); write32(ccu::BASE + ccu::MBUS_MAT_CLK_GATING_REG, 0x00000d87);
@ -162,7 +167,7 @@ fn set_module(addr:u32)
/* Wait pll stable */ /* Wait pll stable */
while(!(read32(addr) & (0x1 << 28)))==0{}; while(!(read32(addr) & (0x1 << 28)))==0{};
// sdelay(20); sdelay(20);
// /* Lock disable */ // /* Lock disable */
val = read32(addr); val = read32(addr);
@ -204,3 +209,30 @@ pub fn sunxi_clk_get_peri1x_rate()->u32
} }
0u32 0u32
} }
pub fn sunxi_clk_dump()->u32
{
let reg32:u32;
// uint32_t cpu_clk, plln, pllm;
let p0:u8;
let p1:u8;
/* PLL CPU */
// reg32 = read32(ccu::BASE + ccu::CPU_AXI_CFG_REG);
reg32 = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG);
// if (reg32 & (1 << 31)) {
p0 = (reg32 >> 16) as u8 & 0x03;
if p0 == 0 {
p1 = 1;
} else if p0 == 1 {
p1 = 2;
} else if p0 == 2 {
p1 = 4;
} else {
p1 = 1;
}
let pr:u32 = ((((reg32 >> 8) & 0xff) + 1) * 24)/( p1 as u32 );
pr
}

@ -0,0 +1,211 @@
use crate::{
io::{read32, sdelay, write32},
print,
};
#[repr(C)]
#[derive(Clone, Copy)]
struct DramPara_t {
//normal configuration
dram_clk: u32,
dram_type: u32, //dram_type DDR2: 2 DDR3: 3 LPDDR2: 6 LPDDR3: 7 DDR3L: 31
//unsigned int lpddr2_type, //LPDDR2 type S4:0 S2:1 NVM:2
dram_zq: u32, //do not need
dram_odt_en: u32,
//control configuration
dram_para1: u32,
dram_para2: u32,
//timing configuration
dram_mr0: u32,
dram_mr1: u32,
dram_mr2: u32,
dram_mr3: u32,
dram_tpr0: u32, //DRAMTMG0
dram_tpr1: u32, //DRAMTMG1
dram_tpr2: u32, //DRAMTMG2
dram_tpr3: u32, //DRAMTMG3
dram_tpr4: u32, //DRAMTMG4
dram_tpr5: u32, //DRAMTMG5
dram_tpr6: u32, //DRAMTMG8
//reserved for future use
dram_tpr7: u32,
dram_tpr8: u32,
dram_tpr9: u32,
dram_tpr10: u32,
dram_tpr11: u32,
dram_tpr12: u32,
dram_tpr13: u32,
}
impl DramPara_t {
pub fn init(self) -> u32 {
let mut rc: u32;
let mut mem_size: u32;
// Test ZQ status
if self.dram_tpr13 & 0x10000 != 0 {
print!("DRAM only have internal ZQ!!\r\n");
write32(0x3000160, read32(0x3000160) | 0x100);
write32(0x3000168, 0);
sdelay(10);
} else {
write32(0x3000160, read32(0x3000160) & 0xfffffffc);
write32(0x7010254, self.dram_tpr13 & 0x10000);
sdelay(10);
write32(0x3000160, (read32(0x3000160) & 0xfffffef7) | 2);
sdelay(10);
write32(0x3000160, read32(0x3000160) | 0x001);
sdelay(20);
print!("ZQ value = 0x{:x}\r\n", read32(0x300016c));
}
// Set voltage
self.vol_set();
// Set SDRAM controller auto config
if (self.dram_tpr13 & 0x1) == 0 {
if self.auto_scan_dram_config() == 0 {
print!("auto_scan_dram_config() FAILED\r\n");
return 0;
}
}
// Print header message (too late)
print!("DRAM BOOT DRIVE INFO: {:?}\r\n", "V0.24");
print!("DRAM CLK = {:?} MHz\r\n", self.dram_clk);
print!("DRAM Type = {:?} (2:DDR2,3:DDR3)\r\n", self.dram_type);
if (self.dram_odt_en & 0x1) == 0 {
print!("DRAMC read ODT off.\r\n");
} else {
print!("DRAMC ZQ value: 0x{:x?}\r\n", self.dram_zq);
}
// report ODT
rc = self.dram_mr1;
if (rc & 0x44) == 0 {
print!("DRAM ODT off.\r\n");
} else {
print!("DRAM ODT value: 0x{:x?}.\r\n", rc);
}
// Init core, final run
if (self.mctl_core_init() == 0) {
print!("DRAM initialisation error : 1 !\r\n");
return 0;
}
// Get sdram size
rc = self.dram_para2;
if rc < 0 {
rc = (rc & 0x7fff0000u32) >> 16;
} else {
rc = self.get_size();
print!("DRAM SIZE = {:?}M\r\n", rc);
// self.dram_para2 = (self.dram_para2 & 0xffffu32) | rc << 16;
}
mem_size = rc;
// #if 0
// // Purpose ??
// if (self.dram_tpr13 & (1 << 30)) {
// rc = read32(self.dram_tpr8);
// if (rc == 0) {
// rc = 0x10000200;
// }
// write32(0x31030a0, rc);
// write32(0x310309c, 0x40a);
// write32(0x3103004, read32(0x3103004) | 1);
// print!("Enable Auto SR");
// } else {
// #endif
write32(0x31030a0, read32(0x31030a0) & 0xffff0000);
write32(0x3103004, read32(0x3103004) & (!0x1));
// }
// Pupose ??
rc = read32(0x3103100) & !(0xf000);
if (self.dram_tpr13 & 0x200) == 0 {
if (self.dram_type != 6) {
write32(0x3103100, rc);
}
} else {
write32(0x3103100, rc | 0x5000);
}
write32(0x3103140, read32(0x3103140) | (1 << 31));
if (self.dram_tpr13 & (1 << 8)) != 0 {
write32(0x31030b8, read32(0x3103140) | 0x300);
}
rc = read32(0x3103108);
if (self.dram_tpr13 & (1 << 16)) != 0 {
rc &= 0xffffdfff;
} else {
rc |= 0x00002000;
}
write32(0x3103108, rc);
// Purpose ??
if self.dram_type == 7 {
rc = read32(0x310307c) & 0xfff0ffff;
rc |= 0x0001000;
write32(0x310307c, rc);
}
self.enable_all_master();
if (self.dram_tpr13 & (1 << 28)) != 0 {
rc = read32(0x70005d4);
// if ((rc & (1 << 16))!=0 || dramc_simple_wr_test(mem_size, 4096))!=0 {
// return 0;
// }
}
mem_size
}
fn vol_set(self) {
let mut reg = 0;
let mut vol = 0;
match self.dram_type {
2 => {
vol = 47;
}
3 => {
vol = 25;
}
_ => {
vol = 0;
}
}
vol = 25; // XXX
reg = read32(0x3000150);
reg = (reg & 0xffdf00ff) | vol << 8;
/*
reg = read32(0x3000150);
reg &= ~(0xff00);
reg |= vol << 8;
reg &= ~(0x200000);
*/
write32(0x3000150, reg);
sdelay(1);
// sid_read_ldoB_cal(para);
}
fn auto_scan_dram_config(self) -> u32 {
return 0u32;
}
fn mctl_core_init(self) -> u32 {
return 0u32;
}
fn get_size(self) -> u32 {
return 0u32;
}
fn enable_all_master(self) {}
fn dramc_simple_wr_test(mem_size: u32, test: u32) -> u32 {
0u32
}
}

@ -15,3 +15,21 @@ pub fn read32(addr:u32)->u32
} }
value value
} }
pub fn sdelay(ticks:u32) {
let mut rnd_addr = 0u32;
let addr = &mut rnd_addr as *mut u32;
let mut z: u32 = ticks;
unsafe {
// asm!(
// "1:",
// "subs {0}, {0}, #1",
// "bne 1b",
// in(reg) i
// );
while z > 0 {
core::ptr::write_volatile(addr, z);
z -= 1;
}
}
}

@ -8,6 +8,9 @@ use rt::entry;
entry!(main); entry!(main);
use rt::cpu; use rt::cpu;
use crate::io::read32;
use crate::io::write32;
pub mod ccu; pub mod ccu;
pub mod clk; pub mod clk;
pub mod gpio; pub mod gpio;
@ -15,6 +18,7 @@ pub mod io;
pub mod print; pub mod print;
pub mod sdhci; pub mod sdhci;
pub mod uart; pub mod uart;
pub mod dram;
fn main() -> ! { fn main() -> ! {
uart::init(); uart::init();
@ -24,10 +28,27 @@ fn main() -> ! {
let pin22: u32 = 1 << 22; let pin22: u32 = 1 << 22;
//инициализация порта D ноги 22 //инициализация порта D ноги 22
gpio::init(gpio_d, 22, gpio::PD22_Select::Output as u8); gpio::init(gpio_d, 22, gpio::PD22_Select::Output as u8);
print!("PD22 inited\n"); // print!("PD22 inited\n");
// let clk=clk::sunxi_clk_get_peri1x_rate();
// print!("PLL={:?} Hz\r\n",clk);
clk::init(); clk::init();
let clk=clk::sunxi_clk_get_peri1x_rate(); let pr = clk::sunxi_clk_dump();
print!("{:?}\r\n",clk); print!("CLK={:?} MHz\r\n", pr);
/* ?? */
let mut reg32 = read32(0x070901f4);
if (reg32 & 0x1f) != 0 {
reg32 = (reg32 & 0xffffff8f) | 0x40;
reg32 = (reg32 & 0xffffff8f) | 0xc0;
reg32 = (reg32 & 0xffffff8e) | 0xc0;
write32(0x070901f4, reg32);
print!("fix vccio detect value:0x{:X?}\r\n", reg32);
}
let addr = 0x0200180Cu32;
let val = (1 << 16) | (1 << 0);
write32(addr, val);
delay();
//мигаем //мигаем
loop { loop {
unsafe { unsafe {

@ -1,6 +1,8 @@
use core::fmt;
use crate::uart; use crate::uart;
use core::fmt;
#[no_mangle]
#[inline(always)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
pub use core::fmt::Write; pub use core::fmt::Write;
uart::console().write_fmt(args).unwrap(); uart::console().write_fmt(args).unwrap();
@ -21,6 +23,6 @@ macro_rules! print {
macro_rules! println { macro_rules! println {
() => ($crate::print!("\n")); () => ($crate::print!("\n"));
($($arg:tt)*) => ({ ($($arg:tt)*) => ({
$crate::print::_print(format_args_nl!($($arg)*)); $crate::print::_print(format_args!($($arg)*));
}) })
} }
Loading…
Cancel
Save