diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-10-07 15:10:20 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2017-01-10 09:53:31 +0100 |
commit | c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f (patch) | |
tree | ad4f2519067709f00ab98b3c591186c26dc3a21f /freebsd/sys/arm/xilinx | |
parent | userspace-header-gen.py: Simplify program ports (diff) | |
download | rtems-libbsd-c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f.tar.bz2 |
Update to FreeBSD head 2016-08-23
Git mirror commit 9fe7c416e6abb28b1398fd3e5687099846800cfd.
Diffstat (limited to 'freebsd/sys/arm/xilinx')
-rw-r--r-- | freebsd/sys/arm/xilinx/zy7_slcr.c | 296 | ||||
-rw-r--r-- | freebsd/sys/arm/xilinx/zy7_slcr.h | 36 |
2 files changed, 323 insertions, 9 deletions
diff --git a/freebsd/sys/arm/xilinx/zy7_slcr.c b/freebsd/sys/arm/xilinx/zy7_slcr.c index 79be30a7..7ce502f9 100644 --- a/freebsd/sys/arm/xilinx/zy7_slcr.c +++ b/freebsd/sys/arm/xilinx/zy7_slcr.c @@ -88,7 +88,6 @@ extern void (*zynq7_cpu_reset); #define ZYNQ_DEFAULT_PS_CLK_FREQUENCY 33333333 /* 33.3 Mhz */ - SYSCTL_NODE(_hw, OID_AUTO, zynq, CTLFLAG_RD, 0, "Xilinx Zynq-7000"); static char zynq_bootmode[64]; @@ -135,7 +134,6 @@ zy7_slcr_lock(struct zy7_slcr_softc *sc) WR4(sc, ZY7_SLCR_LOCK, ZY7_SLCR_LOCK_MAGIC); } - #ifndef __rtems__ static void zy7_slcr_cpu_reset(void) @@ -185,11 +183,12 @@ zy7_slcr_preload_pl(void) ZSLCR_UNLOCK(sc); } +#endif /* __rtems__ */ /* After PL configuration, enable level shifters and deassert top-level * PL resets. Called from zy7_devcfg.c. Optionally, the level shifters * can be left disabled but that's rare of an FPGA application. That option - * is controled by a sysctl in the devcfg driver. + * is controlled by a sysctl in the devcfg driver. */ void zy7_slcr_postload_pl(int en_level_shifters) @@ -216,7 +215,6 @@ zy7_slcr_postload_pl(int en_level_shifters) ZSLCR_UNLOCK(sc); } -#endif /* __rtems__ */ /* Override cgem_set_refclk() in gigabit ethernet driver * (sys/dev/cadence/if_cgem.c). This function is called to @@ -266,6 +264,296 @@ cgem_set_ref_clk(int unit, int frequency) return (0); } +/* + * PL clocks management function + */ +int +zy7_pl_fclk_set_source(int unit, int source) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + uint32_t reg; + + if (!sc) + return (-1); + + ZSLCR_LOCK(sc); + + /* Unlock SLCR registers. */ + zy7_slcr_unlock(sc); + + /* Modify FPGAx source. */ + reg = RD4(sc, ZY7_SLCR_FPGA_CLK_CTRL(unit)); + reg &= ~(ZY7_SLCR_FPGA_CLK_CTRL_SRCSEL_MASK); + reg |= (source << ZY7_SLCR_FPGA_CLK_CTRL_SRCSEL_SHIFT); + WR4(sc, ZY7_SLCR_FPGA_CLK_CTRL(unit), reg); + + /* Lock SLCR registers. */ + zy7_slcr_lock(sc); + + ZSLCR_UNLOCK(sc); + + return (0); +} + +int +zy7_pl_fclk_get_source(int unit) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + uint32_t reg; + int source; + + if (!sc) + return (-1); + + ZSLCR_LOCK(sc); + + /* Modify GEM reference clock. */ + reg = RD4(sc, ZY7_SLCR_FPGA_CLK_CTRL(unit)); + source = (reg & ZY7_SLCR_FPGA_CLK_CTRL_SRCSEL_MASK) >> + ZY7_SLCR_FPGA_CLK_CTRL_SRCSEL_SHIFT; + + /* ZY7_PL_FCLK_SRC_IO is actually b0x */ + if ((source & 2) == 0) + source = ZY7_PL_FCLK_SRC_IO; + + ZSLCR_UNLOCK(sc); + + return (source); +} + +int +zy7_pl_fclk_set_freq(int unit, int frequency) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + int div0, div1; + int base_frequency; + uint32_t reg; + int source; + + if (!sc) + return (-1); + + source = zy7_pl_fclk_get_source(unit); + switch (source) { + case ZY7_PL_FCLK_SRC_IO: + base_frequency = io_pll_frequency; + break; + + case ZY7_PL_FCLK_SRC_ARM: + base_frequency = arm_pll_frequency; + break; + + case ZY7_PL_FCLK_SRC_DDR: + base_frequency = ddr_pll_frequency; + break; + + default: + return (-1); + } + + /* Find suitable divisor pairs. Round result to nearest khz + * to test for match. + */ + for (div1 = 1; div1 <= ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR_MAX; div1++) { + div0 = (base_frequency + div1 * frequency / 2) / + div1 / frequency; + if (div0 > 0 && div0 <= ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR_MAX && + ((base_frequency / div0 / div1) + 500) / 1000 == + (frequency + 500) / 1000) + break; + } + + if (div1 > ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR_MAX) + return (-1); + + ZSLCR_LOCK(sc); + + /* Unlock SLCR registers. */ + zy7_slcr_unlock(sc); + + /* Modify FPGAx reference clock. */ + reg = RD4(sc, ZY7_SLCR_FPGA_CLK_CTRL(unit)); + reg &= ~(ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR1_MASK | + ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR0_MASK); + reg |= (div1 << ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR1_SHIFT) | + (div0 << ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR0_SHIFT); + WR4(sc, ZY7_SLCR_FPGA_CLK_CTRL(unit), reg); + + /* Lock SLCR registers. */ + zy7_slcr_lock(sc); + + ZSLCR_UNLOCK(sc); + + return (base_frequency / div0 / div1); +} + +int +zy7_pl_fclk_get_freq(int unit) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + int div0, div1; + int base_frequency; + int frequency; + uint32_t reg; + int source; + + if (!sc) + return (-1); + + source = zy7_pl_fclk_get_source(unit); + switch (source) { + case ZY7_PL_FCLK_SRC_IO: + base_frequency = io_pll_frequency; + break; + + case ZY7_PL_FCLK_SRC_ARM: + base_frequency = arm_pll_frequency; + break; + + case ZY7_PL_FCLK_SRC_DDR: + base_frequency = ddr_pll_frequency; + break; + + default: + return (-1); + } + + ZSLCR_LOCK(sc); + + /* Modify FPGAx reference clock. */ + reg = RD4(sc, ZY7_SLCR_FPGA_CLK_CTRL(unit)); + div1 = (reg & ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR1_MASK) >> + ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR1_SHIFT; + div0 = (reg & ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR0_MASK) >> + ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR0_SHIFT; + + ZSLCR_UNLOCK(sc); + + if (div0 == 0) + div0 = 1; + + if (div1 == 0) + div1 = 1; + + frequency = (base_frequency / div0 / div1); + /* Round to KHz */ + frequency = (frequency + 500) / 1000; + frequency = frequency * 1000; + + return (frequency); +} + +int +zy7_pl_fclk_enable(int unit) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + + if (!sc) + return (-1); + + ZSLCR_LOCK(sc); + + /* Unlock SLCR registers. */ + zy7_slcr_unlock(sc); + + WR4(sc, ZY7_SLCR_FPGA_THR_CTRL(unit), 0); + WR4(sc, ZY7_SLCR_FPGA_THR_CNT(unit), 0); + + /* Lock SLCR registers. */ + zy7_slcr_lock(sc); + + ZSLCR_UNLOCK(sc); + + return (0); +} + +int +zy7_pl_fclk_disable(int unit) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + + if (!sc) + return (-1); + + ZSLCR_LOCK(sc); + + /* Unlock SLCR registers. */ + zy7_slcr_unlock(sc); + + WR4(sc, ZY7_SLCR_FPGA_THR_CTRL(unit), 0); + WR4(sc, ZY7_SLCR_FPGA_THR_CNT(unit), 1); + + /* Lock SLCR registers. */ + zy7_slcr_lock(sc); + + ZSLCR_UNLOCK(sc); + + return (0); +} + +int +zy7_pl_fclk_enabled(int unit) +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + uint32_t reg; + + if (!sc) + return (-1); + + ZSLCR_LOCK(sc); + reg = RD4(sc, ZY7_SLCR_FPGA_THR_CNT(unit)); + ZSLCR_UNLOCK(sc); + + return !(reg & 1); +} + +int +zy7_pl_level_shifters_enabled() +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + + uint32_t reg; + + if (!sc) + return (-1); + + ZSLCR_LOCK(sc); + reg = RD4(sc, ZY7_SLCR_LVL_SHFTR_EN); + ZSLCR_UNLOCK(sc); + + return (reg == ZY7_SLCR_LVL_SHFTR_EN_ALL); +} + +void +zy7_pl_level_shifters_enable() +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + + if (!sc) + return; + + ZSLCR_LOCK(sc); + zy7_slcr_unlock(sc); + WR4(sc, ZY7_SLCR_LVL_SHFTR_EN, ZY7_SLCR_LVL_SHFTR_EN_ALL); + zy7_slcr_lock(sc); + ZSLCR_UNLOCK(sc); +} + +void +zy7_pl_level_shifters_disable() +{ + struct zy7_slcr_softc *sc = zy7_slcr_softc_p; + + if (!sc) + return; + + ZSLCR_LOCK(sc); + zy7_slcr_unlock(sc); + WR4(sc, ZY7_SLCR_LVL_SHFTR_EN, 0); + zy7_slcr_lock(sc); + ZSLCR_UNLOCK(sc); +} + static int zy7_slcr_probe(device_t dev) { diff --git a/freebsd/sys/arm/xilinx/zy7_slcr.h b/freebsd/sys/arm/xilinx/zy7_slcr.h index 70c46619..3afec02a 100644 --- a/freebsd/sys/arm/xilinx/zy7_slcr.h +++ b/freebsd/sys/arm/xilinx/zy7_slcr.h @@ -37,7 +37,6 @@ * are in appendix B.28. */ - #ifndef _ZY7_SLCR_H_ #define _ZY7_SLCR_H_ @@ -148,10 +147,19 @@ #define ZY7_SLCR_DBG_CLK_CTRL 0x0164 #define ZY7_SLCR_PCAP_CLK_CTRL 0x0168 #define ZY7_SLCR_TOPSW_CLK_CTRL 0x016c /* central intercnn clk ctrl */ -#define ZY7_SLCR_FPGA0_CLK_CTRL 0x0170 -#define ZY7_SLCR_FPGA1_CLK_CTRL 0x0180 -#define ZY7_SLCR_FPGA2_CLK_CTRL 0x0190 -#define ZY7_SLCR_FPGA3_CLK_CTRL 0x01a0 +#define ZY7_SLCR_FPGA_CLK_CTRL(unit) (0x0170 + 0x10*(unit)) +#define ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR1_SHIFT 20 +#define ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR1_MASK (0x3f << 20) +#define ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR0_SHIFT 8 +#define ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR0_MASK (0x3f << 8) +#define ZY7_SLCR_FPGA_CLK_CTRL_DIVISOR_MAX 0x3f +#define ZY7_SLCR_FPGA_CLK_CTRL_SRCSEL_SHIFT 4 +#define ZY7_SLCR_FPGA_CLK_CTRL_SRCSEL_MASK (3 << 4) +#define ZY7_SLCR_FPGA_THR_CTRL(unit) (0x0174 + 0x10*(unit)) +#define ZY7_SLCR_FPGA_THR_CTRL_CNT_RST (1 << 1) +#define ZY7_SLCR_FPGA_THR_CTRL_CPU_START (1 << 0) +#define ZY7_SLCR_FPGA_THR_CNT(unit) (0x0178 + 0x10*(unit)) +#define ZY7_SLCR_FPGA_THR_STA(unit) (0x017c + 0x10*(unit)) #define ZY7_SLCR_CLK_621_TRUE 0x01c4 /* cpu clock ratio mode */ /* Reset controls. */ @@ -288,5 +296,23 @@ extern void zy7_slcr_preload_pl(void); extern void zy7_slcr_postload_pl(int en_level_shifters); extern int cgem_set_ref_clk(int unit, int frequency); + +/* Should be consistent with SRCSEL field of FPGAx_CLK_CTRL */ +#define ZY7_PL_FCLK_SRC_IO 0 +#define ZY7_PL_FCLK_SRC_IO_ALT 1 /* ZY7_PL_FCLK_SRC_IO is b0x */ +#define ZY7_PL_FCLK_SRC_ARM 2 +#define ZY7_PL_FCLK_SRC_DDR 3 + +int zy7_pl_fclk_set_source(int unit, int source); +int zy7_pl_fclk_get_source(int unit); +int zy7_pl_fclk_set_freq(int unit, int freq); +int zy7_pl_fclk_get_freq(int unit); +int zy7_pl_fclk_enable(int unit); +int zy7_pl_fclk_disable(int unit); +int zy7_pl_fclk_enabled(int unit); +int zy7_pl_level_shifters_enabled(void); +void zy7_pl_level_shifters_enable(void); +void zy7_pl_level_shifters_disable(void); + #endif #endif /* _ZY7_SLCR_H_ */ |