* rename a10-meminfo to meminfo * add static build to Makefile * fix operand warning * built binary verified on proper linux and android
Signed-off-by: Luc Verhaegen <l...@skynet.be> --- .gitignore | 1 + Makefile | 3 + README | 6 + a10-meminfo.c | 288 --------------------------------------------------------- meminfo.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 298 insertions(+), 288 deletions(-) delete mode 100644 a10-meminfo.c create mode 100644 meminfo.c diff --git a/.gitignore b/.gitignore index 22df838..490a572 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ bootinfo fel pio nand-part +meminfo *.o *.swp diff --git a/Makefile b/Makefile index f58bced..922da8f 100644 --- a/Makefile +++ b/Makefile @@ -111,6 +111,9 @@ boot_head_sun5i.bin: boot_head_sun5i.elf bootinfo: bootinfo.c +meminfo: meminfo.c + $(CROSS_COMPILE)gcc -g -O0 -Wall -static -o $@ $^ + .gitignore: Makefile @for x in $(TOOLS) '*.o' '*.swp'; do \ echo "$$x"; \ diff --git a/README b/README index 506930f..e71933f 100644 --- a/README +++ b/README @@ -60,5 +60,11 @@ phoenix_info: phoenixcard utility and optionally extracts the embedded boot code & firmware file from their hidden partitions. +meminfo: + Tool for reading DRAM settings from registers. Compiled as a + static binary for use on android and other OSes. To build this, + get a toolchain, and run: + make CROSS_COMPILE=arm-linux-gnueabihf- meminfo + This software is licensed under the terms of GPLv2+ as defined by the Free Software Foundation, details can be read in the COPYING file. diff --git a/a10-meminfo.c b/a10-meminfo.c deleted file mode 100644 index 9814783..0000000 --- a/a10-meminfo.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * A10-meminfo - * Dumps DRAM controller settings - * - * Author: Floris Bos - * License: GPL - * - * Compile with: gcc -static -o a10-meminfo-static a10-meminfo.c - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <dirent.h> -#include <fcntl.h> -#include <assert.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <stdint.h> - -#define SUNXI_DRAMC_BASE 0x01c01000 -#define SUNXI_CCM_BASE 0x01C20000 - -#define CCM_PLL5_FACTOR_M 0 -#define CCM_PLL5_FACTOR_K 4 -#define CCM_PLL5_FACTOR_N 8 -#define CCM_PLL5_FACTOR_P 16 - -#define CCM_PLL5_FACTOR_M_SIZE 0x03 -#define CCM_PLL5_FACTOR_K_SIZE 0x03 -#define CCM_PLL5_FACTOR_N_SIZE 0x1f -#define CCM_PLL5_FACTOR_P_SIZE 0x03 - -typedef uint32_t u32; -typedef uint8_t u8; - -/* - * Memory header definition copied from u-boot arch/arm/include/asm/arch-sunxi/dram.h - * (C) Copyright 2007-2012 Allwinner Technology Co., Ltd. <www.allwinnertech.com>) - */ -struct sunxi_dram_reg { - u32 ccr; /* 0x00 controller configuration register */ - u32 dcr; /* 0x04 dram configuration register */ - u32 iocr; /* 0x08 i/o configuration register */ - u32 csr; /* 0x0c controller status register */ - u32 drr; /* 0x10 dram refresh register */ - u32 tpr0; /* 0x14 dram timing parameters register 0 */ - u32 tpr1; /* 0x18 dram timing parameters register 1 */ - u32 tpr2; /* 0x1c dram timing parameters register 2 */ - u32 gdllcr; /* 0x20 global dll control register */ - u8 res0[0x28]; - u32 rslr0; /* 0x4c rank system latency register */ - u32 rslr1; /* 0x50 rank system latency register */ - u8 res1[0x8]; - u32 rdgr0; /* 0x5c rank dqs gating register */ - u32 rdgr1; /* 0x60 rank dqs gating register */ - u8 res2[0x34]; - u32 odtcr; /* 0x98 odt configuration register */ - u32 dtr0; /* 0x9c data training register 0 */ - u32 dtr1; /* 0xa0 data training register 1 */ - u32 dtar; /* 0xa4 data training address register */ - u32 zqcr0; /* 0xa8 zq control register 0 */ - u32 zqcr1; /* 0xac zq control register 1 */ - u32 zqsr; /* 0xb0 zq status register */ - u32 idcr; /* 0xb4 initializaton delay configure reg */ - u8 res3[0x138]; - u32 mr; /* 0x1f0 mode register */ - u32 emr; /* 0x1f4 extended mode register */ - u32 emr2; /* 0x1f8 extended mode register */ - u32 emr3; /* 0x1fc extended mode register */ - u32 dllctr; /* 0x200 dll control register */ - u32 dllcr[5]; /* 0x204 dll control register 0(byte 0) */ - /* 0x208 dll control register 1(byte 1) */ - /* 0x20c dll control register 2(byte 2) */ - /* 0x210 dll control register 3(byte 3) */ - /* 0x214 dll control register 4(byte 4) */ - u32 dqtr0; /* 0x218 dq timing register */ - u32 dqtr1; /* 0x21c dq timing register */ - u32 dqtr2; /* 0x220 dq timing register */ - u32 dqtr3; /* 0x224 dq timing register */ - u32 dqstr; /* 0x228 dqs timing register */ - u32 dqsbtr; /* 0x22c dqsb timing register */ - u32 mcr; /* 0x230 mode configure register */ - u8 res[0x8]; - u32 reg_23c; /* 0x23c register description unknown!!! */ - u32 apr; /* 0x240 arbiter period register */ - u32 pldtr; /* 0x244 priority level data threshold reg */ - u8 res5[0x8]; - u32 hpcr[32]; /* 0x250 host port configure register */ - u8 res6[0x10]; - u32 csel; /* 0x2e0 controller select register */ -}; - -struct dram_para { - u32 baseaddr; - u32 clock; - u32 type; - u32 rank_num; - u32 density; - u32 io_width; - u32 bus_width; - u32 cas; - u32 zq; - u32 odt_en; - u32 size; - u32 tpr0; - u32 tpr1; - u32 tpr2; - u32 tpr3; - u32 tpr4; - u32 tpr5; - u32 emr1; - u32 emr2; - u32 emr3; -}; - -/* Clock control header copied from include/asm/arch-sunxi/clock.h */ -struct sunxi_ccm_reg { - u32 pll1_cfg; /* 0x00 pll1 control */ - u32 pll1_tun; /* 0x04 pll1 tuning */ - u32 pll2_cfg; /* 0x08 pll2 control */ - u32 pll2_tun; /* 0x0c pll2 tuning */ - u32 pll3_cfg; /* 0x10 pll3 control */ - u8 res0[0x4]; - u32 pll4_cfg; /* 0x18 pll4 control */ - u8 res1[0x4]; - u32 pll5_cfg; /* 0x20 pll5 control */ - u32 pll5_tun; /* 0x24 pll5 tuning */ - u32 pll6_cfg; /* 0x28 pll6 control */ - u32 pll6_tun; /* 0x2c pll6 tuning */ - u32 pll7_cfg; /* 0x30 pll7 control */ - u8 res2[0x4]; - u32 pll1_tun2; /* 0x38 pll5 tuning2 */ - u32 pll5_tun2; /* 0x3c pll5 tuning2 */ - u8 res3[0xc]; - u32 pll_lock_dbg; /* 0x4c pll lock time debug */ - u32 osc24m_cfg; /* 0x50 osc24m control */ - u32 cpu_ahb_apb0_cfg; /* 0x54 cpu,ahb and apb0 divide ratio */ - u32 apb1_clk_div_cfg; /* 0x58 apb1 clock dividor */ - u32 axi_gate; /* 0x5c axi module clock gating */ - u32 ahb_gate0; /* 0x60 ahb module clock gating 0 */ - u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */ - u32 apb0_gate; /* 0x68 apb0 module clock gating */ - u32 apb1_gate; /* 0x6c apb1 module clock gating */ - u8 res4[0x10]; - u32 nand_sclk_cfg; /* 0x80 nand sub clock control */ - u32 ms_sclk_cfg; /* 0x84 memory stick sub clock control */ - u32 sd0_clk_cfg; /* 0x88 sd0 clock control */ - u32 sd1_clk_cfg; /* 0x8c sd1 clock control */ - u32 sd2_clk_cfg; /* 0x90 sd2 clock control */ - u32 sd3_clk_cfg; /* 0x94 sd3 clock control */ - u32 ts_clk_cfg; /* 0x98 transport stream clock control */ - u32 ss_clk_cfg; /* 0x9c */ - u32 spi0_clk_cfg; /* 0xa0 */ - u32 spi1_clk_cfg; /* 0xa4 */ - u32 spi2_clk_cfg; /* 0xa8 */ - u32 pata_clk_cfg; /* 0xac */ - u32 ir0_clk_cfg; /* 0xb0 */ - u32 ir1_clk_cfg; /* 0xb4 */ - u32 iis_clk_cfg; /* 0xb8 */ - u32 ac97_clk_cfg; /* 0xbc */ - u32 spdif_clk_cfg; /* 0xc0 */ - u32 keypad_clk_cfg; /* 0xc4 */ - u32 sata_clk_cfg; /* 0xc8 */ - u32 usb_clk_cfg; /* 0xcc */ - u32 gps_clk_cfg; /* 0xd0 */ - u32 spi3_clk_cfg; /* 0xd4 */ - u8 res5[0x28]; - u32 dram_clk_cfg; /* 0x100 */ - u32 be0_clk_cfg; /* 0x104 */ - u32 be1_clk_cfg; /* 0x108 */ - u32 fe0_clk_cfg; /* 0x10c */ - u32 fe1_clk_cfg; /* 0x110 */ - u32 mp_clk_cfg; /* 0x114 */ - u32 lcd0_ch0_clk_cfg; /* 0x118 */ - u32 lcd1_ch0_clk_cfg; /* 0x11c */ - u32 csi_isp_clk_cfg; /* 0x120 */ - u8 res6[0x4]; - u32 tvd_clk_reg; /* 0x128 */ - u32 lcd0_ch1_clk_cfg; /* 0x12c */ - u32 lcd1_ch1_clk_cfg; /* 0x130 */ - u32 csi0_clk_cfg; /* 0x134 */ - u32 csi1_clk_cfg; /* 0x138 */ - u32 ve_clk_cfg; /* 0x13c */ - u32 audio_codec_clk_cfg; /* 0x140 */ - u32 avs_clk_cfg; /* 0x144 */ - u32 ace_clk_cfg; /* 0x148 */ - u32 lvds_clk_cfg; /* 0x14c */ - u32 hdmi_clk_cfg; /* 0x150 */ - u32 mali_clk_cfg; /* 0x154 */ - u8 res7[0x4]; - u32 mbus_clk_cfg; /* 0x15c */ -}; - - -int mem_fd = -1; - -volatile unsigned *map_physical_memory(uint32_t addr, size_t len) -{ - volatile unsigned *mem; - - if (mem_fd == -1 && (mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) - { - perror("opening /dev/mem"); - exit(1); - } - - mem = (volatile unsigned *) mmap(NULL, len, PROT_READ, MAP_SHARED, mem_fd, (off_t) addr); - - if (mem == MAP_FAILED) - { - perror("mmap"); - exit (1); - } - - return mem; -} - - -int main(int argc, char **argv) -{ - volatile struct sunxi_dram_reg *r = (volatile struct sunxi_dram_reg *) map_physical_memory(SUNXI_DRAMC_BASE, 4096); - volatile struct sunxi_ccm_reg *ccm = (volatile struct sunxi_ccm_reg *) map_physical_memory(SUNXI_CCM_BASE, 4096); - struct dram_para p = {0}; - - /* Convert information found inside registers back to dram_para struct */ - p.tpr0 = r->tpr0; - p.tpr1 = r->tpr1; - p.tpr2 = r->tpr2; - p.tpr3 = ((((r->dllcr[0]) >> 6) & 0x3f) << 16) | - ((((r->dllcr[1]) >> 14) & 0xf) << 0) | - ((((r->dllcr[2]) >> 14) & 0xf) << 4) | - ((((r->dllcr[3]) >> 14) & 0xf) << 8) | - ((((r->dllcr[4]) >> 14) & 0xf) << 12); - p.emr1 = r->emr; - p.emr2 = r->emr2; - p.emr3 = r->emr3; - p.type = (r->dcr & 0x1 ? 3 : 2); - p.odt_en = (r->iocr & 0x3); - p.zq = (r->zqcr0 & 0xf0000000)+(r->zqcr0 >> 20 & 0xff)+((r->zqcr0 & 0xfffff) << 8); - p.cas = (r->mr >> 4 & 15); - if (p.type == 3) - p.cas += 4; - p.density = 1 << 8+(r->dcr >> 3 & 7); - p.rank_num = (r->dcr >> 10 & 3)+1; - p.io_width = (r->dcr >> 1 & 3) << 3; - p.bus_width = ((r->dcr >> 6 & 3)+1) << 3; - /* - * The clock for DDR is calculated as: - * (24 MHz * N * K) / M - * PLL5 has a second output port isn't interesting for memory info, - * but is calculated as: - * (24 MHz * N * K) / P - */ - p.clock = (24 * - ((ccm->pll5_cfg >> CCM_PLL5_FACTOR_N) & CCM_PLL5_FACTOR_N_SIZE) * - (((ccm->pll5_cfg >> CCM_PLL5_FACTOR_K) & CCM_PLL5_FACTOR_K_SIZE) + 1) / - (((ccm->pll5_cfg >> CCM_PLL5_FACTOR_M) & CCM_PLL5_FACTOR_M_SIZE) + 1) - ); - - /* Print dram_para struct */ - printf("dram_clk = %d\n", p.clock); - printf("dram_type = %d\n", p.type); - printf("dram_rank_num = %d\n", p.rank_num); - printf("dram_chip_density = %d\n", p.density); - printf("dram_io_width = %d\n", p.io_width); - printf("dram_bus_width = %d\n", p.bus_width); - printf("dram_cas = %d\n", p.cas); - printf("dram_zq = 0x%x\n", p.zq); - printf("dram_odt_en = %d\n", p.odt_en); - //printf("dram_size = %d\n", p.size); - printf("dram_tpr0 = 0x%x\n", p.tpr0); - printf("dram_tpr1 = 0x%x\n", p.tpr1); - printf("dram_tpr2 = 0x%x\n", p.tpr2); - printf("dram_tpr3 = 0x%x\n", p.tpr3); - printf("dram_emr1 = 0x%x\n", p.emr1); - printf("dram_emr2 = 0x%x\n", p.emr2); - printf("dram_emr3 = 0x%x\n", p.emr3); - - /* Clean up */ - munmap((void *)r, 4096); - munmap((void *)ccm, 4096); - close(mem_fd); - return 0; -} - diff --git a/meminfo.c b/meminfo.c new file mode 100644 index 0000000..4455bc0 --- /dev/null +++ b/meminfo.c @@ -0,0 +1,288 @@ +/* + * A10-meminfo + * Dumps DRAM controller settings + * + * Author: Floris Bos + * License: GPL + * + * Compile with: gcc -static -o a10-meminfo-static a10-meminfo.c + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <dirent.h> +#include <fcntl.h> +#include <assert.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdint.h> + +#define SUNXI_DRAMC_BASE 0x01c01000 +#define SUNXI_CCM_BASE 0x01C20000 + +#define CCM_PLL5_FACTOR_M 0 +#define CCM_PLL5_FACTOR_K 4 +#define CCM_PLL5_FACTOR_N 8 +#define CCM_PLL5_FACTOR_P 16 + +#define CCM_PLL5_FACTOR_M_SIZE 0x03 +#define CCM_PLL5_FACTOR_K_SIZE 0x03 +#define CCM_PLL5_FACTOR_N_SIZE 0x1f +#define CCM_PLL5_FACTOR_P_SIZE 0x03 + +typedef uint32_t u32; +typedef uint8_t u8; + +/* + * Memory header definition copied from u-boot arch/arm/include/asm/arch-sunxi/dram.h + * (C) Copyright 2007-2012 Allwinner Technology Co., Ltd. <www.allwinnertech.com>) + */ +struct sunxi_dram_reg { + u32 ccr; /* 0x00 controller configuration register */ + u32 dcr; /* 0x04 dram configuration register */ + u32 iocr; /* 0x08 i/o configuration register */ + u32 csr; /* 0x0c controller status register */ + u32 drr; /* 0x10 dram refresh register */ + u32 tpr0; /* 0x14 dram timing parameters register 0 */ + u32 tpr1; /* 0x18 dram timing parameters register 1 */ + u32 tpr2; /* 0x1c dram timing parameters register 2 */ + u32 gdllcr; /* 0x20 global dll control register */ + u8 res0[0x28]; + u32 rslr0; /* 0x4c rank system latency register */ + u32 rslr1; /* 0x50 rank system latency register */ + u8 res1[0x8]; + u32 rdgr0; /* 0x5c rank dqs gating register */ + u32 rdgr1; /* 0x60 rank dqs gating register */ + u8 res2[0x34]; + u32 odtcr; /* 0x98 odt configuration register */ + u32 dtr0; /* 0x9c data training register 0 */ + u32 dtr1; /* 0xa0 data training register 1 */ + u32 dtar; /* 0xa4 data training address register */ + u32 zqcr0; /* 0xa8 zq control register 0 */ + u32 zqcr1; /* 0xac zq control register 1 */ + u32 zqsr; /* 0xb0 zq status register */ + u32 idcr; /* 0xb4 initializaton delay configure reg */ + u8 res3[0x138]; + u32 mr; /* 0x1f0 mode register */ + u32 emr; /* 0x1f4 extended mode register */ + u32 emr2; /* 0x1f8 extended mode register */ + u32 emr3; /* 0x1fc extended mode register */ + u32 dllctr; /* 0x200 dll control register */ + u32 dllcr[5]; /* 0x204 dll control register 0(byte 0) */ + /* 0x208 dll control register 1(byte 1) */ + /* 0x20c dll control register 2(byte 2) */ + /* 0x210 dll control register 3(byte 3) */ + /* 0x214 dll control register 4(byte 4) */ + u32 dqtr0; /* 0x218 dq timing register */ + u32 dqtr1; /* 0x21c dq timing register */ + u32 dqtr2; /* 0x220 dq timing register */ + u32 dqtr3; /* 0x224 dq timing register */ + u32 dqstr; /* 0x228 dqs timing register */ + u32 dqsbtr; /* 0x22c dqsb timing register */ + u32 mcr; /* 0x230 mode configure register */ + u8 res[0x8]; + u32 reg_23c; /* 0x23c register description unknown!!! */ + u32 apr; /* 0x240 arbiter period register */ + u32 pldtr; /* 0x244 priority level data threshold reg */ + u8 res5[0x8]; + u32 hpcr[32]; /* 0x250 host port configure register */ + u8 res6[0x10]; + u32 csel; /* 0x2e0 controller select register */ +}; + +struct dram_para { + u32 baseaddr; + u32 clock; + u32 type; + u32 rank_num; + u32 density; + u32 io_width; + u32 bus_width; + u32 cas; + u32 zq; + u32 odt_en; + u32 size; + u32 tpr0; + u32 tpr1; + u32 tpr2; + u32 tpr3; + u32 tpr4; + u32 tpr5; + u32 emr1; + u32 emr2; + u32 emr3; +}; + +/* Clock control header copied from include/asm/arch-sunxi/clock.h */ +struct sunxi_ccm_reg { + u32 pll1_cfg; /* 0x00 pll1 control */ + u32 pll1_tun; /* 0x04 pll1 tuning */ + u32 pll2_cfg; /* 0x08 pll2 control */ + u32 pll2_tun; /* 0x0c pll2 tuning */ + u32 pll3_cfg; /* 0x10 pll3 control */ + u8 res0[0x4]; + u32 pll4_cfg; /* 0x18 pll4 control */ + u8 res1[0x4]; + u32 pll5_cfg; /* 0x20 pll5 control */ + u32 pll5_tun; /* 0x24 pll5 tuning */ + u32 pll6_cfg; /* 0x28 pll6 control */ + u32 pll6_tun; /* 0x2c pll6 tuning */ + u32 pll7_cfg; /* 0x30 pll7 control */ + u8 res2[0x4]; + u32 pll1_tun2; /* 0x38 pll5 tuning2 */ + u32 pll5_tun2; /* 0x3c pll5 tuning2 */ + u8 res3[0xc]; + u32 pll_lock_dbg; /* 0x4c pll lock time debug */ + u32 osc24m_cfg; /* 0x50 osc24m control */ + u32 cpu_ahb_apb0_cfg; /* 0x54 cpu,ahb and apb0 divide ratio */ + u32 apb1_clk_div_cfg; /* 0x58 apb1 clock dividor */ + u32 axi_gate; /* 0x5c axi module clock gating */ + u32 ahb_gate0; /* 0x60 ahb module clock gating 0 */ + u32 ahb_gate1; /* 0x64 ahb module clock gating 1 */ + u32 apb0_gate; /* 0x68 apb0 module clock gating */ + u32 apb1_gate; /* 0x6c apb1 module clock gating */ + u8 res4[0x10]; + u32 nand_sclk_cfg; /* 0x80 nand sub clock control */ + u32 ms_sclk_cfg; /* 0x84 memory stick sub clock control */ + u32 sd0_clk_cfg; /* 0x88 sd0 clock control */ + u32 sd1_clk_cfg; /* 0x8c sd1 clock control */ + u32 sd2_clk_cfg; /* 0x90 sd2 clock control */ + u32 sd3_clk_cfg; /* 0x94 sd3 clock control */ + u32 ts_clk_cfg; /* 0x98 transport stream clock control */ + u32 ss_clk_cfg; /* 0x9c */ + u32 spi0_clk_cfg; /* 0xa0 */ + u32 spi1_clk_cfg; /* 0xa4 */ + u32 spi2_clk_cfg; /* 0xa8 */ + u32 pata_clk_cfg; /* 0xac */ + u32 ir0_clk_cfg; /* 0xb0 */ + u32 ir1_clk_cfg; /* 0xb4 */ + u32 iis_clk_cfg; /* 0xb8 */ + u32 ac97_clk_cfg; /* 0xbc */ + u32 spdif_clk_cfg; /* 0xc0 */ + u32 keypad_clk_cfg; /* 0xc4 */ + u32 sata_clk_cfg; /* 0xc8 */ + u32 usb_clk_cfg; /* 0xcc */ + u32 gps_clk_cfg; /* 0xd0 */ + u32 spi3_clk_cfg; /* 0xd4 */ + u8 res5[0x28]; + u32 dram_clk_cfg; /* 0x100 */ + u32 be0_clk_cfg; /* 0x104 */ + u32 be1_clk_cfg; /* 0x108 */ + u32 fe0_clk_cfg; /* 0x10c */ + u32 fe1_clk_cfg; /* 0x110 */ + u32 mp_clk_cfg; /* 0x114 */ + u32 lcd0_ch0_clk_cfg; /* 0x118 */ + u32 lcd1_ch0_clk_cfg; /* 0x11c */ + u32 csi_isp_clk_cfg; /* 0x120 */ + u8 res6[0x4]; + u32 tvd_clk_reg; /* 0x128 */ + u32 lcd0_ch1_clk_cfg; /* 0x12c */ + u32 lcd1_ch1_clk_cfg; /* 0x130 */ + u32 csi0_clk_cfg; /* 0x134 */ + u32 csi1_clk_cfg; /* 0x138 */ + u32 ve_clk_cfg; /* 0x13c */ + u32 audio_codec_clk_cfg; /* 0x140 */ + u32 avs_clk_cfg; /* 0x144 */ + u32 ace_clk_cfg; /* 0x148 */ + u32 lvds_clk_cfg; /* 0x14c */ + u32 hdmi_clk_cfg; /* 0x150 */ + u32 mali_clk_cfg; /* 0x154 */ + u8 res7[0x4]; + u32 mbus_clk_cfg; /* 0x15c */ +}; + + +int mem_fd = -1; + +volatile unsigned *map_physical_memory(uint32_t addr, size_t len) +{ + volatile unsigned *mem; + + if (mem_fd == -1 && (mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) + { + perror("opening /dev/mem"); + exit(1); + } + + mem = (volatile unsigned *) mmap(NULL, len, PROT_READ, MAP_SHARED, mem_fd, (off_t) addr); + + if (mem == MAP_FAILED) + { + perror("mmap"); + exit (1); + } + + return mem; +} + + +int main(int argc, char **argv) +{ + volatile struct sunxi_dram_reg *r = (volatile struct sunxi_dram_reg *) map_physical_memory(SUNXI_DRAMC_BASE, 4096); + volatile struct sunxi_ccm_reg *ccm = (volatile struct sunxi_ccm_reg *) map_physical_memory(SUNXI_CCM_BASE, 4096); + struct dram_para p = {0}; + + /* Convert information found inside registers back to dram_para struct */ + p.tpr0 = r->tpr0; + p.tpr1 = r->tpr1; + p.tpr2 = r->tpr2; + p.tpr3 = ((((r->dllcr[0]) >> 6) & 0x3f) << 16) | + ((((r->dllcr[1]) >> 14) & 0xf) << 0) | + ((((r->dllcr[2]) >> 14) & 0xf) << 4) | + ((((r->dllcr[3]) >> 14) & 0xf) << 8) | + ((((r->dllcr[4]) >> 14) & 0xf) << 12); + p.emr1 = r->emr; + p.emr2 = r->emr2; + p.emr3 = r->emr3; + p.type = (r->dcr & 0x1 ? 3 : 2); + p.odt_en = (r->iocr & 0x3); + p.zq = (r->zqcr0 & 0xf0000000)+(r->zqcr0 >> 20 & 0xff)+((r->zqcr0 & 0xfffff) << 8); + p.cas = (r->mr >> 4 & 15); + if (p.type == 3) + p.cas += 4; + p.density = (1 << 8) + (r->dcr >> 3 & 7); + p.rank_num = (r->dcr >> 10 & 3)+1; + p.io_width = (r->dcr >> 1 & 3) << 3; + p.bus_width = ((r->dcr >> 6 & 3)+1) << 3; + /* + * The clock for DDR is calculated as: + * (24 MHz * N * K) / M + * PLL5 has a second output port isn't interesting for memory info, + * but is calculated as: + * (24 MHz * N * K) / P + */ + p.clock = (24 * + ((ccm->pll5_cfg >> CCM_PLL5_FACTOR_N) & CCM_PLL5_FACTOR_N_SIZE) * + (((ccm->pll5_cfg >> CCM_PLL5_FACTOR_K) & CCM_PLL5_FACTOR_K_SIZE) + 1) / + (((ccm->pll5_cfg >> CCM_PLL5_FACTOR_M) & CCM_PLL5_FACTOR_M_SIZE) + 1) + ); + + /* Print dram_para struct */ + printf("dram_clk = %d\n", p.clock); + printf("dram_type = %d\n", p.type); + printf("dram_rank_num = %d\n", p.rank_num); + printf("dram_chip_density = %d\n", p.density); + printf("dram_io_width = %d\n", p.io_width); + printf("dram_bus_width = %d\n", p.bus_width); + printf("dram_cas = %d\n", p.cas); + printf("dram_zq = 0x%x\n", p.zq); + printf("dram_odt_en = %d\n", p.odt_en); + //printf("dram_size = %d\n", p.size); + printf("dram_tpr0 = 0x%x\n", p.tpr0); + printf("dram_tpr1 = 0x%x\n", p.tpr1); + printf("dram_tpr2 = 0x%x\n", p.tpr2); + printf("dram_tpr3 = 0x%x\n", p.tpr3); + printf("dram_emr1 = 0x%x\n", p.emr1); + printf("dram_emr2 = 0x%x\n", p.emr2); + printf("dram_emr3 = 0x%x\n", p.emr3); + + /* Clean up */ + munmap((void *)r, 4096); + munmap((void *)ccm, 4096); + close(mem_fd); + return 0; +} + -- 1.7.7 -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.