void zynq_ddr_init(void) { SLCR_REG(DDRIOB_ADDR0) = zynq_ddriob_cfg.addr0; SLCR_REG(DDRIOB_ADDR1) = zynq_ddriob_cfg.addr1; SLCR_REG(DDRIOB_DATA0) = zynq_ddriob_cfg.data0; SLCR_REG(DDRIOB_DATA1) = zynq_ddriob_cfg.data1; SLCR_REG(DDRIOB_DIFF0) = zynq_ddriob_cfg.diff0; SLCR_REG(DDRIOB_DIFF1) = zynq_ddriob_cfg.diff1; SLCR_REG(DDRIOB_CLOCK) = DDRIOB_OUTPUT_EN(0x3); /* These register fields are not documented in the TRM. These * values represent the defaults generated via the Zynq tools */ SLCR_REG(DDRIOB_DRIVE_SLEW_ADDR) = 0x0018C61CU; SLCR_REG(DDRIOB_DRIVE_SLEW_DATA) = 0x00F9861CU; SLCR_REG(DDRIOB_DRIVE_SLEW_DIFF) = 0x00F9861CU; SLCR_REG(DDRIOB_DRIVE_SLEW_CLOCK) = 0x00F9861CU; SLCR_REG(DDRIOB_DDR_CTRL) = 0x00000E60U; SLCR_REG(DDRIOB_DCI_CTRL) = 0x00000001U; SLCR_REG(DDRIOB_DCI_CTRL) |= 0x00000020U; SLCR_REG(DDRIOB_DCI_CTRL) |= 0x00000823U; /* Write addresss / value pairs from target table */ for (size_t i = 0; i < zynq_ddr_cfg_cnt; i += 2) { *REG32(zynq_ddr_cfg[i]) = zynq_ddr_cfg[i+1]; } /* Wait for DCI done */ reg_poll((uintptr_t)&SLCR->DDRIOB_DCI_STATUS, 0x2000); /* Bring ddr out of reset and wait until self refresh */ *REG32(DDRC_CTRL) |= DDRC_CTRL_OUT_OF_RESET; reg_poll(DDRC_MODE_STATUS, DDRC_STS_SELF_REFRESH); /* Switch timer to 64k */ *REG32(0XF8007000) = *REG32(0xF8007000) & ~0x20000000U; if (zynq_ddriob_cfg.ibuf_disable) { SLCR_REG(DDRIOB_DATA0) |= DDRIOB_IBUF_DISABLE_MODE; SLCR_REG(DDRIOB_DATA1) |= DDRIOB_IBUF_DISABLE_MODE; SLCR_REG(DDRIOB_DIFF0) |= DDRIOB_IBUF_DISABLE_MODE; SLCR_REG(DDRIOB_DIFF1) |= DDRIOB_IBUF_DISABLE_MODE; } if (zynq_ddriob_cfg.term_disable) { SLCR_REG(DDRIOB_DATA0) |= DDRIOB_TERM_DISABLE_MODE; SLCR_REG(DDRIOB_DATA1) |= DDRIOB_TERM_DISABLE_MODE; SLCR_REG(DDRIOB_DIFF0) |= DDRIOB_TERM_DISABLE_MODE; SLCR_REG(DDRIOB_DIFF1) |= DDRIOB_TERM_DISABLE_MODE; } }
/* For each PLL we need to configure the cp / res / lock_cnt and then place the PLL in bypass * before doing a reset to switch to the new values. Then bypass is removed to switch back to using * the PLL once its locked. */ int zynq_pll_init(void) { const zynq_pll_cfg_tree_t *cfg = &zynq_pll_cfg; SLCR_REG(ARM_PLL_CFG) = PLL_CFG_LOCK_CNT(cfg->arm.lock_cnt) | PLL_CFG_PLL_CP(cfg->arm.cp) | PLL_CFG_PLL_RES(cfg->arm.res); SLCR_REG(ARM_PLL_CTRL) = PLL_FDIV(cfg->arm.fdiv) | PLL_BYPASS_FORCE | PLL_RESET; SLCR_REG(ARM_PLL_CTRL) &= ~PLL_RESET; if (reg_poll((uintptr_t)&SLCR->PLL_STATUS, PLL_STATUS_ARM_PLL_LOCK) == -1) { return -1; } SLCR_REG(ARM_PLL_CTRL) &= ~PLL_BYPASS_FORCE; SLCR_REG(ARM_CLK_CTRL) = zynq_clk_cfg.arm_clk; #if ZYNQ_SDRAM_INIT SLCR_REG(DDR_PLL_CFG) = PLL_CFG_LOCK_CNT(cfg->ddr.lock_cnt) | PLL_CFG_PLL_CP(cfg->ddr.cp) | PLL_CFG_PLL_RES(cfg->ddr.res); SLCR_REG(DDR_PLL_CTRL) = PLL_FDIV(cfg->ddr.fdiv) | PLL_BYPASS_FORCE | PLL_RESET; SLCR_REG(DDR_PLL_CTRL) &= ~PLL_RESET; if (reg_poll((uintptr_t)&SLCR->PLL_STATUS, PLL_STATUS_DDR_PLL_LOCK) == -1) { return -1; } SLCR_REG(DDR_PLL_CTRL) &= ~PLL_BYPASS_FORCE; SLCR_REG(DDR_CLK_CTRL) = zynq_clk_cfg.ddr_clk; #elif SDRAM_SIZE == 0 /* if we're not using sdram and haven't been told to initialize sdram, stop the DDR pll */ SLCR_REG(DDR_CLK_CTRL) = 0; SLCR_REG(DDR_PLL_CTRL) |= PLL_PWRDOWN; #endif SLCR_REG(IO_PLL_CFG) = PLL_CFG_LOCK_CNT(cfg->io.lock_cnt) | PLL_CFG_PLL_CP(cfg->io.cp) | PLL_CFG_PLL_RES(cfg->io.res); SLCR_REG(IO_PLL_CTRL) = PLL_FDIV(cfg->io.fdiv) | PLL_BYPASS_FORCE | PLL_RESET; SLCR_REG(IO_PLL_CTRL) &= ~PLL_RESET; if (reg_poll((uintptr_t)&SLCR->PLL_STATUS, PLL_STATUS_IO_PLL_LOCK) == -1) { return -1; } SLCR_REG(IO_PLL_CTRL) &= ~PLL_BYPASS_FORCE; return 0; }
/* For each PLL we need to configure the cp / res / lock_cnt and then place the PLL in bypass * before doing a reset to switch to the new values. Then bypass is removed to switch back to using * the PLL once its locked. */ int zynq_pll_init(void) { const zynq_pll_cfg_tree_t *cfg = &zynq_pll_cfg; zynq_slcr_unlock(); SLCR_REG(ARM_PLL_CFG) = PLL_CFG_LOCK_CNT(cfg->arm.lock_cnt) | PLL_CFG_PLL_CP(cfg->arm.cp) | PLL_CFG_PLL_RES(cfg->arm.res); SLCR_REG(ARM_PLL_CTRL) = PLL_FDIV(cfg->arm.fdiv) | PLL_BYPASS_FORCE | PLL_RESET; SLCR_REG(ARM_PLL_CTRL) &= ~PLL_RESET; if (reg_poll((uintptr_t)&SLCR->PLL_STATUS, PLL_STATUS_ARM_PLL_LOCK) == -1) { return -1; } SLCR_REG(ARM_PLL_CTRL) &= ~PLL_BYPASS_FORCE; SLCR_REG(ARM_CLK_CTRL) = zynq_clk_cfg.arm_clk; #if ZYNQ_SDRAM_INIT SLCR_REG(DDR_PLL_CFG) = PLL_CFG_LOCK_CNT(cfg->ddr.lock_cnt) | PLL_CFG_PLL_CP(cfg->ddr.cp) | PLL_CFG_PLL_RES(cfg->ddr.res); SLCR_REG(DDR_PLL_CTRL) = PLL_FDIV(cfg->ddr.fdiv) | PLL_BYPASS_FORCE | PLL_RESET; SLCR_REG(DDR_PLL_CTRL) &= ~PLL_RESET; if (reg_poll((uintptr_t)&SLCR->PLL_STATUS, PLL_STATUS_DDR_PLL_LOCK) == -1) { return -1; } SLCR_REG(DDR_PLL_CTRL) &= ~PLL_BYPASS_FORCE; SLCR_REG(DDR_CLK_CTRL) = zynq_clk_cfg.ddr_clk; #endif SLCR_REG(IO_PLL_CFG) = PLL_CFG_LOCK_CNT(cfg->io.lock_cnt) | PLL_CFG_PLL_CP(cfg->io.cp) | PLL_CFG_PLL_RES(cfg->io.res); SLCR_REG(IO_PLL_CTRL) = PLL_FDIV(cfg->io.fdiv) | PLL_BYPASS_FORCE | PLL_RESET; SLCR_REG(IO_PLL_CTRL) &= ~PLL_RESET; if (reg_poll((uintptr_t)&SLCR->PLL_STATUS, PLL_STATUS_IO_PLL_LOCK) == -1) { return -1; } SLCR_REG(IO_PLL_CTRL) &= ~PLL_BYPASS_FORCE; zynq_slcr_lock(); return 0; }
void zynq_ddr_init(void) { zynq_slcr_unlock(); /* Write addresss / value pairs from target table */ for (size_t i = 0; i < zynq_ddr_cfg_cnt; i += 2) { *REG32(zynq_ddr_cfg[i]) = zynq_ddr_cfg[i+1]; } /* Wait for DCI done */ reg_poll((uintptr_t)&SLCR->DDRIOB_DCI_STATUS, 0x2000); /* Bring ddr out of reset and wait until self refresh */ *REG32(DDRC_CTRL) |= DDRC_CTRL_OUT_OF_RESET; reg_poll(DDRC_MODE_STATUS, DDRC_STS_SELF_REFRESH); /* Switch timer to 64k */ *REG32(0XF8007000) = *REG32(0xF8007000) & ~0x20000000U; zynq_slcr_lock(); }
void zynq_ddr_init(void) { zynq_slcr_unlock(); /* Write addresss / value pairs from target table */ for (size_t i = 0; i < zynq_ddr_cfg_cnt; i += 2) { *REG32(zynq_ddr_cfg[i]) = zynq_ddr_cfg[i+1]; } /* Wait for DCI done */ reg_poll((uintptr_t)&SLCR->DDRIOB_DCI_STATUS, 0x2000); /* Bring ddr out of reset and wait until self refresh */ *REG32(0XF8006000) = 0x00000081U; reg_poll(0xf8006054, 0x00000007); /* Switch timer to 64k */ *REG32(0XF8007000) = *REG32(0xF8007000) & ~0x20000000U; zynq_slcr_lock(); }