全志 DDR初始化 v3s
-
看了全志的DRAM,在手册里(包括Allwinner_V3s_User_Manual_V1.0)根本没有REG描述。
难道用全志的芯片这么折磨人吗。
看中V3S的内置DDR才选用,但现在DRAM根本不提怎么初始化。
大佬们谁有方法,帮一把,小弟跪求。 -
DRAM寄存器
#define S3_DRAM_COM_BASE (0x01c62000) #define S3_DRAM_CTL_BASE (0x01c63000) #define MCTL_CR_BL8 (0x4 << 20) #define MCTL_CR_1T (0x1 << 19) #define MCTL_CR_2T (0x0 << 19) #define MCTL_CR_LPDDR3 (0x7 << 16) #define MCTL_CR_LPDDR2 (0x6 << 16) #define MCTL_CR_DDR3 (0x3 << 16) #define MCTL_CR_DDR2 (0x2 << 16) #define MCTL_CR_SEQUENTIAL (0x1 << 15) #define MCTL_CR_INTERLEAVED (0x0 << 15) #define MCTL_CR_32BIT (0x1 << 12) #define MCTL_CR_16BIT (0x0 << 12) #define MCTL_CR_BUS_WIDTH(x) ((x) == 32 ? MCTL_CR_32BIT : MCTL_CR_16BIT) #define MCTL_CR_PAGE_SIZE(x) ((gfls(x) - 4) << 8) #define MCTL_CR_ROW_BITS(x) (((x) - 1) << 4) #define MCTL_CR_EIGHT_BANKS (0x1 << 2) #define MCTL_CR_FOUR_BANKS (0x0 << 2) #define MCTL_CR_DUAL_RANK (0x1 << 0) #define MCTL_CR_SINGLE_RANK (0x0 << 0) #define DRAMTMG0_TWTP(x) ((x) << 24) #define DRAMTMG0_TFAW(x) ((x) << 16) #define DRAMTMG0_TRAS_MAX(x) ((x) << 8) #define DRAMTMG0_TRAS(x) ((x) << 0) #define DRAMTMG1_TXP(x) ((x) << 16) #define DRAMTMG1_TRTP(x) ((x) << 8) #define DRAMTMG1_TRC(x) ((x) << 0) #define DRAMTMG2_TCWL(x) ((x) << 24) #define DRAMTMG2_TCL(x) ((x) << 16) #define DRAMTMG2_TRD2WR(x) ((x) << 8) #define DRAMTMG2_TWR2RD(x) ((x) << 0) #define DRAMTMG3_TMRW(x) ((x) << 16) #define DRAMTMG3_TMRD(x) ((x) << 12) #define DRAMTMG3_TMOD(x) ((x) << 0) #define DRAMTMG4_TRCD(x) ((x) << 24) #define DRAMTMG4_TCCD(x) ((x) << 16) #define DRAMTMG4_TRRD(x) ((x) << 8) #define DRAMTMG4_TRP(x) ((x) << 0) #define DRAMTMG5_TCKSRX(x) ((x) << 24) #define DRAMTMG5_TCKSRE(x) ((x) << 16) #define DRAMTMG5_TCKESR(x) ((x) << 8) #define DRAMTMG5_TCKE(x) ((x) << 0) #define PTR3_TDINIT1(x) ((x) << 20) #define PTR3_TDINIT0(x) ((x) << 0) #define PTR4_TDINIT3(x) ((x) << 20) #define PTR4_TDINIT2(x) ((x) << 0) #define RFSHTMG_TREFI(x) ((x) << 16) #define RFSHTMG_TRFC(x) ((x) << 0) #define PIR_CLRSR (0x1 << 27) /* Clear status registers */ #define PIR_QSGATE (0x1 << 10) /* Read DQS gate training */ #define PIR_DRAMINIT (0x1 << 8) /* DRAM initialization */ #define PIR_DRAMRST (0x1 << 7) /* DRAM reset */ #define PIR_PHYRST (0x1 << 6) /* PHY reset */ #define PIR_DCAL (0x1 << 5) /* DDL calibration */ #define PIR_PLLINIT (0x1 << 4) /* PLL initialization */ #define PIR_ZCAL (0x1 << 1) /* ZQ calibration */ #define PIR_INIT (0x1 << 0) /* PHY initialization trigger */ #define PGSR_INIT_DONE (0x1 << 0) /* PHY init done */ #define ZQCR_PWRDOWN (0x1 << 31) /* ZQ power down */ #define DATX_IOCR_DQ(x) (x) #define DATX_IOCR_DM (8) #define DATX_IOCR_DQS (9) #define DATX_IOCR_DQSN (10) #define DATX_IOCR_WRITE_DELAY(x) ((x) << 8) #define DATX_IOCR_READ_DELAY(x) ((x) << 0)
时钟寄存器
#define S3_CCU_BASE (0x01c20000) #define CCU_PLL_CPU_CTRL (0x000) #define CCU_PLL_AUDIO_CTRL (0x008) #define CCU_PLL_VIDEO_CTRL (0x010) #define CCU_PLL_VE_CTRL (0x018) #define CCU_PLL_DDR0_CTRL (0x020) #define CCU_PLL_PERIPH0_CTRL (0x028) #define CCU_PLL_ISP_CTRL (0x02c) #define CCU_PLL_PERIPH1_CTRL (0x044) #define CCU_PLL_DDR1_CTRL (0x04c) #define CCU_CPU_AXI_CFG (0x050) #define CCU_AHB_APB0_CFG (0x054) #define CCU_APB1_CFG (0x058) #define CCU_AHB2_CFG (0x05c) #define CCU_BUS_CLK_GATE0 (0x060) #define CCU_BUS_CLK_GATE1 (0x064) #define CCU_BUS_CLK_GATE2 (0x068) #define CCU_BUS_CLK_GATE3 (0x06c) #define CCU_BUS_CLK_GATE4 (0x070) #define CCU_SDMMC0_CLK (0x088) #define CCU_SDMMC1_CLK (0x08c) #define CCU_SDMMC2_CLK (0x090) #define CCU_CE_CLK (0x09c) #define CCU_SPI0_CLK (0x0a0) #define CCU_USBPHY_CFG (0x0cc) #define CCU_DRAM_CFG (0x0f4) #define CCU_PLL_DDR1_CFG (0x0f8) #define CCU_MBUS_RST (0x0fc) #define CCU_DRAM_CLK_GATE (0x100) #define CCU_TCON_CLK (0x118) #define CCU_CSI_MISC_CLK (0x130) #define CCU_CSI_CLK (0x134) #define CCU_VE_CLK (0x13c) #define CCU_AC_DIG_CLK (0x140) #define CCU_AVS_CLK (0x144) #define CCU_MBUS_CLK (0x15c) #define CCU_MIPI_CSI_CLK (0x16c) #define CCU_PLL_STABLE_TIME0 (0x200) #define CCU_PLL_STABLE_TIME1 (0x204) #define CCU_PLL_CPU_BIAS (0x220) #define CCU_PLL_AUDIO_BIAS (0x224) #define CCU_PLL_VIDEO_BIAS (0x228) #define CCU_PLL_VE_BIAS (0x22c) #define CCU_PLL_DDR0_BIAS (0x230) #define CCU_PLL_PERIPH0_BIAS (0x234) #define CCU_PLL_ISP_BIAS (0x238) #define CCU_PLL_PERIPH1_BIAS (0x244) #define CCU_PLL_DDR1_BIAS (0x24C) #define CCU_PLL_CPU_TUN (0x250) #define CCU_PLL_DDR0_TUN (0x260) #define CCU_PLL_CPU_PAT (0x280) #define CCU_PLL_AUDIO_PAT (0x284) #define CCU_PLL_VIDEO_PAT (0x288) #define CCU_PLL_VE_PAT (0x28c) #define CCU_PLL_DDR0_PAT (0x290) #define CCU_PLL_ISP_PAT (0x298) #define CCU_PLL_PERIPH1_PAT (0x2a4) #define CCU_PLL_DDR1_PAT0 (0x2ac) #define CCU_PLL_DDR1_PAT1 (0x2b0) #define CCU_BUS_SOFT_RST0 (0x2c0) #define CCU_BUS_SOFT_RST1 (0x2c4) #define CCU_BUS_SOFT_RST2 (0x2c8) #define CCU_BUS_SOFT_RST3 (0x2d0) #define CCU_BUS_SOFT_RST4 (0x2d8) #define CCU_PS_CTRL (0x300) #define CCU_PS_CNT (0x304)
驱动
#include <reg-ccu.h> #include <reg-dram.h> #define CONFIG_DRAM_BASE (0x40000000) #define CONFIG_DRAM_CLK (360) #define CONFIG_DRAM_ZQ (14779) #define clrbits_le32(addr, clear) \ write32(((virtual_addr_t)(addr)), read32(((virtual_addr_t)(addr))) & ~(clear)) #define setbits_le32(addr, set) \ write32(((virtual_addr_t)(addr)), read32(((virtual_addr_t)(addr))) | (set)) #define clrsetbits_le32(addr, clear, set) \ write32(((virtual_addr_t)(addr)), (read32(((virtual_addr_t)(addr))) & ~(clear)) | (set)) #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) #define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) struct s3_dram_com_reg_t { u32_t cr; /* 0x00 control register */ u8_t res0[0xc]; /* 0x04 */ u32_t mcr[16][2]; /* 0x10 */ u32_t bwcr; /* 0x90 bandwidth control register */ u32_t maer; /* 0x94 master enable register */ u32_t mapr; /* 0x98 master priority register */ u32_t mcgcr; /* 0x9c */ u32_t cpu_bwcr; /* 0xa0 */ u32_t gpu_bwcr; /* 0xa4 */ u32_t ve_bwcr; /* 0xa8 */ u32_t disp_bwcr; /* 0xac */ u32_t other_bwcr; /* 0xb0 */ u32_t total_bwcr; /* 0xb4 */ u8_t res1[0x8]; /* 0xb8 */ u32_t swonr; /* 0xc0 */ u32_t swoffr; /* 0xc4 */ u8_t res2[0x8]; /* 0xc8 */ u32_t cccr; /* 0xd0 */ u8_t res3[0x72c]; /* 0xd4 */ u32_t protect; /* 0x800 */ }; struct s3_dram_ctl_reg_t { u32_t pir; /* 0x00 PHY initialization register */ u32_t pwrctl; /* 0x04 */ u32_t mrctrl; /* 0x08 */ u32_t clken; /* 0x0c */ u32_t pgsr[2]; /* 0x10 PHY general status registers */ u32_t statr; /* 0x18 */ u8_t res1[0x14]; /* 0x1c */ u32_t mr[4]; /* 0x30 mode registers */ u32_t pllgcr; /* 0x40 */ u32_t ptr[5]; /* 0x44 PHY timing registers */ u32_t dramtmg[9]; /* 0x58 DRAM timing registers */ u32_t odtcfg; /* 0x7c */ u32_t pitmg[2]; /* 0x80 PHY interface timing registers */ u8_t res2[0x4]; /* 0x88 */ u32_t rfshctl0; /* 0x8c */ u32_t rfshtmg; /* 0x90 refresh timing */ u32_t rfshctl1; /* 0x94 */ u32_t pwrtmg; /* 0x98 */ u8_t res3[0x20]; /* 0x9c */ u32_t dqsgmr; /* 0xbc */ u32_t dtcr; /* 0xc0 */ u32_t dtar[4]; /* 0xc4 */ u32_t dtdr[2]; /* 0xd4 */ u32_t dtmr[2]; /* 0xdc */ u32_t dtbmr; /* 0xe4 */ u32_t catr[2]; /* 0xe8 */ u32_t dtedr[2]; /* 0xf0 */ u8_t res4[0x8]; /* 0xf8 */ u32_t pgcr[4]; /* 0x100 PHY general configuration registers */ u32_t iovcr[2]; /* 0x110 */ u32_t dqsdr; /* 0x118 */ u32_t dxccr; /* 0x11c */ u32_t odtmap; /* 0x120 */ u32_t zqctl[2]; /* 0x124 */ u8_t res6[0x14]; /* 0x12c */ u32_t zqcr; /* 0x140 ZQ control register */ u32_t zqsr; /* 0x144 ZQ status register */ u32_t zqdr[3]; /* 0x148 ZQ data registers */ u8_t res7[0x6c]; /* 0x154 */ u32_t sched; /* 0x1c0 */ u32_t perfhpr[2]; /* 0x1c4 */ u32_t perflpr[2]; /* 0x1cc */ u32_t perfwr[2]; /* 0x1d4 */ u8_t res8[0x2c]; /* 0x1dc */ u32_t aciocr; /* 0x208 */ u8_t res9[0xf4]; /* 0x20c */ struct { /* 0x300 DATX8 modules*/ u32_t mdlr; /* 0x00 */ u32_t lcdlr[3]; /* 0x04 */ u32_t iocr[11]; /* 0x10 IO configuration register */ u32_t bdlr6; /* 0x3c */ u32_t gtr; /* 0x40 */ u32_t gcr; /* 0x44 */ u32_t gsr[3]; /* 0x48 */ u8_t res0[0x2c];/* 0x54 */ } datx[4]; u8_t res10[0x388]; /* 0x500 */ u32_t upd2; /* 0x888 */ }; struct dram_para_t { u32_t read_delays; u32_t write_delays; u16_t page_size; u8_t bus_width; u8_t dual_rank; u8_t row_bits; u8_t bank_bits; }; static inline void sdelay(int loops) { __asm__ __volatile__ ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0"(loops)); } static inline int gfls(int x) { int r = 32; if(!x) return 0; if(!(x & 0xffff0000u)) { x <<= 16; r -= 16; } if(!(x & 0xff000000u)) { x <<= 8; r -= 8; } if(!(x & 0xf0000000u)) { x <<= 4; r -= 4; } if(!(x & 0xc0000000u)) { x <<= 2; r -= 2; } if(!(x & 0x80000000u)) { x <<= 1; r -= 1; } return r; } static inline int ns_to_t(int ns) { unsigned int freq = CONFIG_DRAM_CLK / 2; return DIV_ROUND_UP(freq * ns, 1000); } static u32_t bin_to_mgray(int val) { u8_t table[32]; table[0] = 0x00; table[1] = 0x01; table[2] = 0x02; table[3] = 0x03; table[4] = 0x06; table[5] = 0x07; table[6] = 0x04; table[7] = 0x05; table[8] = 0x0c; table[9] = 0x0d; table[10] = 0x0e; table[11] = 0x0f; table[12] = 0x0a; table[13] = 0x0b; table[14] = 0x08; table[15] = 0x09; table[16] = 0x18; table[17] = 0x19; table[18] = 0x1a; table[19] = 0x1b; table[20] = 0x1e; table[21] = 0x1f; table[22] = 0x1c; table[23] = 0x1d; table[24] = 0x14; table[25] = 0x15; table[26] = 0x16; table[27] = 0x17; table[28] = 0x12; table[29] = 0x13; table[30] = 0x10; table[31] = 0x11; return table[clamp(val, 0, 31)]; } static int mgray_to_bin(u32_t val) { u8_t table[32]; table[0] = 0x00; table[1] = 0x01; table[2] = 0x02; table[3] = 0x03; table[4] = 0x06; table[5] = 0x07; table[6] = 0x04; table[7] = 0x05; table[8] = 0x0e; table[9] = 0x0f; table[10] = 0x0c; table[11] = 0x0d; table[12] = 0x08; table[13] = 0x09; table[14] = 0x0a; table[15] = 0x0b; table[16] = 0x1e; table[17] = 0x1f; table[18] = 0x1c; table[19] = 0x1d; table[20] = 0x18; table[21] = 0x19; table[22] = 0x1a; table[23] = 0x1b; table[24] = 0x10; table[25] = 0x11; table[26] = 0x12; table[27] = 0x13; table[28] = 0x16; table[29] = 0x17; table[30] = 0x14; table[31] = 0x15; return table[val & 0x1f]; } static void clock_set_pll_ddr(u32_t clk) { int n = 32; int k = 1; int m = 2; u32_t val; /* ddr pll rate = 24000000 * n * k / m */ if(clk > 24000000 * k * n / m) { m = 1; if(clk > 24000000 * k * n / m) { k = 2; } } val = (0x1 << 31); val |= (0x0 << 24); val |= (0x1 << 20); val |= ((((clk / (24000000 * k / m)) - 1) & 0x1f) << 8); val |= (((k - 1) & 0x3) << 4); val |= (((m - 1) & 0x3) << 0); write32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL, val); sdelay(5500); } static void mctl_await_completion(u32_t * reg, u32_t mask, u32_t val) { int timeout = 0; while((read32((virtual_addr_t)reg) & mask) != val) { if(timeout++ > 10000) break; } } static int mctl_mem_matches(u32_t offset) { write32(CONFIG_DRAM_BASE, 0); write32(CONFIG_DRAM_BASE + offset, 0xaa55aa55); __asm__ __volatile__ ("dsb" : : : "memory"); return (read32(CONFIG_DRAM_BASE) == read32(CONFIG_DRAM_BASE + offset)) ? 1 : 0; } static void mctl_phy_init(u32_t val) { struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; write32((virtual_addr_t)&ctl->pir, val | PIR_INIT); mctl_await_completion(&ctl->pgsr[0], PGSR_INIT_DONE, 0x1); } static void mctl_dq_delay(u32_t read, u32_t write) { struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; int i, j; u32_t val; for(i = 0; i < 4; i++) { val = DATX_IOCR_WRITE_DELAY((write >> (i * 4)) & 0xf) | DATX_IOCR_READ_DELAY(((read >> (i * 4)) & 0xf) * 2); for(j = DATX_IOCR_DQ(0); j <= DATX_IOCR_DM; j++) write32((virtual_addr_t)&ctl->datx[i].iocr[j], val); } clrbits_le32(&ctl->pgcr[0], 1 << 26); for(i = 0; i < 4; i++) { val = DATX_IOCR_WRITE_DELAY((write >> (16 + i * 4)) & 0xf) | DATX_IOCR_READ_DELAY((read >> (16 + i * 4)) & 0xf); write32((virtual_addr_t)&ctl->datx[i].iocr[DATX_IOCR_DQS], val); write32((virtual_addr_t)&ctl->datx[i].iocr[DATX_IOCR_DQSN], val); } setbits_le32(&ctl->pgcr[0], 1 << 26); sdelay(1); } static void mctl_set_master_priority(void) { struct s3_dram_com_reg_t * com = (struct s3_dram_com_reg_t *)S3_DRAM_COM_BASE; write32((virtual_addr_t)&com->bwcr, 0x00010190); write32((virtual_addr_t)&com->mapr, 0x00000001); write32((virtual_addr_t)&com->mcr[0][0], 0x0200000d); write32((virtual_addr_t)&com->mcr[0][1], 0x00800100); write32((virtual_addr_t)&com->mcr[1][0], 0x06000009); write32((virtual_addr_t)&com->mcr[1][1], 0x01000400); write32((virtual_addr_t)&com->mcr[2][0], 0x0200000d); write32((virtual_addr_t)&com->mcr[2][1], 0x00600100); write32((virtual_addr_t)&com->mcr[3][0], 0x0100000d); write32((virtual_addr_t)&com->mcr[3][1], 0x00200080); write32((virtual_addr_t)&com->mcr[4][0], 0x07000009); write32((virtual_addr_t)&com->mcr[4][1], 0x01000640); write32((virtual_addr_t)&com->mcr[5][0], 0x0100000d); write32((virtual_addr_t)&com->mcr[5][1], 0x00200080); write32((virtual_addr_t)&com->mcr[6][0], 0x01000009); write32((virtual_addr_t)&com->mcr[6][1], 0x00400080); write32((virtual_addr_t)&com->mcr[7][0], 0x0100000d); write32((virtual_addr_t)&com->mcr[7][1], 0x00400080); write32((virtual_addr_t)&com->mcr[8][0], 0x0100000d); write32((virtual_addr_t)&com->mcr[8][1], 0x00400080); write32((virtual_addr_t)&com->mcr[9][0], 0x04000009); write32((virtual_addr_t)&com->mcr[9][1], 0x00400100); write32((virtual_addr_t)&com->mcr[10][0], 0x2000030d); write32((virtual_addr_t)&com->mcr[10][1], 0x04001800); write32((virtual_addr_t)&com->mcr[11][0], 0x04000009); write32((virtual_addr_t)&com->mcr[11][1], 0x00400120); } static void mctl_set_timing_params(struct dram_para_t * para) { struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; u8_t tccd = 2; u8_t tfaw = ns_to_t(50); u8_t trrd = max(ns_to_t(10), 4); u8_t trcd = ns_to_t(15); u8_t trc = ns_to_t(53); u8_t txp = max(ns_to_t(8), 3); u8_t twtr = max(ns_to_t(8), 4); u8_t trtp = max(ns_to_t(8), 4); u8_t twr = max(ns_to_t(15), 3); u8_t trp = ns_to_t(15); u8_t tras = ns_to_t(38); u16_t trefi = ns_to_t(7800) / 32; u16_t trfc = ns_to_t(350); u8_t tmrw = 0; u8_t tmrd = 4; u8_t tmod = 12; u8_t tcke = 3; u8_t tcksrx = 5; u8_t tcksre = 5; u8_t tckesr = 4; u8_t trasmax = 24; u8_t tcl = 6; /* CL 12 */ u8_t tcwl = 4; /* CWL 8 */ u8_t t_rdata_en = 4; u8_t wr_latency = 2; u32_t tdinit0 = (500 * CONFIG_DRAM_CLK) + 1; /* 500us */ u32_t tdinit1 = (360 * CONFIG_DRAM_CLK) / 1000 + 1; /* 360ns */ u32_t tdinit2 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */ u32_t tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */ u8_t twtp = tcwl + 2 + twr; /* WL + BL / 2 + tWR */ u8_t twr2rd = tcwl + 2 + twtr; /* WL + BL / 2 + tWTR */ u8_t trd2wr = tcl + 2 + 1 - tcwl; /* RL + BL / 2 + 2 - WL */ write32((virtual_addr_t)&ctl->mr[0], 0x1c70); /* CL=11, WR=12 */ write32((virtual_addr_t)&ctl->mr[1], 0x40); write32((virtual_addr_t)&ctl->mr[2], 0x18); /* CWL=8 */ write32((virtual_addr_t)&ctl->mr[3], 0x0); /* Set DRAM timing */ write32((virtual_addr_t)&ctl->dramtmg[0], DRAMTMG0_TWTP(twtp) | DRAMTMG0_TFAW(tfaw) | DRAMTMG0_TRAS_MAX(trasmax) | DRAMTMG0_TRAS(tras)); write32((virtual_addr_t)&ctl->dramtmg[1], DRAMTMG1_TXP(txp) | DRAMTMG1_TRTP(trtp) | DRAMTMG1_TRC(trc)); write32((virtual_addr_t)&ctl->dramtmg[2], DRAMTMG2_TCWL(tcwl) | DRAMTMG2_TCL(tcl) | DRAMTMG2_TRD2WR(trd2wr) | DRAMTMG2_TWR2RD(twr2rd)); write32((virtual_addr_t)&ctl->dramtmg[3], DRAMTMG3_TMRW(tmrw) | DRAMTMG3_TMRD(tmrd) | DRAMTMG3_TMOD(tmod)); write32((virtual_addr_t)&ctl->dramtmg[4], DRAMTMG4_TRCD(trcd) | DRAMTMG4_TCCD(tccd) | DRAMTMG4_TRRD(trrd) | DRAMTMG4_TRP(trp)); write32((virtual_addr_t)&ctl->dramtmg[5], DRAMTMG5_TCKSRX(tcksrx) | DRAMTMG5_TCKSRE(tcksre) | DRAMTMG5_TCKESR(tckesr) | DRAMTMG5_TCKE(tcke)); /* Set two rank timing */ clrsetbits_le32(&ctl->dramtmg[8], (0xff << 8) | (0xff << 0), (0x66 << 8) | (0x10 << 0)); /* Set PHY interface timing, write latency and read latency configure */ write32((virtual_addr_t)&ctl->pitmg[0], (0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8) | (wr_latency << 0)); /* Set PHY timing, PTR0-2 use default */ write32((virtual_addr_t)&ctl->ptr[3], PTR3_TDINIT0(tdinit0) | PTR3_TDINIT1(tdinit1)); write32((virtual_addr_t)&ctl->ptr[4], PTR4_TDINIT2(tdinit2) | PTR4_TDINIT3(tdinit3)); /* Set refresh timing */ write32((virtual_addr_t)&ctl->rfshtmg, RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc)); } static void mctl_zq_calibration(struct dram_para_t * para) { struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; u16_t zq_val[6]; u32_t val; u8_t zq; int i; if(((read32(0x01c00000 + 0x24) & 0xff) == 0) && ((read32(0x01c00000 + 0xf0) & 0x1) == 0)) { clrsetbits_le32(&ctl->zqcr, 0xffff, CONFIG_DRAM_ZQ & 0xffff); write32((virtual_addr_t)&ctl->pir, PIR_CLRSR); mctl_phy_init(PIR_ZCAL); val = read32((virtual_addr_t)&ctl->zqdr[0]); val &= (0x1f << 16) | (0x1f << 0); val |= val << 8; write32((virtual_addr_t)&ctl->zqdr[0], val); val = read32((virtual_addr_t)&ctl->zqdr[1]); val &= (0x1f << 16) | (0x1f << 0); val |= val << 8; write32((virtual_addr_t)&ctl->zqdr[1], val); write32((virtual_addr_t)&ctl->zqdr[2], val); } else { write32((virtual_addr_t)&ctl->zqdr[2], 0x0a0a0a0a); for(i = 0; i < 6; i++) { zq = (CONFIG_DRAM_ZQ >> (i * 4)) & 0xf; write32((virtual_addr_t)&ctl->zqcr, (zq << 20) | (zq << 16) | (zq << 12) | (zq << 8) | (zq << 4) | (zq << 0)); write32((virtual_addr_t)&ctl->pir, PIR_CLRSR); mctl_phy_init(PIR_ZCAL); zq_val[i] = read32((virtual_addr_t)&ctl->zqdr[0]) & 0xff; write32((virtual_addr_t)&ctl->zqdr[2], REPEAT_BYTE(zq_val[i])); write32((virtual_addr_t)&ctl->pir, PIR_CLRSR); mctl_phy_init(PIR_ZCAL); val = read32((virtual_addr_t)&ctl->zqdr[0]) >> 24; zq_val[i] |= bin_to_mgray(mgray_to_bin(val) - 1) << 8; } write32((virtual_addr_t)&ctl->zqdr[0], (zq_val[1] << 16) | zq_val[0]); write32((virtual_addr_t)&ctl->zqdr[1], (zq_val[3] << 16) | zq_val[2]); write32((virtual_addr_t)&ctl->zqdr[2], (zq_val[5] << 16) | zq_val[4]); } } static void mctl_set_cr(struct dram_para_t * para) { struct s3_dram_com_reg_t * com = (struct s3_dram_com_reg_t *)S3_DRAM_COM_BASE; write32((virtual_addr_t)&com->cr, MCTL_CR_BL8 | MCTL_CR_2T | MCTL_CR_DDR3 | MCTL_CR_EIGHT_BANKS | MCTL_CR_BUS_WIDTH(para->bus_width) | MCTL_CR_INTERLEAVED | (para->dual_rank ? MCTL_CR_DUAL_RANK : MCTL_CR_SINGLE_RANK) | MCTL_CR_PAGE_SIZE(para->page_size) | MCTL_CR_ROW_BITS(para->row_bits)); } static void mctl_sys_init(struct dram_para_t * para) { struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; u32_t val; val = read32(S3_CCU_BASE + CCU_MBUS_CLK); val &= ~(0x1 << 31); write32(S3_CCU_BASE + CCU_MBUS_CLK, val); val = read32(S3_CCU_BASE + CCU_MBUS_RST); val &= ~(0x1 << 31); write32(S3_CCU_BASE + CCU_MBUS_RST, val); val = read32(S3_CCU_BASE + CCU_BUS_CLK_GATE0); val &= ~(0x1 << 14); write32(S3_CCU_BASE + CCU_BUS_CLK_GATE0, val); val = read32(S3_CCU_BASE + CCU_BUS_SOFT_RST0); val &= ~(0x1 << 14); write32(S3_CCU_BASE + CCU_BUS_SOFT_RST0, val); val = read32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL); val &= ~(0x1 << 31); write32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL, val); sdelay(10); val = read32(S3_CCU_BASE + CCU_DRAM_CLK_GATE); val &= ~(0x1 << 31); write32(S3_CCU_BASE + CCU_DRAM_CLK_GATE, val); sdelay(1000); clock_set_pll_ddr(CONFIG_DRAM_CLK * 2 * 1000000); val = read32(S3_CCU_BASE + CCU_DRAM_CFG); val &= ~(0xf << 0); val &= ~(0x3 << 20); val |= ((1 - 1) << 0); val |= (0x0 << 20); val |= (0x1 << 16); write32(S3_CCU_BASE + CCU_DRAM_CFG, val); mctl_await_completion((u32_t *)(S3_CCU_BASE + CCU_DRAM_CFG), 0x1 << 16, 0); val = read32(S3_CCU_BASE + CCU_BUS_SOFT_RST0); val |= (0x1 << 14); write32(S3_CCU_BASE + CCU_BUS_SOFT_RST0, val); val = read32(S3_CCU_BASE + CCU_BUS_CLK_GATE0); val |= (0x1 << 14); write32(S3_CCU_BASE + CCU_BUS_CLK_GATE0, val); val = read32(S3_CCU_BASE + CCU_MBUS_RST); val |= (0x1 << 31); write32(S3_CCU_BASE + CCU_MBUS_RST, val); val = read32(S3_CCU_BASE + CCU_MBUS_CLK); val |= (0x1 << 31); write32(S3_CCU_BASE + CCU_MBUS_CLK, val); val = read32(S3_CCU_BASE + CCU_DRAM_CFG); val |= (0x1 << 31); write32(S3_CCU_BASE + CCU_DRAM_CFG, val); sdelay(10); write32((virtual_addr_t)&ctl->clken, 0xc00e); sdelay(500); } static int mctl_channel_init(struct dram_para_t * para) { struct s3_dram_com_reg_t * com = (struct s3_dram_com_reg_t *)S3_DRAM_COM_BASE; struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; int i; mctl_set_cr(para); mctl_set_timing_params(para); mctl_set_master_priority(); clrbits_le32(&ctl->pgcr[0], (1 << 30) | 0x3f); clrsetbits_le32(&ctl->pgcr[1], 1 << 24, 1 << 26); write32((virtual_addr_t)&com->protect, 0x94be6fa3); sdelay(100); clrsetbits_le32(&ctl->upd2, 0xfff << 16, 0x50 << 16); write32((virtual_addr_t)&com->protect, 0x0); sdelay(100); for(i = 0; i < 4; i++) clrsetbits_le32(&ctl->datx[i].gcr, (0x3 << 4) | (0x1 << 1) | (0x3 << 2) | (0x3 << 12) | (0x3 << 14), 0x20); setbits_le32(&ctl->aciocr, 0x1 << 1); setbits_le32(&ctl->pgcr[2], 0x3 << 6); clrbits_le32(&ctl->pgcr[0], (0x3 << 14) | (0x3 << 12)); clrsetbits_le32(&ctl->pgcr[2], (0x3 << 10) | (0x3 << 8), (0x1 << 10) | (0x2 << 8)); if(para->bus_width != 32) { write32((virtual_addr_t)&ctl->datx[2].gcr, 0x0); write32((virtual_addr_t)&ctl->datx[3].gcr, 0x0); } clrsetbits_le32(&ctl->dtcr, 0xf << 24, (para->dual_rank ? 0x3 : 0x1) << 24); if(para->read_delays || para->write_delays) { mctl_dq_delay(para->read_delays, para->write_delays); sdelay(50); } mctl_zq_calibration(para); mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST | PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE); if(read32((virtual_addr_t)&ctl->pgsr[0]) & (0xfe << 20)) { if(((read32((virtual_addr_t)&ctl->datx[0].gsr[0]) >> 24) & 0x2) || ((read32((virtual_addr_t)&ctl->datx[1].gsr[0]) >> 24) & 0x2)) { clrsetbits_le32(&ctl->dtcr, 0xf << 24, 0x1 << 24); para->dual_rank = 0; } if(((read32((virtual_addr_t)&ctl->datx[2].gsr[0]) >> 24) & 0x1) || ((read32((virtual_addr_t)&ctl->datx[3].gsr[0]) >> 24) & 0x1)) { write32((virtual_addr_t)&ctl->datx[2].gcr, 0x0); write32((virtual_addr_t)&ctl->datx[3].gcr, 0x0); para->bus_width = 16; } mctl_set_cr(para); sdelay(20); mctl_phy_init(PIR_QSGATE); if(read32((virtual_addr_t)&ctl->pgsr[0]) & (0xfe << 20)) return 1; } mctl_await_completion(&ctl->statr, 0x1, 0x1); setbits_le32(&ctl->rfshctl0, 0x1 << 31); sdelay(10); clrbits_le32(&ctl->rfshctl0, 0x1 << 31); sdelay(10); write32((virtual_addr_t)&ctl->pgcr[3], 0x00aa0060); setbits_le32(&ctl->zqcr, ZQCR_PWRDOWN); write32((virtual_addr_t)&com->maer, 0xffffffff); return 0; } static void mctl_auto_detect_dram_size(struct dram_para_t * para) { para->page_size = 512; para->row_bits = 16; para->bank_bits = 2; mctl_set_cr(para); for(para->row_bits = 11; para->row_bits < 16; para->row_bits++) { if(mctl_mem_matches((1 << (para->row_bits + para->bank_bits)) * para->page_size)) break; } para->bank_bits = 3; mctl_set_cr(para); for(para->bank_bits = 2; para->bank_bits < 3; para->bank_bits++) { if(mctl_mem_matches((1 << para->bank_bits) * para->page_size)) break; } para->page_size = 8192; mctl_set_cr(para); for(para->page_size = 512; para->page_size < 8192; para->page_size *= 2) { if(mctl_mem_matches(para->page_size)) break; } } void sys_dram_init(void) { struct s3_dram_com_reg_t * com = (struct s3_dram_com_reg_t *)S3_DRAM_COM_BASE; struct s3_dram_ctl_reg_t * ctl = (struct s3_dram_ctl_reg_t *)S3_DRAM_CTL_BASE; struct dram_para_t para = { .read_delays = 0x00007979, .write_delays = 0x6aaa0000, .dual_rank = 0, .bus_width = 32, .row_bits = 15, .bank_bits = 3, .page_size = 4096, }; u32_t * dsz = (void *)0x00000020; if(dsz[0] != 0) return; mctl_sys_init(¶); if(mctl_channel_init(¶)) { dsz[0] = 0; return; } if(para.dual_rank) write32((virtual_addr_t)&ctl->odtmap, 0x00000303); else write32((virtual_addr_t)&ctl->odtmap, 0x00000201); sdelay(1); write32((virtual_addr_t)&ctl->odtcfg, 0x0c000400); setbits_le32(&com->cccr, 1 << 31); sdelay(10); mctl_auto_detect_dram_size(¶); mctl_set_cr(¶); dsz[0] = (1UL << (para.row_bits + para.bank_bits)) * para.page_size * (para.dual_rank ? 2 : 1); }
代码都有,咋这么喜欢自己从头造轮子呢?DRAM驱动也没这么容易写的吧。
-
This post is deleted! -
我按照上面几个文件编译,结果出现了如下错误:
dram.c:(.text+0x2a0): undefined reference to__aeabi_idiv' arm-linux-gnueabihf-ld: dram.c:(.text+0x2ca): undefined reference to
__aeabi_idiv'
就是说a=3,b=1,
a/1可以
a/b不行
就是在这个函数里面:
static void clock_set_pll_ddr(u32_t clk)
不知怎么办 -
@casdfxx 这不就是除法,启用编译器除法选项就行了
-
@awwwwa 主要我用的是vscode + make,没有除法选项这个配置
-
然后我就修改了一下,根据判断将除变量改为除常量,
static void clock_set_pll_ddr(u32_t clk) { int n = 32; int k = 1; int m = 2; u32_t val; /* ddr pll rate = 24000000 * n * k / m=2 */ if(clk > 24000000 * k * n / 2) { m = 1; if(clk > 24000000 * k * n / 1) { k = 2; val = (0x1 << 31); val |= (0x0 << 24); val |= (0x1 << 20); val |= ((((clk / (24000000 * 2 / 1)) - 1) & 0x1f) << 8); val |= (((2 - 1) & 0x3) << 4); val |= (((1 - 1) & 0x3) << 0); write32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL, val); sdelay(5500); }else{ val = (0x1 << 31); val |= (0x0 << 24); val |= (0x1 << 20); val |= ((((clk / (24000000 * 1 / 1)) - 1) & 0x1f) << 8); val |= (((k - 1) & 0x3) << 4); val |= (((1 - 1) & 0x3) << 0); write32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL, val); sdelay(5500); } }else{ //k=1 n=32 m=2 val = (0x1 << 31); val |= (0x0 << 24); val |= (0x1 << 20); val |= ((((clk / (24000000 * 1 / 2)) - 1) & 0x1f) << 8); val |= (((1 - 1) & 0x3) << 4); val |= (((2 - 1) & 0x3) << 0); write32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL, val); sdelay(5500); } }
原来的函数为:
static void clock_set_pll_ddr(u32_t clk) { int n = 32; int k = 1; int m = 2; u32_t val; /* ddr pll rate = 24000000 * n * k / m */ if(clk > 24000000 * k * n / m) { m = 1; if(clk > 24000000 * k * n / m) { k = 2; } } val = (0x1 << 31); val |= (0x0 << 24); val |= (0x1 << 20); val |= ((((clk / (24000000 * k / m)) - 1) & 0x1f) << 8); val |= (((k - 1) & 0x3) << 4); val |= (((m - 1) & 0x3) << 0); write32(S3_CCU_BASE + CCU_PLL_DDR0_CTRL, val); sdelay(5500); }
结果运行后,发现读取dram中的数据(位置0x41000000)程序直接卡死。
-
@casdfxx 这个代码是u-boot提供的,具体问题可以访问 https://lists.denx.de/listinfo/u-boot 寻求帮助。
裸机工程:https://github.com/xboot/xboot/tree/master/src/arch/arm32/mach-v3s
-
天呐,雷姆。
我才发现为什么我的程序不可以启动SDRAM的真正原因。我今天在网上找了一个使用IAR的.mac的文件,功能是进入调试前初始化SDRAM,将其一点点剥离,通过fel烧录到板子上。因为别人使用IAR能初始化SDRAM,我提取出地址与值,使用fel应该能初始化SDRAM吧。
一百多行的写寄存器,硬是被我折腾了好几遍,可结果还是卡死(读0x41000000 提示timeout)。
这没道理呀,使用程序初始化可能因为我没有改好,导致初始化失败,但是直接写寄存器我可是核对了过了呀。
又在网上找到一个硬件测试软件DragonHD。用其测试串口通过,于是测试DRAM,可是失败。那到这里就知道是硬件的问题了。
由于板子是别人画的,我猜测可能是DDR供电异常(因为电源芯片SY8088很多)。
测量1.8V的供电,发现只有0.6-0.7V。
将两个反馈电阻去掉测量发现值正常,分别为150K、300K。
偷了个懒,不焊回电阻,准备直接测芯片输入电压。闻到一股糊味。被吓了一跳。赶紧拔掉电源,摸芯片发烫。
后悔并害怕,心想这芯片玩了,还得换芯片,说不定要拖到明天了。将两个新电阻补焊上后,再上电,发现仍然能通过fel识别芯片。
长舒一口气。
使用DragonHD测试,发现DDR通了。
狂喜,测试1.8V,发现正常了。
怀疑是电阻焊接不良吗?不过,DDR可算是通了。
现在已经把裸机驱动调通了IO,TIMER,UART,GIC。这样就算是入坑了吧。 -
使用fel,下面的代码可以调通dram:
sunxi-fel writel 0x1C2015C 0x0 sunxi-fel writel 0x1C200FC 0x0 sunxi-fel writel 0x1C20060 0x1000000 sunxi-fel writel 0x1C202C0 0x1000000 sunxi-fel writel 0x1C20020 0x1000 10 sunxi-fel writel 0x1C20100 0x0 1000 sunxi-fel writel 0x1C20020 0x80101D00 5500 sunxi-fel writel 0x1C200F4 0x10000 sunxi-fel writel 0x1C202C0 0x1004000 sunxi-fel writel 0x1C20060 0x1004000 sunxi-fel writel 0x1C2015C 0x80000000 sunxi-fel writel 0x1C200FC 0x80000000 sunxi-fel writel 0x1C200F4 0x80000000 10 sunxi-fel writel 0x1C6300C 0xC00E 500 sunxi-fel writel 0x1C62000 0x4219E4 sunxi-fel writel 0x1C63030 0x263 sunxi-fel writel 0x1C63034 0x4 sunxi-fel writel 0x1C63038 0 sunxi-fel writel 0x1C6303C 0 sunxi-fel writel 0x1C63058 0x8091B09 sunxi-fel writel 0x1C6305C 0x2020C sunxi-fel writel 0x1C63060 0x3030307 sunxi-fel writel 0x1C63064 0x200C sunxi-fel writel 0x1C63068 0x4010203 sunxi-fel writel 0x1C6306C 0x5050403 sunxi-fel writel 0x1C63078 0x90006610 sunxi-fel writel 0x1C63080 0x2010101 sunxi-fel writel 0x1C63050 0xB523281 sunxi-fel writel 0x1C63054 0x16911941 sunxi-fel writel 0x1C63090 0x2B003C sunxi-fel writel 0x1C62090 0x10190 sunxi-fel writel 0x1C62098 0x1 sunxi-fel writel 0x1C62010 0x200000D sunxi-fel writel 0x1C62014 0x800100 sunxi-fel writel 0x1C62018 0x6000009 sunxi-fel writel 0x1C6201C 0x1000400 sunxi-fel writel 0x1C62020 0x200000D sunxi-fel writel 0x1C62024 0x600100 sunxi-fel writel 0x1C62028 0x100000D sunxi-fel writel 0x1C6202C 0x200080 sunxi-fel writel 0x1C62030 0x7000009 sunxi-fel writel 0x1C62034 0x1000640 sunxi-fel writel 0x1C62038 0x100000D sunxi-fel writel 0x1C6203C 0x200080 sunxi-fel writel 0x1C62040 0x1000009 sunxi-fel writel 0x1C62044 0x400080 sunxi-fel writel 0x1C62048 0x100000D sunxi-fel writel 0x1C6204C 0x400080 sunxi-fel writel 0x1C62050 0x100000D sunxi-fel writel 0x1C62054 0x400080 sunxi-fel writel 0x1C62058 0x4000009 sunxi-fel writel 0x1C6205C 0x400100 sunxi-fel writel 0x1C62060 0x2000030D sunxi-fel writel 0x1C62064 0x4001800 sunxi-fel writel 0x1C62068 0x4000009 sunxi-fel writel 0x1C6206C 0x400120 sunxi-fel writel 0x1C63100 0x4005400 sunxi-fel writel 0x1C63104 0x4680C620 sunxi-fel writel 0x1C62800 0x94BE6FA3 100 sunxi-fel writel 0x1C63888 0x80500010 sunxi-fel writel 0x1C62800 0x0 100 sunxi-fel writel 0x1C63344 0x7C0002A1 sunxi-fel writel 0x1C633C4 0x7C0002A1 sunxi-fel writel 0x1C63444 0x20 sunxi-fel writel 0x1C634C4 0x20 sunxi-fel writel 0x1C63208 0x34A sunxi-fel writel 0x1C63108 0x2CC0 sunxi-fel writel 0x1C63100 0x4000400 sunxi-fel writel 0x1C63108 0x26C0 sunxi-fel writel 0x1C630C0 0x81003087 sunxi-fel writel 0x1C63310 0x10 sunxi-fel writel 0x1C63314 0x10 sunxi-fel writel 0x1C63318 0x10 l sunxi-fel writel 0x1C6331C 0x10 sunxi-fel writel 0x1C63320 0x10 sunxi-fel writel 0x1C63324 0x10 sunxi-fel writel 0x1C63328 0x10 sunxi-fel writel 0x1C6332C 0x10 sunxi-fel writel 0x1C63330 0x10 sunxi-fel writel 0x1C63390 0xE sunxi-fel writel 0x1C63394 0xE sunxi-fel writel 0x1C63398 0xE sunxi-fel writel 0x1C6339C 0xE sunxi-fel writel 0x1C633A0 0xE sunxi-fel writel 0x1C633A4 0xE sunxi-fel writel 0x1C633A8 0xE sunxi-fel writel 0x1C633AC 0xE sunxi-fel writel 0x1C633B0 0xE sunxi-fel writel 0x1C63410 0x10 sunxi-fel writel 0x1C63414 0x10 sunxi-fel writel 0x1C63418 0x10 sunxi-fel writel 0x1C6341C 0x10 sunxi-fel writel 0x1C63420 0x10 sunxi-fel writel 0x1C63424 0x10 sunxi-fel writel 0x1C63428 0x10 sunxi-fel writel 0x1C6342C 0x10 sunxi-fel writel 0x1C63430 0x10 sunxi-fel writel 0x1C63490 0xE sunxi-fel writel 0x1C63494 0xE sunxi-fel writel 0x1C63498 0xE sunxi-fel writel 0x1C6349C 0xE sunxi-fel writel 0x1C634A0 0xE sunxi-fel writel 0x1C634A4 0xE sunxi-fel writel 0x1C634A8 0xE sunxi-fel writel 0x1C634AC 0xE sunxi-fel writel 0x1C634B0 0xE sunxi-fel writel 0x1C63100 0x400 sunxi-fel writel 0x1C63334 0x400 sunxi-fel writel 0x1C63338 0x400 sunxi-fel writel 0x1C633B4 0x400 sunxi-fel writel 0x1C633B8 0x400 sunxi-fel writel 0x1C63434 0xA00 sunxi-fel writel 0x1C63438 0xA00 sunxi-fel writel 0x1C634B4 0x600 sunxi-fel writel 0x1C634B8 0x600 sunxi-fel writel 0x1C63100 0x4000400 1 50 sunxi-fel writel 0x1C63150 0xA0A0A0A sunxi-fel writel 0x1C63140 0xBBBBBB sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63150 0xA0A0A0A sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63140 0xBBBBBB sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63150 0xA0A0A0A sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63140 0x999999 sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63150 0xE0E0E0E sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63140 0x333333 sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63150 0x7070707 sunxi-fel writel 0x1C63000 0x8000000 sunxi-fel writel 0x1C63000 0x3 sunxi-fel writel 0x1C63148 0xA0A0A0A sunxi-fel writel 0x1C6314C 0x7070E0E sunxi-fel writel 0x1C63000 0x571 sunxi-fel writel 0x1C6308C 0x80200010 10 sunxi-fel writel 0x1C6308C 0x200010 10 sunxi-fel writel 0x1C6310C 0xAA0060 sunxi-fel writel 0x1C63140 0x80333333 sunxi-fel writel 0x1C62094 0xFFFFFFFF sunxi-fel writel 0x1C63120 0x201 1 sunxi-fel writel 0x1C6307C 0x4000400 sunxi-fel writel 0x1C63108 0x6C0 sunxi-fel writel 0x1C620D0 0x80103040 10 sunxi-fel writel 0x1C62000 0x4216F0 sunxi-fel writel 0x40000000 0x0 sunxi-fel writel 0x40400000 0xAA55AA55 sunxi-fel writel 0x40000000 0x0 sunxi-fel writel 0x40800000 0xAA55AA55 sunxi-fel writel 0x40000000 0x0 sunxi-fel writel 0x41000000 0xAA55AA55 sunxi-fel writel 0x1C62000 0x421AC0 sunxi-fel writel 0x40000000 0x0 sunxi-fel writel 0x40000200 0xAA55AA55 sunxi-fel writel 0x40000000 0x0 sunxi-fel writel 0x40000400 0xAA55AA55 sunxi-fel writel 0x40000000 0 sunxi-fel writel 0x40000800 0xAA55AA55 sunxi-fel writel 0x1C62000 0x4218C0
Copyright © 2023 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号