summaryrefslogtreecommitdiff
path: root/arch/arm/cpu
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2015-04-29 06:46:33 -0400
committerTom Rini <trini@konsulko.com>2015-04-29 06:46:33 -0400
commitace97d26176a3ebc9ec07738450de93eea35975c (patch)
tree7de5b3cdc2f269ae1426540ae9f74b420423f132 /arch/arm/cpu
parent1692515e51a190b2ad1e2c54fdaa15fbb8387ba7 (diff)
parent5ca269a4df21a7e326eb3b3f7788177d064fe782 (diff)
Merge branch 'zynq' of git://www.denx.de/git/u-boot-microblaze
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r--arch/arm/cpu/armv7/Makefile1
-rw-r--r--arch/arm/cpu/armv7/zynq/Kconfig39
-rw-r--r--arch/arm/cpu/armv7/zynq/Makefile17
-rw-r--r--arch/arm/cpu/armv7/zynq/clk.c664
-rw-r--r--arch/arm/cpu/armv7/zynq/config.mk7
-rw-r--r--arch/arm/cpu/armv7/zynq/cpu.c67
-rw-r--r--arch/arm/cpu/armv7/zynq/ddrc.c50
-rw-r--r--arch/arm/cpu/armv7/zynq/lowlevel_init.S26
-rw-r--r--arch/arm/cpu/armv7/zynq/slcr.c196
-rw-r--r--arch/arm/cpu/armv7/zynq/spl.c90
-rw-r--r--arch/arm/cpu/armv7/zynq/timer.c166
-rw-r--r--arch/arm/cpu/armv7/zynq/u-boot-spl.lds62
-rw-r--r--arch/arm/cpu/armv7/zynq/u-boot.lds105
-rw-r--r--arch/arm/cpu/armv8/zynqmp/Makefile1
-rw-r--r--arch/arm/cpu/armv8/zynqmp/clk.c3
-rw-r--r--arch/arm/cpu/armv8/zynqmp/cpu.c166
-rw-r--r--arch/arm/cpu/armv8/zynqmp/mp.c242
17 files changed, 412 insertions, 1490 deletions
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index e6249f13c8..fcccd0c9ba 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -56,4 +56,3 @@ obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_U8500) += u8500/
obj-$(CONFIG_VF610) += vf610/
-obj-$(CONFIG_ZYNQ) += zynq/
diff --git a/arch/arm/cpu/armv7/zynq/Kconfig b/arch/arm/cpu/armv7/zynq/Kconfig
deleted file mode 100644
index 3a52535ce0..0000000000
--- a/arch/arm/cpu/armv7/zynq/Kconfig
+++ /dev/null
@@ -1,39 +0,0 @@
-if ZYNQ
-
-choice
- prompt "Xilinx Zynq board select"
-
-config TARGET_ZYNQ_ZED
- bool "Zynq ZedBoard"
-
-config TARGET_ZYNQ_MICROZED
- bool "Zynq MicroZed"
-
-config TARGET_ZYNQ_ZC70X
- bool "Zynq ZC702/ZC706 Board"
-
-config TARGET_ZYNQ_ZC770
- bool "Zynq ZC770 Board"
-
-config TARGET_ZYNQ_ZYBO
- bool "Zynq Zybo Board"
-
-endchoice
-
-config SYS_BOARD
- default "zynq"
-
-config SYS_VENDOR
- default "xilinx"
-
-config SYS_SOC
- default "zynq"
-
-config SYS_CONFIG_NAME
- default "zynq_zed" if TARGET_ZYNQ_ZED
- default "zynq_microzed" if TARGET_ZYNQ_MICROZED
- default "zynq_zc70x" if TARGET_ZYNQ_ZC70X
- default "zynq_zc770" if TARGET_ZYNQ_ZC770
- default "zynq_zybo" if TARGET_ZYNQ_ZYBO
-
-endif
diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/cpu/armv7/zynq/Makefile
deleted file mode 100644
index 901f2ce4cb..0000000000
--- a/arch/arm/cpu/armv7/zynq/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# (C) Copyright 2000-2003
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# (C) Copyright 2008
-# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
-#
-# SPDX-License-Identifier: GPL-2.0+
-#
-
-obj-y := timer.o
-obj-y += cpu.o
-obj-y += ddrc.o
-obj-y += slcr.o
-obj-y += clk.o
-obj-y += lowlevel_init.o
-obj-$(CONFIG_SPL_BUILD) += spl.o
diff --git a/arch/arm/cpu/armv7/zynq/clk.c b/arch/arm/cpu/armv7/zynq/clk.c
deleted file mode 100644
index d2885dc2b9..0000000000
--- a/arch/arm/cpu/armv7/zynq/clk.c
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * Copyright (C) 2013 Soren Brinkmann <soren.brinkmann@xilinx.com>
- * Copyright (C) 2013 Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h>
-#include <errno.h>
-#include <clk.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/clk.h>
-
-/* Board oscillator frequency */
-#ifndef CONFIG_ZYNQ_PS_CLK_FREQ
-# define CONFIG_ZYNQ_PS_CLK_FREQ 33333333UL
-#endif
-
-/* Register bitfield defines */
-#define PLLCTRL_FBDIV_MASK 0x7f000
-#define PLLCTRL_FBDIV_SHIFT 12
-#define PLLCTRL_BPFORCE_MASK (1 << 4)
-#define PLLCTRL_PWRDWN_MASK 2
-#define PLLCTRL_PWRDWN_SHIFT 1
-#define PLLCTRL_RESET_MASK 1
-#define PLLCTRL_RESET_SHIFT 0
-
-#define ZYNQ_CLK_MAXDIV 0x3f
-#define CLK_CTRL_DIV1_SHIFT 20
-#define CLK_CTRL_DIV1_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV1_SHIFT)
-#define CLK_CTRL_DIV0_SHIFT 8
-#define CLK_CTRL_DIV0_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV0_SHIFT)
-#define CLK_CTRL_SRCSEL_SHIFT 4
-#define CLK_CTRL_SRCSEL_MASK (0x3 << CLK_CTRL_SRCSEL_SHIFT)
-
-#define CLK_CTRL_DIV2X_SHIFT 26
-#define CLK_CTRL_DIV2X_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV2X_SHIFT)
-#define CLK_CTRL_DIV3X_SHIFT 20
-#define CLK_CTRL_DIV3X_MASK (ZYNQ_CLK_MAXDIV << CLK_CTRL_DIV3X_SHIFT)
-
-#define ZYNQ_CLKMUX_SEL_0 0
-#define ZYNQ_CLKMUX_SEL_1 1
-#define ZYNQ_CLKMUX_SEL_2 2
-#define ZYNQ_CLKMUX_SEL_3 3
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct clk;
-
-/**
- * struct clk_ops:
- * @set_rate: Function pointer to set_rate() implementation
- * @get_rate: Function pointer to get_rate() implementation
- */
-struct clk_ops {
- int (*set_rate)(struct clk *clk, unsigned long rate);
- unsigned long (*get_rate)(struct clk *clk);
-};
-
-/**
- * struct clk:
- * @name: Clock name
- * @frequency: Currenct frequency
- * @parent: Parent clock
- * @flags: Clock flags
- * @reg: Clock control register
- * @ops: Clock operations
- */
-struct clk {
- char *name;
- unsigned long frequency;
- enum zynq_clk parent;
- unsigned int flags;
- u32 *reg;
- struct clk_ops ops;
-};
-#define ZYNQ_CLK_FLAGS_HAS_2_DIVS 1
-
-static struct clk clks[clk_max];
-
-/**
- * __zynq_clk_cpu_get_parent() - Decode clock multiplexer
- * @srcsel: Mux select value
- * Returns the clock identifier associated with the selected mux input.
- */
-static int __zynq_clk_cpu_get_parent(unsigned int srcsel)
-{
- unsigned int ret;
-
- switch (srcsel) {
- case ZYNQ_CLKMUX_SEL_0:
- case ZYNQ_CLKMUX_SEL_1:
- ret = armpll_clk;
- break;
- case ZYNQ_CLKMUX_SEL_2:
- ret = ddrpll_clk;
- break;
- case ZYNQ_CLKMUX_SEL_3:
- ret = iopll_clk;
- break;
- default:
- ret = armpll_clk;
- break;
- }
-
- return ret;
-}
-
-/**
- * ddr2x_get_rate() - Get clock rate of DDR2x clock
- * @clk: Clock handle
- * Returns the current clock rate of @clk.
- */
-static unsigned long ddr2x_get_rate(struct clk *clk)
-{
- u32 clk_ctrl = readl(clk->reg);
- u32 div = (clk_ctrl & CLK_CTRL_DIV2X_MASK) >> CLK_CTRL_DIV2X_SHIFT;
-
- return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
-}
-
-/**
- * ddr3x_get_rate() - Get clock rate of DDR3x clock
- * @clk: Clock handle
- * Returns the current clock rate of @clk.
- */
-static unsigned long ddr3x_get_rate(struct clk *clk)
-{
- u32 clk_ctrl = readl(clk->reg);
- u32 div = (clk_ctrl & CLK_CTRL_DIV3X_MASK) >> CLK_CTRL_DIV3X_SHIFT;
-
- return DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div);
-}
-
-static void init_ddr_clocks(void)
-{
- u32 div0, div1;
- unsigned long prate = zynq_clk_get_rate(ddrpll_clk);
- u32 clk_ctrl = readl(&slcr_base->ddr_clk_ctrl);
-
- /* DDR2x */
- clks[ddr2x_clk].reg = &slcr_base->ddr_clk_ctrl;
- clks[ddr2x_clk].parent = ddrpll_clk;
- clks[ddr2x_clk].name = "ddr_2x";
- clks[ddr2x_clk].frequency = ddr2x_get_rate(&clks[ddr2x_clk]);
- clks[ddr2x_clk].ops.get_rate = ddr2x_get_rate;
-
- /* DDR3x */
- clks[ddr3x_clk].reg = &slcr_base->ddr_clk_ctrl;
- clks[ddr3x_clk].parent = ddrpll_clk;
- clks[ddr3x_clk].name = "ddr_3x";
- clks[ddr3x_clk].frequency = ddr3x_get_rate(&clks[ddr3x_clk]);
- clks[ddr3x_clk].ops.get_rate = ddr3x_get_rate;
-
- /* DCI */
- clk_ctrl = readl(&slcr_base->dci_clk_ctrl);
- div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
- clks[dci_clk].reg = &slcr_base->dci_clk_ctrl;
- clks[dci_clk].parent = ddrpll_clk;
- clks[dci_clk].frequency = DIV_ROUND_CLOSEST(
- DIV_ROUND_CLOSEST(prate, div0), div1);
- clks[dci_clk].name = "dci";
-
- gd->bd->bi_ddr_freq = clks[ddr3x_clk].frequency / 1000000;
-}
-
-static void init_cpu_clocks(void)
-{
- int clk_621;
- u32 reg, div, srcsel;
- enum zynq_clk parent;
-
- reg = readl(&slcr_base->arm_clk_ctrl);
- clk_621 = readl(&slcr_base->clk_621_true) & 1;
- div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
- parent = __zynq_clk_cpu_get_parent(srcsel);
-
- /* cpu clocks */
- clks[cpu_6or4x_clk].reg = &slcr_base->arm_clk_ctrl;
- clks[cpu_6or4x_clk].parent = parent;
- clks[cpu_6or4x_clk].frequency = DIV_ROUND_CLOSEST(
- zynq_clk_get_rate(parent), div);
- clks[cpu_6or4x_clk].name = "cpu_6or4x";
-
- clks[cpu_3or2x_clk].reg = &slcr_base->arm_clk_ctrl;
- clks[cpu_3or2x_clk].parent = cpu_6or4x_clk;
- clks[cpu_3or2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) / 2;
- clks[cpu_3or2x_clk].name = "cpu_3or2x";
-
- clks[cpu_2x_clk].reg = &slcr_base->arm_clk_ctrl;
- clks[cpu_2x_clk].parent = cpu_6or4x_clk;
- clks[cpu_2x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
- (2 + clk_621);
- clks[cpu_2x_clk].name = "cpu_2x";
-
- clks[cpu_1x_clk].reg = &slcr_base->arm_clk_ctrl;
- clks[cpu_1x_clk].parent = cpu_6or4x_clk;
- clks[cpu_1x_clk].frequency = zynq_clk_get_rate(cpu_6or4x_clk) /
- (4 + 2 * clk_621);
- clks[cpu_1x_clk].name = "cpu_1x";
-}
-
-/**
- * periph_calc_two_divs() - Calculate clock dividers
- * @cur_rate: Current clock rate
- * @tgt_rate: Target clock rate
- * @prate: Parent clock rate
- * @div0: First divider (output)
- * @div1: Second divider (output)
- * Returns the actual clock rate possible.
- *
- * Calculates clock dividers for clocks with two 6-bit dividers.
- */
-static unsigned long periph_calc_two_divs(unsigned long cur_rate,
- unsigned long tgt_rate, unsigned long prate, u32 *div0,
- u32 *div1)
-{
- long err, best_err = (long)(~0UL >> 1);
- unsigned long rate, best_rate = 0;
- u32 d0, d1;
-
- for (d0 = 1; d0 <= ZYNQ_CLK_MAXDIV; d0++) {
- for (d1 = 1; d1 <= ZYNQ_CLK_MAXDIV >> 1; d1++) {
- rate = DIV_ROUND_CLOSEST(DIV_ROUND_CLOSEST(prate, d0),
- d1);
- err = abs(rate - tgt_rate);
-
- if (err < best_err) {
- *div0 = d0;
- *div1 = d1;
- best_err = err;
- best_rate = rate;
- }
- }
- }
-
- return best_rate;
-}
-
-/**
- * zynq_clk_periph_set_rate() - Set clock rate
- * @clk: Handle of the peripheral clock
- * @rate: New clock rate
- * Sets the clock frequency of @clk to @rate. Returns zero on success.
- */
-static int zynq_clk_periph_set_rate(struct clk *clk,
- unsigned long rate)
-{
- u32 ctrl, div0 = 0, div1 = 0;
- unsigned long prate, new_rate, cur_rate = clk->frequency;
-
- ctrl = readl(clk->reg);
- prate = zynq_clk_get_rate(clk->parent);
- ctrl &= ~CLK_CTRL_DIV0_MASK;
-
- if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS) {
- ctrl &= ~CLK_CTRL_DIV1_MASK;
- new_rate = periph_calc_two_divs(cur_rate, rate, prate, &div0,
- &div1);
- ctrl |= div1 << CLK_CTRL_DIV1_SHIFT;
- } else {
- div0 = DIV_ROUND_CLOSEST(prate, rate);
- div0 &= ZYNQ_CLK_MAXDIV;
- new_rate = DIV_ROUND_CLOSEST(rate, div0);
- }
-
- /* write new divs to hardware */
- ctrl |= div0 << CLK_CTRL_DIV0_SHIFT;
- writel(ctrl, clk->reg);
-
- /* update frequency in clk framework */
- clk->frequency = new_rate;
-
- return 0;
-}
-
-/**
- * zynq_clk_periph_get_rate() - Get clock rate
- * @clk: Handle of the peripheral clock
- * Returns the current clock rate of @clk.
- */
-static unsigned long zynq_clk_periph_get_rate(struct clk *clk)
-{
- u32 clk_ctrl = readl(clk->reg);
- u32 div0 = (clk_ctrl & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- u32 div1 = 1;
-
- if (clk->flags & ZYNQ_CLK_FLAGS_HAS_2_DIVS)
- div1 = (clk_ctrl & CLK_CTRL_DIV1_MASK) >> CLK_CTRL_DIV1_SHIFT;
-
- /* a register value of zero == division by 1 */
- if (!div0)
- div0 = 1;
- if (!div1)
- div1 = 1;
-
- return
- DIV_ROUND_CLOSEST(
- DIV_ROUND_CLOSEST(zynq_clk_get_rate(clk->parent), div0),
- div1);
-}
-
-/**
- * __zynq_clk_periph_get_parent() - Decode clock multiplexer
- * @srcsel: Mux select value
- * Returns the clock identifier associated with the selected mux input.
- */
-static enum zynq_clk __zynq_clk_periph_get_parent(u32 srcsel)
-{
- switch (srcsel) {
- case ZYNQ_CLKMUX_SEL_0:
- case ZYNQ_CLKMUX_SEL_1:
- return iopll_clk;
- case ZYNQ_CLKMUX_SEL_2:
- return armpll_clk;
- case ZYNQ_CLKMUX_SEL_3:
- return ddrpll_clk;
- default:
- return 0;
- }
-}
-
-/**
- * zynq_clk_periph_get_parent() - Decode clock multiplexer
- * @clk: Clock handle
- * Returns the clock identifier associated with the selected mux input.
- */
-static enum zynq_clk zynq_clk_periph_get_parent(struct clk *clk)
-{
- u32 clk_ctrl = readl(clk->reg);
- u32 srcsel = (clk_ctrl & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
-
- return __zynq_clk_periph_get_parent(srcsel);
-}
-
-/**
- * zynq_clk_register_periph_clk() - Set up a peripheral clock with the framework
- * @clk: Pointer to struct clk for the clock
- * @ctrl: Clock control register
- * @name: PLL name
- * @two_divs: Indicates whether the clock features one or two dividers
- */
-static int zynq_clk_register_periph_clk(struct clk *clk, u32 *ctrl, char *name,
- bool two_divs)
-{
- clk->name = name;
- clk->reg = ctrl;
- if (two_divs)
- clk->flags = ZYNQ_CLK_FLAGS_HAS_2_DIVS;
- clk->parent = zynq_clk_periph_get_parent(clk);
- clk->frequency = zynq_clk_periph_get_rate(clk);
- clk->ops.get_rate = zynq_clk_periph_get_rate;
- clk->ops.set_rate = zynq_clk_periph_set_rate;
-
- return 0;
-}
-
-static void init_periph_clocks(void)
-{
- zynq_clk_register_periph_clk(&clks[gem0_clk], &slcr_base->gem0_clk_ctrl,
- "gem0", 1);
- zynq_clk_register_periph_clk(&clks[gem1_clk], &slcr_base->gem1_clk_ctrl,
- "gem1", 1);
-
- zynq_clk_register_periph_clk(&clks[smc_clk], &slcr_base->smc_clk_ctrl,
- "smc", 0);
-
- zynq_clk_register_periph_clk(&clks[lqspi_clk],
- &slcr_base->lqspi_clk_ctrl, "lqspi", 0);
-
- zynq_clk_register_periph_clk(&clks[sdio0_clk],
- &slcr_base->sdio_clk_ctrl, "sdio0", 0);
- zynq_clk_register_periph_clk(&clks[sdio1_clk],
- &slcr_base->sdio_clk_ctrl, "sdio1", 0);
-
- zynq_clk_register_periph_clk(&clks[spi0_clk], &slcr_base->spi_clk_ctrl,
- "spi0", 0);
- zynq_clk_register_periph_clk(&clks[spi1_clk], &slcr_base->spi_clk_ctrl,
- "spi1", 0);
-
- zynq_clk_register_periph_clk(&clks[uart0_clk],
- &slcr_base->uart_clk_ctrl, "uart0", 0);
- zynq_clk_register_periph_clk(&clks[uart1_clk],
- &slcr_base->uart_clk_ctrl, "uart1", 0);
-
- zynq_clk_register_periph_clk(&clks[dbg_trc_clk],
- &slcr_base->dbg_clk_ctrl, "dbg_trc", 0);
- zynq_clk_register_periph_clk(&clks[dbg_apb_clk],
- &slcr_base->dbg_clk_ctrl, "dbg_apb", 0);
-
- zynq_clk_register_periph_clk(&clks[pcap_clk],
- &slcr_base->pcap_clk_ctrl, "pcap", 0);
-
- zynq_clk_register_periph_clk(&clks[fclk0_clk],
- &slcr_base->fpga0_clk_ctrl, "fclk0", 1);
- zynq_clk_register_periph_clk(&clks[fclk1_clk],
- &slcr_base->fpga1_clk_ctrl, "fclk1", 1);
- zynq_clk_register_periph_clk(&clks[fclk2_clk],
- &slcr_base->fpga2_clk_ctrl, "fclk2", 1);
- zynq_clk_register_periph_clk(&clks[fclk3_clk],
- &slcr_base->fpga3_clk_ctrl, "fclk3", 1);
-}
-
-/**
- * zynq_clk_register_aper_clk() - Set up a APER clock with the framework
- * @clk: Pointer to struct clk for the clock
- * @ctrl: Clock control register
- * @name: PLL name
- */
-static void zynq_clk_register_aper_clk(struct clk *clk, u32 *ctrl, char *name)
-{
- clk->name = name;
- clk->reg = ctrl;
- clk->parent = cpu_1x_clk;
- clk->frequency = zynq_clk_get_rate(clk->parent);
-}
-
-static void init_aper_clocks(void)
-{
- zynq_clk_register_aper_clk(&clks[usb0_aper_clk],
- &slcr_base->aper_clk_ctrl, "usb0_aper");
- zynq_clk_register_aper_clk(&clks[usb1_aper_clk],
- &slcr_base->aper_clk_ctrl, "usb1_aper");
-
- zynq_clk_register_aper_clk(&clks[gem0_aper_clk],
- &slcr_base->aper_clk_ctrl, "gem0_aper");
- zynq_clk_register_aper_clk(&clks[gem1_aper_clk],
- &slcr_base->aper_clk_ctrl, "gem1_aper");
-
- zynq_clk_register_aper_clk(&clks[sdio0_aper_clk],
- &slcr_base->aper_clk_ctrl, "sdio0_aper");
- zynq_clk_register_aper_clk(&clks[sdio1_aper_clk],
- &slcr_base->aper_clk_ctrl, "sdio1_aper");
-
- zynq_clk_register_aper_clk(&clks[spi0_aper_clk],
- &slcr_base->aper_clk_ctrl, "spi0_aper");
- zynq_clk_register_aper_clk(&clks[spi1_aper_clk],
- &slcr_base->aper_clk_ctrl, "spi1_aper");
-
- zynq_clk_register_aper_clk(&clks[can0_aper_clk],
- &slcr_base->aper_clk_ctrl, "can0_aper");
- zynq_clk_register_aper_clk(&clks[can1_aper_clk],
- &slcr_base->aper_clk_ctrl, "can1_aper");
-
- zynq_clk_register_aper_clk(&clks[i2c0_aper_clk],
- &slcr_base->aper_clk_ctrl, "i2c0_aper");
- zynq_clk_register_aper_clk(&clks[i2c1_aper_clk],
- &slcr_base->aper_clk_ctrl, "i2c1_aper");
-
- zynq_clk_register_aper_clk(&clks[uart0_aper_clk],
- &slcr_base->aper_clk_ctrl, "uart0_aper");
- zynq_clk_register_aper_clk(&clks[uart1_aper_clk],
- &slcr_base->aper_clk_ctrl, "uart1_aper");
-
- zynq_clk_register_aper_clk(&clks[gpio_aper_clk],
- &slcr_base->aper_clk_ctrl, "gpio_aper");
-
- zynq_clk_register_aper_clk(&clks[lqspi_aper_clk],
- &slcr_base->aper_clk_ctrl, "lqspi_aper");
-
- zynq_clk_register_aper_clk(&clks[smc_aper_clk],
- &slcr_base->aper_clk_ctrl, "smc_aper");
-}
-
-/**
- * __zynq_clk_pll_get_rate() - Get PLL rate
- * @addr: Address of the PLL's control register
- * Returns the current PLL output rate.
- */
-static unsigned long __zynq_clk_pll_get_rate(u32 *addr)
-{
- u32 reg, mul, bypass;
-
- reg = readl(addr);
- bypass = reg & PLLCTRL_BPFORCE_MASK;
- if (bypass)
- mul = 1;
- else
- mul = (reg & PLLCTRL_FBDIV_MASK) >> PLLCTRL_FBDIV_SHIFT;
-
- return CONFIG_ZYNQ_PS_CLK_FREQ * mul;
-}
-
-/**
- * zynq_clk_pll_get_rate() - Get PLL rate
- * @pll: Handle of the PLL
- * Returns the current clock rate of @pll.
- */
-static unsigned long zynq_clk_pll_get_rate(struct clk *pll)
-{
- return __zynq_clk_pll_get_rate(pll->reg);
-}
-
-/**
- * zynq_clk_register_pll() - Set up a PLL with the framework
- * @clk: Pointer to struct clk for the PLL
- * @ctrl: PLL control register
- * @name: PLL name
- * @prate: PLL input clock rate
- */
-static void zynq_clk_register_pll(struct clk *clk, u32 *ctrl, char *name,
- unsigned long prate)
-{
- clk->name = name;
- clk->reg = ctrl;
- clk->frequency = zynq_clk_pll_get_rate(clk);
- clk->ops.get_rate = zynq_clk_pll_get_rate;
-}
-
-/**
- * clkid_2_register() - Get clock control register
- * @id: Clock identifier of one of the PLLs
- * Returns the address of the requested PLL's control register.
- */
-static u32 *clkid_2_register(enum zynq_clk id)
-{
- switch (id) {
- case armpll_clk:
- return &slcr_base->arm_pll_ctrl;
- case ddrpll_clk:
- return &slcr_base->ddr_pll_ctrl;
- case iopll_clk:
- return &slcr_base->io_pll_ctrl;
- default:
- return &slcr_base->io_pll_ctrl;
- }
-}
-
-/* API */
-/**
- * zynq_clk_early_init() - Early init for the clock framework
- *
- * This function is called from before relocation and sets up the CPU clock
- * frequency in the global data struct.
- */
-void zynq_clk_early_init(void)
-{
- u32 reg = readl(&slcr_base->arm_clk_ctrl);
- u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
- enum zynq_clk parent = __zynq_clk_cpu_get_parent(srcsel);
- u32 *pllreg = clkid_2_register(parent);
- unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
-
- if (!div)
- div = 1;
-
- gd->cpu_clk = DIV_ROUND_CLOSEST(prate, div);
-}
-
-/**
- * get_uart_clk() - Get UART input frequency
- * @dev_index: UART ID
- * Returns UART input clock frequency in Hz.
- *
- * Compared to zynq_clk_get_rate() this function is designed to work before
- * relocation and can be called when the serial UART is set up.
- */
-unsigned long get_uart_clk(int dev_index)
-{
- u32 reg = readl(&slcr_base->uart_clk_ctrl);
- u32 div = (reg & CLK_CTRL_DIV0_MASK) >> CLK_CTRL_DIV0_SHIFT;
- u32 srcsel = (reg & CLK_CTRL_SRCSEL_MASK) >> CLK_CTRL_SRCSEL_SHIFT;
- enum zynq_clk parent = __zynq_clk_periph_get_parent(srcsel);
- u32 *pllreg = clkid_2_register(parent);
- unsigned long prate = __zynq_clk_pll_get_rate(pllreg);
-
- if (!div)
- div = 1;
-
- return DIV_ROUND_CLOSEST(prate, div);
-}
-
-/**
- * set_cpu_clk_info() - Initialize clock framework
- * Always returns zero.
- *
- * This function is called from common code after relocation and sets up the
- * clock framework. The framework must not be used before this function had been
- * called.
- */
-int set_cpu_clk_info(void)
-{
- zynq_clk_register_pll(&clks[armpll_clk], &slcr_base->arm_pll_ctrl,
- "armpll", CONFIG_ZYNQ_PS_CLK_FREQ);
- zynq_clk_register_pll(&clks[ddrpll_clk], &slcr_base->ddr_pll_ctrl,
- "ddrpll", CONFIG_ZYNQ_PS_CLK_FREQ);
- zynq_clk_register_pll(&clks[iopll_clk], &slcr_base->io_pll_ctrl,
- "iopll", CONFIG_ZYNQ_PS_CLK_FREQ);
-
- init_ddr_clocks();
- init_cpu_clocks();
- init_periph_clocks();
- init_aper_clocks();
-
- gd->bd->bi_arm_freq = gd->cpu_clk / 1000000;
- gd->bd->bi_dsp_freq = 0;
-
- return 0;
-}
-
-/**
- * zynq_clk_get_rate() - Get clock rate
- * @clk: Clock identifier
- * Returns the current clock rate of @clk on success or zero for an invalid
- * clock id.
- */
-unsigned long zynq_clk_get_rate(enum zynq_clk clk)
-{
- if (clk < 0 || clk >= clk_max)
- return 0;
-
- return clks[clk].frequency;
-}
-
-/**
- * zynq_clk_set_rate() - Set clock rate
- * @clk: Clock identifier
- * @rate: Requested clock rate
- * Passes on the return value from the clock's set_rate() function or negative
- * errno.
- */
-int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate)
-{
- if (clk < 0 || clk >= clk_max)
- return -ENODEV;
-
- if (clks[clk].ops.set_rate)
- return clks[clk].ops.set_rate(&clks[clk], rate);
-
- return -ENXIO;
-}
-
-/**
- * zynq_clk_get_name() - Get clock name
- * @clk: Clock identifier
- * Returns the name of @clk.
- */
-const char *zynq_clk_get_name(enum zynq_clk clk)
-{
- return clks[clk].name;
-}
-
-/**
- * soc_clk_dump() - Print clock frequencies
- * Returns zero on success
- *
- * Implementation for the clk dump command.
- */
-int soc_clk_dump(void)
-{
- int i;
-
- printf("clk\t\tfrequency\n");
- for (i = 0; i < clk_max; i++) {
- const char *name = zynq_clk_get_name(i);
- if (name)
- printf("%10s%20lu\n", name, zynq_clk_get_rate(i));
- }
-
- return 0;
-}
diff --git a/arch/arm/cpu/armv7/zynq/config.mk b/arch/arm/cpu/armv7/zynq/config.mk
deleted file mode 100644
index 778a377e8a..0000000000
--- a/arch/arm/cpu/armv7/zynq/config.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Copyright (C) 2013 - 2015 Xilinx, Inc. All rights reserved.
-#
-# SPDX-License-Identifier: GPL-2.0
-#
-# Allow NEON instructions (needed for lowlevel_init.S with GNU toolchain)
-PLATFORM_RELFLAGS += -mfpu=neon
diff --git a/arch/arm/cpu/armv7/zynq/cpu.c b/arch/arm/cpu/armv7/zynq/cpu.c
deleted file mode 100644
index 914b1feb68..0000000000
--- a/arch/arm/cpu/armv7/zynq/cpu.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2012 Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/clk.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/hardware.h>
-
-#define ZYNQ_SILICON_VER_MASK 0xF0000000
-#define ZYNQ_SILICON_VER_SHIFT 28
-
-int arch_cpu_init(void)
-{
- zynq_slcr_unlock();
-#ifndef CONFIG_SPL_BUILD
- /* Device config APB, unlock the PCAP */
- writel(0x757BDF0D, &devcfg_base->unlock);
- writel(0xFFFFFFFF, &devcfg_base->rom_shadow);
-
-#if (CONFIG_SYS_SDRAM_BASE == 0)
- /* remap DDR to zero, FILTERSTART */
- writel(0, &scu_base->filter_start);
-
- /* OCM_CFG, Mask out the ROM, map ram into upper addresses */
- writel(0x1F, &slcr_base->ocm_cfg);
- /* FPGA_RST_CTRL, clear resets on AXI fabric ports */
- writel(0x0, &slcr_base->fpga_rst_ctrl);
- /* Set urgent bits with register */
- writel(0x0, &slcr_base->ddr_urgent_sel);
- /* Urgent write, ports S2/S3 */
- writel(0xC, &slcr_base->ddr_urgent);
-#endif
-#endif
- zynq_clk_early_init();
- zynq_slcr_lock();
-
- return 0;
-}
-
-unsigned int zynq_get_silicon_version(void)
-{
- unsigned int ver;
-
- ver = (readl(&devcfg_base->mctrl) &
- ZYNQ_SILICON_VER_MASK) >> ZYNQ_SILICON_VER_SHIFT;
-
- return ver;
-}
-
-void reset_cpu(ulong addr)
-{
- zynq_slcr_cpu_reset();
- while (1)
- ;
-}
-
-#ifndef CONFIG_SYS_DCACHE_OFF
-void enable_caches(void)
-{
- /* Enable D-cache. I-cache is already enabled in start.S */
- dcache_enable();
-}
-#endif
diff --git a/arch/arm/cpu/armv7/zynq/ddrc.c b/arch/arm/cpu/armv7/zynq/ddrc.c
deleted file mode 100644
index 5b20accbcb..0000000000
--- a/arch/arm/cpu/armv7/zynq/ddrc.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 - 2013 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2012 - 2013 Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/hardware.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-/* Control regsiter bitfield definitions */
-#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK 0xC
-#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT 2
-#define ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT 1
-
-/* ECC scrub regsiter definitions */
-#define ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK 0x7
-#define ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED 0x4
-
-void zynq_ddrc_init(void)
-{
- u32 width, ecctype;
-
- width = readl(&ddrc_base->ddrc_ctrl);
- width = (width & ZYNQ_DDRC_CTRLREG_BUSWIDTH_MASK) >>
- ZYNQ_DDRC_CTRLREG_BUSWIDTH_SHIFT;
- ecctype = (readl(&ddrc_base->ecc_scrub) &
- ZYNQ_DDRC_ECC_SCRUBREG_ECC_MODE_MASK);
-
- /* ECC is enabled when memory is in 16bit mode and it is enabled */
- if ((ecctype == ZYNQ_DDRC_ECC_SCRUBREG_ECCMODE_SECDED) &&
- (width == ZYNQ_DDRC_CTRLREG_BUSWIDTH_16BIT)) {
- puts("ECC enabled ");
- /*
- * Clear the first 1MB because it is not initialized from
- * first stage bootloader. To get ECC to work all memory has
- * been initialized by writing any value.
- */
- /* cppcheck-suppress nullPointer */
- memset((void *)0, 0, 1 * 1024 * 1024);
-
- gd->ram_size /= 2;
- } else {
- puts("ECC disabled ");
- }
-}
diff --git a/arch/arm/cpu/armv7/zynq/lowlevel_init.S b/arch/arm/cpu/armv7/zynq/lowlevel_init.S
deleted file mode 100644
index 6d714b711c..0000000000
--- a/arch/arm/cpu/armv7/zynq/lowlevel_init.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <asm-offsets.h>
-#include <config.h>
-#include <linux/linkage.h>
-
-ENTRY(lowlevel_init)
-
- /* Enable the the VFP */
- mrc p15, 0, r1, c1, c0, 2
- orr r1, r1, #(0x3 << 20)
- orr r1, r1, #(0x3 << 20)
- mcr p15, 0, r1, c1, c0, 2
- isb
- fmrx r1, FPEXC
- orr r1,r1, #(1<<30)
- fmxr FPEXC, r1
-
- /* Move back to caller */
- mov pc, lr
-
-ENDPROC(lowlevel_init)
diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/cpu/armv7/zynq/slcr.c
deleted file mode 100644
index 2521589c07..0000000000
--- a/arch/arm/cpu/armv7/zynq/slcr.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2013 Xilinx Inc.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <malloc.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/sys_proto.h>
-#include <asm/arch/clk.h>
-
-#define SLCR_LOCK_MAGIC 0x767B
-#define SLCR_UNLOCK_MAGIC 0xDF0D
-
-#define SLCR_USB_L1_SEL 0x04
-
-#define SLCR_IDCODE_MASK 0x1F000
-#define SLCR_IDCODE_SHIFT 12
-
-/*
- * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
- *
- * @peri_name: Name of the peripheral for checking MIO status
- * @get_pins: Pointer to array of get pin for this peripheral
- * @num_pins: Number of pins for this peripheral
- * @mask: Mask value
- * @check_val: Required check value to get the status of periph
- */
-struct zynq_slcr_mio_get_status {
- const char *peri_name;
- const int *get_pins;
- int num_pins;
- u32 mask;
- u32 check_val;
-};
-
-static const int usb0_pins[] = {
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
-};
-
-static const int usb1_pins[] = {
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
-};
-
-static const struct zynq_slcr_mio_get_status mio_periphs[] = {
- {
- "usb0",
- usb0_pins,
- ARRAY_SIZE(usb0_pins),
- SLCR_USB_L1_SEL,
- SLCR_USB_L1_SEL,
- },
- {
- "usb1",
- usb1_pins,
- ARRAY_SIZE(usb1_pins),
- SLCR_USB_L1_SEL,
- SLCR_USB_L1_SEL,
- },
-};
-
-static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
-
-void zynq_slcr_lock(void)
-{
- if (!slcr_lock) {
- writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
- slcr_lock = 1;
- }
-}
-
-void zynq_slcr_unlock(void)
-{
- if (slcr_lock) {
- writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
- slcr_lock = 0;
- }
-}
-
-/* Reset the entire system */
-void zynq_slcr_cpu_reset(void)
-{
- /*
- * Unlock the SLCR then reset the system.
- * Note that this seems to require raw i/o
- * functions or there's a lockup?
- */
- zynq_slcr_unlock();
-
- /*
- * Clear 0x0F000000 bits of reboot status register to workaround
- * the FSBL not loading the bitstream after soft-reboot
- * This is a temporary solution until we know more.
- */
- clrbits_le32(&slcr_base->reboot_status, 0xF000000);
-
- writel(1, &slcr_base->pss_rst_ctrl);
-}
-
-/* Setup clk for network */
-void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
-{
- int ret;
-
- zynq_slcr_unlock();
-
- if (gem_id > 1) {
- printf("Non existing GEM id %d\n", gem_id);
- goto out;
- }
-
- ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
- if (ret)
- goto out;
-
- if (gem_id) {
- /* Configure GEM_RCLK_CTRL */
- writel(1, &slcr_base->gem1_rclk_ctrl);
- } else {
- /* Configure GEM_RCLK_CTRL */
- writel(1, &slcr_base->gem0_rclk_ctrl);
- }
- udelay(100000);
-out:
- zynq_slcr_lock();
-}
-
-void zynq_slcr_devcfg_disable(void)
-{
- zynq_slcr_unlock();
-
- /* Disable AXI interface by asserting FPGA resets */
- writel(0xF, &slcr_base->fpga_rst_ctrl);
-
- /* Set Level Shifters DT618760 */
- writel(0xA, &slcr_base->lvl_shftr_en);
-
- zynq_slcr_lock();
-}
-
-void zynq_slcr_devcfg_enable(void)
-{
- zynq_slcr_unlock();
-
- /* Set Level Shifters DT618760 */
- writel(0xF, &slcr_base->lvl_shftr_en);
-
- /* Enable AXI interface by de-asserting FPGA resets */
- writel(0x0, &slcr_base->fpga_rst_ctrl);
-
- zynq_slcr_lock();
-}
-
-u32 zynq_slcr_get_boot_mode(void)
-{
- /* Get the bootmode register value */
- return readl(&slcr_base->boot_mode);
-}
-
-u32 zynq_slcr_get_idcode(void)
-{
- return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >>
- SLCR_IDCODE_SHIFT;
-}
-
-/*
- * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
- *
- * @periph: Name of the peripheral
- *
- * Returns count to indicate the number of pins configured for the
- * given @periph.
- */
-int zynq_slcr_get_mio_pin_status(const char *periph)
-{
- const struct zynq_slcr_mio_get_status *mio_ptr;
- int val, i, j;
- int mio = 0;
-
- for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
- if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
- mio_ptr = &mio_periphs[i];
- for (j = 0; j < mio_ptr->num_pins; j++) {
- val = readl(&slcr_base->mio_pin
- [mio_ptr->get_pins[j]]);
- if ((val & mio_ptr->mask) == mio_ptr->check_val)
- mio++;
- }
- break;
- }
- }
-
- return mio;
-}
diff --git a/arch/arm/cpu/armv7/zynq/spl.c b/arch/arm/cpu/armv7/zynq/spl.c
deleted file mode 100644
index b80c35794a..0000000000
--- a/arch/arm/cpu/armv7/zynq/spl.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * (C) Copyright 2014 Xilinx, Inc. Michal Simek
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-#include <common.h>
-#include <spl.h>
-
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/spl.h>
-#include <asm/arch/sys_proto.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-void board_init_f(ulong dummy)
-{
- ps7_init();
-
- /* Clear the BSS. */
- memset(__bss_start, 0, __bss_end - __bss_start);
-
- preloader_console_init();
- arch_cpu_init();
- board_init_r(NULL, 0);
-}
-
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
-{
- board_init();
-}
-#endif
-
-u32 spl_boot_device(void)
-{
- u32 mode;
-
- switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) {
-#ifdef CONFIG_SPL_SPI_SUPPORT
- case ZYNQ_BM_QSPI:
- puts("qspi boot\n");
- mode = BOOT_DEVICE_SPI;
- break;
-#endif
- case ZYNQ_BM_NAND:
- mode = BOOT_DEVICE_NAND;
- break;
- case ZYNQ_BM_NOR:
- mode = BOOT_DEVICE_NOR;
- break;
-#ifdef CONFIG_SPL_MMC_SUPPORT
- case ZYNQ_BM_SD:
- puts("mmc boot\n");
- mode = BOOT_DEVICE_MMC1;
- break;
-#endif
- case ZYNQ_BM_JTAG:
- mode = BOOT_DEVICE_RAM;
- break;
- default:
- puts("Unsupported boot mode selected\n");
- hang();
- }
-
- return mode;
-}
-
-#ifdef CONFIG_SPL_MMC_SUPPORT
-u32 spl_boot_mode(void)
-{
- return MMCSD_MODE_FS;
-}
-#endif
-
-#ifdef CONFIG_SPL_OS_BOOT
-int spl_start_uboot(void)
-{
- /* boot linux */
- return 0;
-}
-#endif
-
-__weak void ps7_init(void)
-{
- /*
- * This function is overridden by the one in
- * board/xilinx/zynq/ps7_init.c, if it exists.
- */
-}
diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/cpu/armv7/zynq/timer.c
deleted file mode 100644
index 303dbcfcea..0000000000
--- a/arch/arm/cpu/armv7/zynq/timer.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved.
- *
- * (C) Copyright 2008
- * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
- *
- * (C) Copyright 2004
- * Philippe Robin, ARM Ltd. <philippe.robin@arm.com>
- *
- * (C) Copyright 2002-2004
- * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
- *
- * (C) Copyright 2003
- * Texas Instruments <www.ti.com>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Marius Groeger <mgroeger@sysgo.de>
- *
- * (C) Copyright 2002
- * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
- * Alex Zuepke <azu@sysgo.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <div64.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/arch/clk.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct scu_timer {
- u32 load; /* Timer Load Register */
- u32 counter; /* Timer Counter Register */
- u32 control; /* Timer Control Register */
-};
-
-static struct scu_timer *timer_base =
- (struct scu_timer *)ZYNQ_SCUTIMER_BASEADDR;
-
-#define SCUTIMER_CONTROL_PRESCALER_MASK 0x0000FF00 /* Prescaler */
-#define SCUTIMER_CONTROL_PRESCALER_SHIFT 8
-#define SCUTIMER_CONTROL_AUTO_RELOAD_MASK 0x00000002 /* Auto-reload */
-#define SCUTIMER_CONTROL_ENABLE_MASK 0x00000001 /* Timer enable */
-
-#define TIMER_LOAD_VAL 0xFFFFFFFF
-#define TIMER_PRESCALE 255
-
-int timer_init(void)
-{
- const u32 emask = SCUTIMER_CONTROL_AUTO_RELOAD_MASK |
- (TIMER_PRESCALE << SCUTIMER_CONTROL_PRESCALER_SHIFT) |
- SCUTIMER_CONTROL_ENABLE_MASK;
-
- gd->arch.timer_rate_hz = (gd->cpu_clk / 2) / (TIMER_PRESCALE + 1);
-
- /* Load the timer counter register */
- writel(0xFFFFFFFF, &timer_base->load);
-
- /*
- * Start the A9Timer device
- * Enable Auto reload mode, Clear prescaler control bits
- * Set prescaler value, Enable the decrementer
- */
- clrsetbits_le32(&timer_base->control, SCUTIMER_CONTROL_PRESCALER_MASK,
- emask);
-
- /* Reset time */
- gd->arch.lastinc = readl(&timer_base->counter) /
- (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
- gd->arch.tbl = 0;
-
- return 0;
-}
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-ulong get_timer_masked(void)
-{
- ulong now;
-
- now = readl(&timer_base->counter) /
- (gd->arch.timer_rate_hz / CONFIG_SYS_HZ);
-
- if (gd->arch.lastinc >= now) {
- /* Normal mode */
- gd->arch.tbl += gd->arch.lastinc - now;
- } else {
- /* We have an overflow ... */
- gd->arch.tbl += gd->arch.lastinc + TIMER_LOAD_VAL - now + 1;
- }
- gd->arch.lastinc = now;
-
- return gd->arch.tbl;
-}
-
-void __udelay(unsigned long usec)
-{
- u32 countticks;
- u32 timeend;
- u32 timediff;
- u32 timenow;
-
- if (usec == 0)
- return;
-
- countticks = lldiv(((unsigned long long)gd->arch.timer_rate_hz * usec),
- 1000000);
-
- /* decrementing timer */
- timeend = readl(&timer_base->counter) - countticks;
-
-#if TIMER_LOAD_VAL != 0xFFFFFFFF
- /* do not manage multiple overflow */
- if (countticks >= TIMER_LOAD_VAL)
- countticks = TIMER_LOAD_VAL - 1;
-#endif
-
- do {
- timenow = readl(&timer_base->counter);
-
- if (timenow >= timeend) {
- /* normal case */
- timediff = timenow - timeend;
- } else {
- if ((TIMER_LOAD_VAL - timeend + timenow) <=
- countticks) {
- /* overflow */
- timediff = TIMER_LOAD_VAL - timeend + timenow;
- } else {
- /* missed the exact match */
- break;
- }
- }
- } while (timediff > 0);
-}
-
-/* Timer without interrupts */
-ulong get_timer(ulong base)
-{
- return get_timer_masked() - base;
-}
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-unsigned long long get_ticks(void)
-{
- return get_timer(0);
-}
-
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk(void)
-{
- return CONFIG_SYS_HZ;
-}
diff --git a/arch/arm/cpu/armv7/zynq/u-boot-spl.lds b/arch/arm/cpu/armv7/zynq/u-boot-spl.lds
deleted file mode 100644
index 0f2f756f83..0000000000
--- a/arch/arm/cpu/armv7/zynq/u-boot-spl.lds
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2014 Xilinx, Inc. Michal Simek
- * Copyright (c) 2004-2008 Texas Instruments
- *
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
- LENGTH = CONFIG_SPL_MAX_SIZE }
-MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
- LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
-
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
- . = ALIGN(4);
- .text :
- {
- __image_copy_start = .;
- *(.vectors)
- CPUDIR/start.o (.text*)
- *(.text*)
- } > .sram
-
- . = ALIGN(4);
- .rodata : {
- *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
- } > .sram
-
- . = ALIGN(4);
- .data : {
- *(.data*)
- } > .sram
-
- . = ALIGN(4);
-
- . = .;
-
- __image_copy_end = .;
-
- _end = .;
-
- /* Move BSS section to RAM because of FAT */
- .bss (NOLOAD) : {
- __bss_start = .;
- *(.bss*)
- . = ALIGN(4);
- __bss_end = .;
- } > .sdram
-
- /DISCARD/ : { *(.dynsym) }
- /DISCARD/ : { *(.dynstr*) }
- /DISCARD/ : { *(.dynamic*) }
- /DISCARD/ : { *(.plt*) }
- /DISCARD/ : { *(.interp*) }
- /DISCARD/ : { *(.gnu*) }
-}
diff --git a/arch/arm/cpu/armv7/zynq/u-boot.lds b/arch/arm/cpu/armv7/zynq/u-boot.lds
deleted file mode 100644
index 4dc9bb0102..0000000000
--- a/arch/arm/cpu/armv7/zynq/u-boot.lds
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2004-2008 Texas Instruments
- *
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
- . = 0x00000000;
-
- . = ALIGN(4);
- .text :
- {
- *(.__image_copy_start)
- *(.vectors)
- CPUDIR/start.o (.text*)
- *(.text*)
- }
-
- . = ALIGN(4);
- .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
-
- . = ALIGN(4);
- .data : {
- *(.data*)
- }
-
- . = ALIGN(4);
-
- . = .;
-
- . = ALIGN(4);
- .u_boot_list : {
- KEEP(*(SORT(.u_boot_list*)));
- }
-
- . = ALIGN(4);
-
- .image_copy_end :
- {
- *(.__image_copy_end)
- }
-
- .rel_dyn_start :
- {
- *(.__rel_dyn_start)
- }
-
- .rel.dyn : {
- *(.rel*)
- }
-
- .rel_dyn_end :
- {
- *(.__rel_dyn_end)
- }
-
- .end :
- {
- *(.__end)
- }
-
- _image_binary_end = .;
-
-/*
- * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
- * __bss_base and __bss_limit are for linker only (overlay ordering)
- */
-
- .bss_start __rel_dyn_start (OVERLAY) : {
- KEEP(*(.__bss_start));
- __bss_base = .;
- }
-
- .bss __bss_base (OVERLAY) : {
- *(.bss*)
- . = ALIGN(4);
- __bss_limit = .;
- }
-
- .bss_end __bss_limit (OVERLAY) : {
- KEEP(*(.__bss_end));
- }
-
- /*
- * Zynq needs to discard these sections because the user
- * is expected to pass this image on to tools for boot.bin
- * generation that require them to be dropped.
- */
- /DISCARD/ : { *(.dynsym) }
- /DISCARD/ : { *(.dynbss*) }
- /DISCARD/ : { *(.dynstr*) }
- /DISCARD/ : { *(.dynamic*) }
- /DISCARD/ : { *(.plt*) }
- /DISCARD/ : { *(.interp*) }
- /DISCARD/ : { *(.gnu*) }
- /DISCARD/ : { *(.ARM.exidx*) }
- /DISCARD/ : { *(.gnu.linkonce.armexidx.*) }
-}
diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile
index a997e045bd..efab5eabc9 100644
--- a/arch/arm/cpu/armv8/zynqmp/Makefile
+++ b/arch/arm/cpu/armv8/zynqmp/Makefile
@@ -7,3 +7,4 @@
obj-y += clk.o
obj-y += cpu.o
+obj-$(CONFIG_MP) += mp.o
diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c
index 0af619d92f..9218586e94 100644
--- a/arch/arm/cpu/armv8/zynqmp/clk.c
+++ b/arch/arm/cpu/armv8/zynqmp/clk.c
@@ -6,6 +6,7 @@
*/
#include <common.h>
+#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
@@ -16,6 +17,8 @@ unsigned long get_uart_clk(int dev_id)
u32 ver = zynqmp_get_silicon_version();
switch (ver) {
+ case ZYNQMP_CSU_VERSION_VELOCE:
+ return 48000;
case ZYNQMP_CSU_VERSION_EP108:
return 25000000;
}
diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
index 6fae03c1af..60d7d20e17 100644
--- a/arch/arm/cpu/armv8/zynqmp/cpu.c
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -20,9 +20,175 @@ unsigned int zynqmp_get_silicon_version(void)
gd->cpu_clk = get_tbclk();
switch (gd->cpu_clk) {
+ case 0 ... 1000000:
+ return ZYNQMP_CSU_VERSION_VELOCE;
case 50000000:
return ZYNQMP_CSU_VERSION_QEMU;
}
return ZYNQMP_CSU_VERSION_EP108;
}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+#include <asm/armv8/mmu.h>
+
+#define SECTION_SHIFT_L1 30UL
+#define SECTION_SHIFT_L2 21UL
+#define BLOCK_SIZE_L0 0x8000000000UL
+#define BLOCK_SIZE_L1 (1 << SECTION_SHIFT_L1)
+#define BLOCK_SIZE_L2 (1 << SECTION_SHIFT_L2)
+
+#define TCR_TG1_4K (1 << 31)
+#define TCR_EPD1_DISABLE (1 << 23)
+#define ZYNQMO_VA_BITS 40
+#define ZYNQMP_TCR TCR_TG1_4K | \
+ TCR_EPD1_DISABLE | \
+ TCR_SHARED_OUTER | \
+ TCR_SHARED_INNER | \
+ TCR_IRGN_WBWA | \
+ TCR_ORGN_WBWA | \
+ TCR_T0SZ(ZYNQMO_VA_BITS)
+
+#define MEMORY_ATTR PMD_SECT_AF | PMD_SECT_INNER_SHARE | \
+ PMD_ATTRINDX(MT_NORMAL) | \
+ PMD_TYPE_SECT
+#define DEVICE_ATTR PMD_SECT_AF | PMD_SECT_PXN | \
+ PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_NGNRNE) | \
+ PMD_TYPE_SECT
+
+/* 4K size is required to place 512 entries in each level */
+#define TLB_TABLE_SIZE 0x1000
+
+struct attr_tbl {
+ u32 num;
+ u64 attr;
+};
+
+static struct attr_tbl attr_tbll1t0[4] = { {16, 0x0},
+ {8, DEVICE_ATTR},
+ {32, MEMORY_ATTR},
+ {456, DEVICE_ATTR}
+ };
+static struct attr_tbl attr_tbll2t3[4] = { {0x180, DEVICE_ATTR},
+ {0x40, 0x0},
+ {0x3F, DEVICE_ATTR},
+ {0x1, MEMORY_ATTR}
+ };
+
+/*
+ * This mmu table looks as below
+ * Level 0 table contains two entries to 512GB sizes. One is Level1 Table 0
+ * and other Level1 Table1.
+ * Level1 Table0 contains entries for each 1GB from 0 to 511GB.
+ * Level1 Table1 contains entries for each 1GB from 512GB to 1TB.
+ * Level2 Table0, Level2 Table1, Level2 Table2 and Level2 Table3 contains
+ * entries for each 2MB starting from 0GB, 1GB, 2GB and 3GB respectively.
+ */
+static void zynqmp_mmu_setup(void)
+{
+ int el;
+ u32 index_attr;
+ u64 i, section_l1t0, section_l1t1;
+ u64 section_l2t0, section_l2t1, section_l2t2, section_l2t3;
+ u64 *level0_table = (u64 *)gd->arch.tlb_addr;
+ u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + TLB_TABLE_SIZE);
+ u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + (2 * TLB_TABLE_SIZE));
+ u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + (3 * TLB_TABLE_SIZE));
+ u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + (4 * TLB_TABLE_SIZE));
+ u64 *level2_table_2 = (u64 *)(gd->arch.tlb_addr + (5 * TLB_TABLE_SIZE));
+ u64 *level2_table_3 = (u64 *)(gd->arch.tlb_addr + (6 * TLB_TABLE_SIZE));
+
+ level0_table[0] =
+ (u64)level1_table_0 | PMD_TYPE_TABLE;
+ level0_table[1] =
+ (u64)level1_table_1 | PMD_TYPE_TABLE;
+
+ /*
+ * set level 1 table 0, covering 0 to 512GB
+ * set level 1 table 1, covering 512GB to 1TB
+ */
+ section_l1t0 = 0;
+ section_l1t1 = BLOCK_SIZE_L0;
+
+ index_attr = 0;
+ for (i = 0; i < 512; i++) {
+ level1_table_0[i] = section_l1t0;
+ level1_table_0[i] |= attr_tbll1t0[index_attr].attr;
+ attr_tbll1t0[index_attr].num--;
+ if (attr_tbll1t0[index_attr].num == 0)
+ index_attr++;
+ level1_table_1[i] = section_l1t1;
+ level1_table_1[i] |= DEVICE_ATTR;
+ section_l1t0 += BLOCK_SIZE_L1;
+ section_l1t1 += BLOCK_SIZE_L1;
+ }
+
+ level1_table_0[0] =
+ (u64)level2_table_0 | PMD_TYPE_TABLE;
+ level1_table_0[1] =
+ (u64)level2_table_1 | PMD_TYPE_TABLE;
+ level1_table_0[2] =
+ (u64)level2_table_2 | PMD_TYPE_TABLE;
+ level1_table_0[3] =
+ (u64)level2_table_3 | PMD_TYPE_TABLE;
+
+ section_l2t0 = 0;
+ section_l2t1 = section_l2t0 + BLOCK_SIZE_L1; /* 1GB */
+ section_l2t2 = section_l2t1 + BLOCK_SIZE_L1; /* 2GB */
+ section_l2t3 = section_l2t2 + BLOCK_SIZE_L1; /* 3GB */
+
+ index_attr = 0;
+
+ for (i = 0; i < 512; i++) {
+ level2_table_0[i] = section_l2t0 | MEMORY_ATTR;
+ level2_table_1[i] = section_l2t1 | MEMORY_ATTR;
+ level2_table_2[i] = section_l2t2 | DEVICE_ATTR;
+ level2_table_3[i] = section_l2t3 |
+ attr_tbll2t3[index_attr].attr;
+ attr_tbll2t3[index_attr].num--;
+ if (attr_tbll2t3[index_attr].num == 0)
+ index_attr++;
+ section_l2t0 += BLOCK_SIZE_L2;
+ section_l2t1 += BLOCK_SIZE_L2;
+ section_l2t2 += BLOCK_SIZE_L2;
+ section_l2t3 += BLOCK_SIZE_L2;
+ }
+
+ /* flush new MMU table */
+ flush_dcache_range(gd->arch.tlb_addr,
+ gd->arch.tlb_addr + gd->arch.tlb_size);
+
+ /* point TTBR to the new table */
+ el = current_el();
+ set_ttbr_tcr_mair(el, gd->arch.tlb_addr,
+ ZYNQMP_TCR, MEMORY_ATTRIBUTES);
+
+ set_sctlr(get_sctlr() | CR_M);
+}
+
+int arch_cpu_init(void)
+{
+ icache_enable();
+ __asm_invalidate_dcache_all();
+ __asm_invalidate_tlb_all();
+ return 0;
+}
+
+/*
+ * This function is called from lib/board.c.
+ * It recreates MMU table in main memory. MMU and d-cache are enabled earlier.
+ * There is no need to disable d-cache for this operation.
+ */
+void enable_caches(void)
+{
+ /* The data cache is not active unless the mmu is enabled */
+ if (!(get_sctlr() & CR_M)) {
+ invalidate_dcache_all();
+ __asm_invalidate_tlb_all();
+ zynqmp_mmu_setup();
+ }
+ puts("Enabling Caches...\n");
+
+ set_sctlr(get_sctlr() | CR_C);
+}
+#endif
diff --git a/arch/arm/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c
new file mode 100644
index 0000000000..17e32a7b7c
--- /dev/null
+++ b/arch/arm/cpu/armv8/zynqmp/mp.c
@@ -0,0 +1,242 @@
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+
+#define LOCK 0
+#define SPLIT 1
+
+#define HALT 0
+#define RELEASE 1
+
+#define ZYNQMP_BOOTADDR_HIGH_MASK 0xFFFFFFFF
+#define ZYNQMP_R5_HIVEC_ADDR 0xFFFF0000
+#define ZYNQMP_R5_LOVEC_ADDR 0x0
+#define ZYNQMP_RPU_CFG_CPU_HALT_MASK 0x01
+#define ZYNQMP_RPU_CFG_HIVEC_MASK 0x04
+#define ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK 0x08
+#define ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK 0x40
+#define ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK 0x10
+
+#define ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK 0x04
+#define ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK 0x01
+#define ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK 0x02
+#define ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK 0x1000000
+
+#define ZYNQMP_TCM_START_ADDRESS 0xFFE00000
+#define ZYNQMP_TCM_BOTH_SIZE 0x40000
+
+#define ZYNQMP_CORE_APU0 0
+#define ZYNQMP_CORE_APU3 3
+
+#define ZYNQMP_MAX_CORES 6
+
+int is_core_valid(unsigned int core)
+{
+ if (core < ZYNQMP_MAX_CORES)
+ return 1;
+
+ return 0;
+}
+
+int cpu_reset(int nr)
+{
+ puts("Feature is not implemented.\n");
+ return 0;
+}
+
+static void set_r5_halt_mode(u8 halt, u8 mode)
+{
+ u32 tmp;
+
+ tmp = readl(&rpu_base->rpu0_cfg);
+ if (halt == HALT)
+ tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+ else
+ tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+ writel(tmp, &rpu_base->rpu0_cfg);
+
+ if (mode == LOCK) {
+ tmp = readl(&rpu_base->rpu1_cfg);
+ if (halt == HALT)
+ tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+ else
+ tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK;
+ writel(tmp, &rpu_base->rpu1_cfg);
+ }
+}
+
+static void set_r5_tcm_mode(u8 mode)
+{
+ u32 tmp;
+
+ tmp = readl(&rpu_base->rpu_glbl_ctrl);
+ if (mode == LOCK) {
+ tmp &= ~ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK;
+ tmp |= ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK |
+ ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK;
+ } else {
+ tmp |= ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK;
+ tmp &= ~(ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK |
+ ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK);
+ }
+
+ writel(tmp, &rpu_base->rpu_glbl_ctrl);
+}
+
+static void set_r5_reset(u8 mode)
+{
+ u32 tmp;
+
+ tmp = readl(&crlapb_base->rst_lpd_top);
+ tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+ ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+
+ if (mode == LOCK)
+ tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+
+ writel(tmp, &crlapb_base->rst_lpd_top);
+}
+
+static void release_r5_reset(u8 mode)
+{
+ u32 tmp;
+
+ tmp = readl(&crlapb_base->rst_lpd_top);
+ tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK |
+ ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK);
+
+ if (mode == LOCK)
+ tmp &= ~ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK;
+
+ writel(tmp, &crlapb_base->rst_lpd_top);
+}
+
+static void enable_clock_r5(void)
+{
+ u32 tmp;
+
+ tmp = readl(&crlapb_base->cpu_r5_ctrl);
+ tmp |= ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK;
+ writel(tmp, &crlapb_base->cpu_r5_ctrl);
+
+ /* Give some delay for clock
+ * to propogate */
+ udelay(0x500);
+}
+
+int cpu_disable(int nr)
+{
+ if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+ u32 val = readl(&crfapb_base->rst_fpd_apu);
+ val |= 1 << nr;
+ writel(val, &crfapb_base->rst_fpd_apu);
+ } else {
+ set_r5_reset(LOCK);
+ }
+
+ return 0;
+}
+
+int cpu_status(int nr)
+{
+ if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+ u32 addr_low = readl(((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
+ u32 addr_high = readl(((u8 *)&apu_base->rvbar_addr0_h) +
+ nr * 8);
+ u32 val = readl(&crfapb_base->rst_fpd_apu);
+ val &= 1 << nr;
+ printf("APU CPU%d %s - starting address HI: %x, LOW: %x\n",
+ nr, val ? "OFF" : "ON" , addr_high, addr_low);
+ } else {
+ u32 val = readl(&crlapb_base->rst_lpd_top);
+ val &= 1 << (nr - 4);
+ printf("RPU CPU%d %s\n", nr - 4, val ? "OFF" : "ON");
+ }
+
+ return 0;
+}
+
+static void set_r5_start(u8 high)
+{
+ u32 tmp;
+
+ tmp = readl(&rpu_base->rpu0_cfg);
+ if (high)
+ tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK;
+ else
+ tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK;
+ writel(tmp, &rpu_base->rpu0_cfg);
+
+ tmp = readl(&rpu_base->rpu1_cfg);
+ if (high)
+ tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK;
+ else
+ tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK;
+ writel(tmp, &rpu_base->rpu1_cfg);
+}
+
+int cpu_release(int nr, int argc, char * const argv[])
+{
+ if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) {
+ u64 boot_addr = simple_strtoull(argv[0], NULL, 16);
+ /* HIGH */
+ writel((u32)(boot_addr >> 32),
+ ((u8 *)&apu_base->rvbar_addr0_h) + nr * 8);
+ /* LOW */
+ writel((u32)(boot_addr & ZYNQMP_BOOTADDR_HIGH_MASK),
+ ((u8 *)&apu_base->rvbar_addr0_l) + nr * 8);
+
+ u32 val = readl(&crfapb_base->rst_fpd_apu);
+ val &= ~(1 << nr);
+ writel(val, &crfapb_base->rst_fpd_apu);
+ } else {
+ if (argc != 2) {
+ printf("Invalid number of arguments to release.\n");
+ printf("<addr> <mode>-Start addr lockstep or split\n");
+ return 1;
+ }
+
+ u32 boot_addr = simple_strtoul(argv[0], NULL, 16);
+ if (!(boot_addr == ZYNQMP_R5_LOVEC_ADDR ||
+ boot_addr == ZYNQMP_R5_HIVEC_ADDR)) {
+ printf("Invalid starting address 0x%x\n", boot_addr);
+ printf("0 or 0xffff0000 are permitted\n");
+ return 1;
+ }
+
+ if (!strncmp(argv[1], "lockstep", 8)) {
+ printf("R5 lockstep mode\n");
+ set_r5_tcm_mode(LOCK);
+ set_r5_halt_mode(HALT, LOCK);
+
+ if (boot_addr == 0)
+ set_r5_start(0);
+ else
+ set_r5_start(1);
+
+ enable_clock_r5();
+ release_r5_reset(LOCK);
+ set_r5_halt_mode(RELEASE, LOCK);
+ } else if (!strncmp(argv[1], "split", 5)) {
+ printf("R5 split mode\n");
+ set_r5_tcm_mode(SPLIT);
+ set_r5_halt_mode(HALT, SPLIT);
+ enable_clock_r5();
+ release_r5_reset(SPLIT);
+ set_r5_halt_mode(RELEASE, SPLIT);
+ } else {
+ printf("Unsupported mode\n");
+ return 1;
+ }
+ }
+
+ return 0;
+}