diff --git a/Cargo.toml b/Cargo.toml index 0d1977f..a1b766c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,5 +16,5 @@ opt-level = 0 [profile.release] panic = "abort" -opt-level = "z" +opt-level = "s" lto = true \ No newline at end of file diff --git a/src/clk/mod.rs b/src/clk/mod.rs index 8ffe66c..e913c70 100644 --- a/src/clk/mod.rs +++ b/src/clk/mod.rs @@ -1,28 +1,33 @@ use crate::{ ccu, - io::{read32, write32}, - print, + io::{read32, write32,sdelay}, }; + + fn set_pll_cpux_axi() { 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( ccu::BASE + ccu::CPU_AXI_CFG_REG, - (0 << 24) | (3 << 8) | (1 << 0), + val ); - // // sdelay(1); + sdelay(1); // /* Disable pll gating */ val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); + // print!("v={:#?}\r\n",val); val &= !(1 << 27); - write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val); + write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val); // /* Enable pll ldo */ val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); val |= 1 << 30; write32(ccu::BASE + ccu::PLL_CPU_CTRL_REG, val); - // sdelay(5); + sdelay(5); // /* Set default clk to 1008mhz */ val = read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG); @@ -42,7 +47,7 @@ fn set_pll_cpux_axi() { /* Wait pll stable */ while (!(read32(ccu::BASE + ccu::PLL_CPU_CTRL_REG) & (0x1 << 28)))==0{} - // sdelay(20); + sdelay(20); // /* Enable pll gating */ 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 &= !(1 << 29); 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 */ val = read32(ccu::BASE + ccu::CPU_AXI_CFG_REG); val &= !(0x07 << 24 | 0x3 << 16 | 0x3 << 8 | 0xf << 0); val |= 0x03 << 24 | 0x0 << 16 | 0x0 << 8 | 0x1 << 0; write32(ccu::BASE + ccu::CPU_AXI_CFG_REG, val); - // // sdelay(1); + sdelay(1); } fn set_pll_periph0() @@ -100,7 +105,7 @@ fn set_pll_periph0() }; } - // sdelay(20); + sdelay(20); /* Lock disable */ 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, read32(ccu::BASE + ccu::PSI_CLK_REG) | (0x03 << 24)); - // sdelay(1); + sdelay(1); } fn set_apb() { 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)); - // sdelay(1); + sdelay(1); } fn set_dma() { /* Dma reset */ 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 */ 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 |= 0x1 << 30; write32(ccu::BASE + ccu::MBUS_CLK_REG, val); - // sdelay(1); + sdelay(1); /* Enable mbus master clock gating */ write32(ccu::BASE + ccu::MBUS_MAT_CLK_GATING_REG, 0x00000d87); @@ -162,7 +167,7 @@ fn set_module(addr:u32) /* Wait pll stable */ while(!(read32(addr) & (0x1 << 28)))==0{}; - // sdelay(20); + sdelay(20); // /* Lock disable */ val = read32(addr); @@ -203,4 +208,31 @@ pub fn sunxi_clk_get_peri1x_rate()->u32 return (((24 * plln)/(pllm * p0)) >> 1) as u32 * 1000 * 1000; } 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 + } \ No newline at end of file diff --git a/src/dram/mod.rs b/src/dram/mod.rs new file mode 100644 index 0000000..5a19103 --- /dev/null +++ b/src/dram/mod.rs @@ -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 + } +} diff --git a/src/io/mod.rs b/src/io/mod.rs index 211c72f..25b6052 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -14,4 +14,22 @@ pub fn read32(addr:u32)->u32 value = core::ptr::read_volatile(addr as *const u32); } 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; + } + } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 71c37c6..ef5cc7b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,9 @@ use rt::entry; entry!(main); use rt::cpu; + +use crate::io::read32; +use crate::io::write32; pub mod ccu; pub mod clk; pub mod gpio; @@ -15,6 +18,7 @@ pub mod io; pub mod print; pub mod sdhci; pub mod uart; +pub mod dram; fn main() -> ! { uart::init(); @@ -24,10 +28,27 @@ fn main() -> ! { let pin22: u32 = 1 << 22; //инициализация порта D ноги 22 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(); - let clk=clk::sunxi_clk_get_peri1x_rate(); - print!("{:?}\r\n",clk); + let pr = clk::sunxi_clk_dump(); + 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 { unsafe { diff --git a/src/print.rs b/src/print.rs index c378eea..225341f 100644 --- a/src/print.rs +++ b/src/print.rs @@ -1,8 +1,10 @@ -use core::fmt; use crate::uart; +use core::fmt; +#[no_mangle] +#[inline(always)] pub fn _print(args: fmt::Arguments) { - pub use core::fmt::Write; + pub use core::fmt::Write; uart::console().write_fmt(args).unwrap(); } @@ -21,6 +23,6 @@ macro_rules! print { macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ({ - $crate::print::_print(format_args_nl!($($arg)*)); + $crate::print::_print(format_args!($($arg)*)); }) -} \ No newline at end of file +}