diff --git a/platform/zynq/include/platform/zynq.h b/platform/zynq/include/platform/zynq.h index 5c3d839e..a0a1dd44 100644 --- a/platform/zynq/include/platform/zynq.h +++ b/platform/zynq/include/platform/zynq.h @@ -119,6 +119,7 @@ #ifndef ASSEMBLY +/* Configuration values for each of the system PLLs. Refer to the TRM 25.10.4 */ typedef struct { uint32_t lock_cnt; uint32_t cp; @@ -152,6 +153,18 @@ typedef struct { zynq_pll_cfg_t io; } zynq_pll_cfg_tree_t; +/* Configuration for the DDR controller and buffers. TRM Ch 10 */ +typedef struct { + uint32_t addr0; + uint32_t addr1; + uint32_t data0; + uint32_t data1; + uint32_t diff0; + uint32_t diff1; + bool ibuf_disable; + bool term_disable; +} zynq_ddriob_cfg_t;; + /* SLCR registers */ struct slcr_regs { uint32_t SCL; // Secure Configuration Lock diff --git a/platform/zynq/platform.c b/platform/zynq/platform.c index 8cd4f853..e1e15876 100644 --- a/platform/zynq/platform.c +++ b/platform/zynq/platform.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ extern const long zynq_ddr_cfg[]; extern const uint32_t zynq_ddr_cfg_cnt; extern const zynq_pll_cfg_tree_t zynq_pll_cfg; extern const zynq_clk_cfg_t zynq_clk_cfg; +extern const zynq_ddriob_cfg_t zynq_ddriob_cfg; static inline int reg_poll(uint32_t addr,uint32_t mask) @@ -65,7 +67,6 @@ static inline int reg_poll(uint32_t addr,uint32_t mask) 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; @@ -101,60 +102,31 @@ int zynq_pll_init(void) { } SLCR_REG(IO_PLL_CTRL) &= ~PLL_BYPASS_FORCE; - zynq_slcr_lock(); return 0; } int zynq_mio_init(void) { - zynq_slcr_unlock(); /* This DDRIOB configuration applies to both zybo and uzed, but it's possible * it may not work for all boards in the future. Just something to keep in mind * with different memory configurations. */ -#if ZYNQ_SDRAM_INIT SLCR_REG(GPIOB_CTRL) = GPIOB_CTRL_VREF_EN; - SLCR_REG(DDRIOB_ADDR0) = DDRIOB_OUTPUT_EN(0x3); - SLCR_REG(DDRIOB_ADDR1) = DDRIOB_OUTPUT_EN(0x3); - SLCR_REG(DDRIOB_DATA0) = DDRIOB_INP_TYPE(1) | DDRIOB_TERM_EN | - DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3); - SLCR_REG(DDRIOB_DATA1) = DDRIOB_INP_TYPE(1) | DDRIOB_TERM_EN | - DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3); - SLCR_REG(DDRIOB_DIFF0) = DDRIOB_INP_TYPE(2) | DDRIOB_TERM_EN | - DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3); - SLCR_REG(DDRIOB_DIFF1) = DDRIOB_INP_TYPE(2) | DDRIOB_TERM_EN | - DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3); - 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; -#endif for (size_t pin = 0; pin < countof(zynq_mio_cfg); pin++) { if (zynq_mio_cfg[pin] != 0) { - SLCR_REG(MIO_PIN_00 + (pin * sizeof(uint32_t))) = zynq_mio_cfg[pin]; + SLCR_REG(MIO_PIN_00 + (pin * 4)) = zynq_mio_cfg[pin]; } } SLCR_REG(SD0_WP_CD_SEL) = SDIO0_WP_SEL(0x37) | SDIO0_CD_SEL(0x2F); - zynq_slcr_lock(); return 0; } void zynq_clk_init(void) { - zynq_slcr_unlock(); SLCR_REG(DCI_CLK_CTRL) = zynq_clk_cfg.dci_clk; SLCR_REG(GEM0_CLK_CTRL) = zynq_clk_cfg.gem0_clk; SLCR_REG(GEM0_RCLK_CTRL) = zynq_clk_cfg.gem0_rclk; @@ -170,12 +142,31 @@ void zynq_clk_init(void) SLCR_REG(FPGA3_CLK_CTRL) = zynq_clk_cfg.fpga3_clk; SLCR_REG(APER_CLK_CTRL) = zynq_clk_cfg.aper_clk; SLCR_REG(CLK_621_TRUE) = zynq_clk_cfg.clk_621_true; - zynq_slcr_lock(); } void zynq_ddr_init(void) { - zynq_slcr_unlock(); +#ifdef ZYNQ_SDRAM_INIT + 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; +#endif /* Write addresss / value pairs from target table */ for (size_t i = 0; i < zynq_ddr_cfg_cnt; i += 2) { @@ -192,7 +183,19 @@ void zynq_ddr_init(void) /* Switch timer to 64k */ *REG32(0XF8007000) = *REG32(0xF8007000) & ~0x20000000U; - zynq_slcr_lock(); + 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; + } } STATIC_ASSERT(IS_ALIGNED(SDRAM_BASE, MB)); @@ -288,14 +291,18 @@ void platform_init_mmu_mappings(void) void platform_early_init(void) { + /* Unlock the registers and leave them that way */ +#if 0 + ps7_init(); +#else + zynq_slcr_unlock(); zynq_mio_init(); zynq_pll_init(); zynq_clk_init(); #if ZYNQ_SDRAM_INIT zynq_ddr_init(); #endif - - zynq_slcr_unlock(); +#endif /* Enable all level shifters */ SLCR_REG(LVL_SHFTR_EN) = 0xF; @@ -305,7 +312,6 @@ void platform_early_init(void) /* zynq manual says this is mandatory for cache init */ *REG32(SLCR_BASE + 0xa1c) = 0x020202; - zynq_slcr_lock(); /* early initialize the uart so we can printf */ uart_init_early(); @@ -370,7 +376,32 @@ static int cmd_mio(int argc, const cmd_args *argv) return 0; } +#define DSR(x) printf("%30s (0x%08lx): 0x%08x\n", #x, (uintptr_t)&SLCR_REG(x), SLCR_REG(x)); +static int cmd_slcr(int argc, const cmd_args *argv) +{ + if (argc == 2) { + bool print_lock_status = false; + if (!strcmp(argv[1].str, "lock")) { + zynq_slcr_lock(); + print_lock_status = true; + } else if (!strcmp(argv[1].str, "unlock")) { + zynq_slcr_unlock(); + print_lock_status = true; + } else if (print_lock_status || !strcmp(argv[1].str, "lockstatus")) { + printf("%s\n", (SLCR->SLCR_LOCKSTA & 0x1) ? "locked" : "unlocked"); + } + } else { + printf("slcr lock: lock the SCL registers\n"); + printf("slcr unlock: unlock the SCL registers\n"); + printf("slcr lockstatus: print the SCL lock status\n"); + } + + return 0; +} +#undef DSR + STATIC_COMMAND_START STATIC_COMMAND("mio", "print mio configuration", &cmd_mio) +STATIC_COMMAND("slcr", "slcr commands", &cmd_slcr) STATIC_COMMAND_END(mio); -#endif +#endif // WITH_LIB_CONSOLE diff --git a/target/uzed/target.c b/target/uzed/target.c index d23f8bd4..d71e3eeb 100644 --- a/target/uzed/target.c +++ b/target/uzed/target.c @@ -76,6 +76,17 @@ const unsigned long zynq_ddr_cfg[] = { const unsigned long zynq_ddr_cfg_cnt = countof(zynq_ddr_cfg); +const zynq_ddriob_cfg_t zynq_ddriob_cfg = { + .addr0 = DDRIOB_OUTPUT_EN(0x3), + .addr1 = DDRIOB_OUTPUT_EN(0x3), + .data0 = DDRIOB_INP_TYPE(1) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .data1 = DDRIOB_INP_TYPE(1) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .diff0 = DDRIOB_INP_TYPE(2) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .diff1 = DDRIOB_INP_TYPE(2) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .ibuf_disable = false, + .term_disable = false, +}; + const uint32_t zynq_mio_cfg[ZYNQ_MIO_CNT] = { [0] = MIO_IO_TYPE_LVCMOS33, [1] = MIO_L0_SEL | MIO_IO_TYPE_LVCMOS33, diff --git a/target/zybo/target.c b/target/zybo/target.c index a363b441..7ac04ce8 100644 --- a/target/zybo/target.c +++ b/target/zybo/target.c @@ -77,6 +77,17 @@ const unsigned long zynq_ddr_cfg[] = { const unsigned long zynq_ddr_cfg_cnt = countof(zynq_ddr_cfg); +const zynq_ddriob_cfg_t zynq_ddriob_cfg = { + .addr0 = DDRIOB_OUTPUT_EN(0x3), + .addr1 = DDRIOB_OUTPUT_EN(0x3), + .data0 = DDRIOB_INP_TYPE(1) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .data1 = DDRIOB_INP_TYPE(1) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .diff0 = DDRIOB_INP_TYPE(2) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .diff1 = DDRIOB_INP_TYPE(2) | DDRIOB_TERM_EN | DDRIOB_DCI_TYPE(0x3) | DDRIOB_OUTPUT_EN(0x3), + .ibuf_disable = false, + .term_disable = false, +}; + const uint32_t zynq_mio_cfg[ZYNQ_MIO_CNT] = { [1] = MIO_L0_SEL | MIO_SPEED_FAST | MIO_IO_TYPE_LVCMOS33, [2] = MIO_L0_SEL | MIO_SPEED_FAST | MIO_IO_TYPE_LVCMOS33,