avionic design with actual uboot and tooling
submodule of avionic design uboot bootloader and with included tools to get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
20
u-boot/arch/arm/mach-zynq/Kconfig
Normal file
20
u-boot/arch/arm/mach-zynq/Kconfig
Normal file
@@ -0,0 +1,20 @@
|
||||
if ARCH_ZYNQ
|
||||
|
||||
config SYS_BOARD
|
||||
default "zynq"
|
||||
|
||||
config SYS_VENDOR
|
||||
default "xilinx"
|
||||
|
||||
config SYS_SOC
|
||||
default "zynq"
|
||||
|
||||
config SYS_CONFIG_NAME
|
||||
string "Board configuration name"
|
||||
default "zynq-common"
|
||||
help
|
||||
This option contains information about board configuration name.
|
||||
Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
|
||||
will be used for board configuration.
|
||||
|
||||
endif
|
||||
18
u-boot/arch/arm/mach-zynq/Makefile
Normal file
18
u-boot/arch/arm/mach-zynq/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# (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
|
||||
AFLAGS_lowlevel_init.o := -mfpu=neon
|
||||
obj-$(CONFIG_SPL_BUILD) += spl.o
|
||||
663
u-boot/arch/arm/mach-zynq/clk.c
Normal file
663
u-boot/arch/arm/mach-zynq/clk.c
Normal file
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
* 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 <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 zynq_clk_ops:
|
||||
* @set_rate: Function pointer to set_rate() implementation
|
||||
* @get_rate: Function pointer to get_rate() implementation
|
||||
*/
|
||||
struct zynq_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 zynq_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;
|
||||
}
|
||||
67
u-boot/arch/arm/mach-zynq/cpu.c
Normal file
67
u-boot/arch/arm/mach-zynq/cpu.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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
|
||||
48
u-boot/arch/arm/mach-zynq/ddrc.c
Normal file
48
u-boot/arch/arm/mach-zynq/ddrc.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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);
|
||||
} else {
|
||||
puts("ECC disabled ");
|
||||
}
|
||||
}
|
||||
29
u-boot/arch/arm/mach-zynq/include/mach/clk.h
Normal file
29
u-boot/arch/arm/mach-zynq/include/mach/clk.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Xilinx Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _ZYNQ_CLK_H_
|
||||
#define _ZYNQ_CLK_H_
|
||||
|
||||
enum zynq_clk {
|
||||
armpll_clk, ddrpll_clk, iopll_clk,
|
||||
cpu_6or4x_clk, cpu_3or2x_clk, cpu_2x_clk, cpu_1x_clk,
|
||||
ddr2x_clk, ddr3x_clk, dci_clk,
|
||||
lqspi_clk, smc_clk, pcap_clk, gem0_clk, gem1_clk,
|
||||
fclk0_clk, fclk1_clk, fclk2_clk, fclk3_clk, can0_clk, can1_clk,
|
||||
sdio0_clk, sdio1_clk, uart0_clk, uart1_clk, spi0_clk, spi1_clk, dma_clk,
|
||||
usb0_aper_clk, usb1_aper_clk, gem0_aper_clk, gem1_aper_clk,
|
||||
sdio0_aper_clk, sdio1_aper_clk, spi0_aper_clk, spi1_aper_clk,
|
||||
can0_aper_clk, can1_aper_clk, i2c0_aper_clk, i2c1_aper_clk,
|
||||
uart0_aper_clk, uart1_aper_clk, gpio_aper_clk, lqspi_aper_clk,
|
||||
smc_aper_clk, swdt_clk, dbg_trc_clk, dbg_apb_clk, clk_max};
|
||||
|
||||
void zynq_clk_early_init(void);
|
||||
int zynq_clk_set_rate(enum zynq_clk clk, unsigned long rate);
|
||||
unsigned long zynq_clk_get_rate(enum zynq_clk clk);
|
||||
const char *zynq_clk_get_name(enum zynq_clk clk);
|
||||
unsigned long get_uart_clk(int dev_id);
|
||||
|
||||
#endif
|
||||
11
u-boot/arch/arm/mach-zynq/include/mach/gpio.h
Normal file
11
u-boot/arch/arm/mach-zynq/include/mach/gpio.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Xilinx, Inc.
|
||||
* Copyright (c) 2015 DAVE Embedded Systems
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _ZYNQ_GPIO_H
|
||||
#define _ZYNQ_GPIO_H
|
||||
|
||||
#endif /* _ZYNQ_GPIO_H */
|
||||
142
u-boot/arch/arm/mach-zynq/include/mach/hardware.h
Normal file
142
u-boot/arch/arm/mach-zynq/include/mach/hardware.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Xilinx Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _ASM_ARCH_HARDWARE_H
|
||||
#define _ASM_ARCH_HARDWARE_H
|
||||
|
||||
#define ZYNQ_SYS_CTRL_BASEADDR 0xF8000000
|
||||
#define ZYNQ_DEV_CFG_APB_BASEADDR 0xF8007000
|
||||
#define ZYNQ_SCU_BASEADDR 0xF8F00000
|
||||
#define ZYNQ_GEM_BASEADDR0 0xE000B000
|
||||
#define ZYNQ_GEM_BASEADDR1 0xE000C000
|
||||
#define ZYNQ_I2C_BASEADDR0 0xE0004000
|
||||
#define ZYNQ_I2C_BASEADDR1 0xE0005000
|
||||
#define ZYNQ_QSPI_BASEADDR 0xE000D000
|
||||
#define ZYNQ_SMC_BASEADDR 0xE000E000
|
||||
#define ZYNQ_NAND_BASEADDR 0xE1000000
|
||||
#define ZYNQ_DDRC_BASEADDR 0xF8006000
|
||||
#define ZYNQ_EFUSE_BASEADDR 0xF800D000
|
||||
#define ZYNQ_USB_BASEADDR0 0xE0002000
|
||||
#define ZYNQ_USB_BASEADDR1 0xE0003000
|
||||
|
||||
/* Bootmode setting values */
|
||||
#define ZYNQ_BM_MASK 0x7
|
||||
#define ZYNQ_BM_QSPI 0x1
|
||||
#define ZYNQ_BM_NOR 0x2
|
||||
#define ZYNQ_BM_NAND 0x4
|
||||
#define ZYNQ_BM_SD 0x5
|
||||
#define ZYNQ_BM_JTAG 0x0
|
||||
|
||||
/* Reflect slcr offsets */
|
||||
struct slcr_regs {
|
||||
u32 scl; /* 0x0 */
|
||||
u32 slcr_lock; /* 0x4 */
|
||||
u32 slcr_unlock; /* 0x8 */
|
||||
u32 reserved0_1[61];
|
||||
u32 arm_pll_ctrl; /* 0x100 */
|
||||
u32 ddr_pll_ctrl; /* 0x104 */
|
||||
u32 io_pll_ctrl; /* 0x108 */
|
||||
u32 reserved0_2[5];
|
||||
u32 arm_clk_ctrl; /* 0x120 */
|
||||
u32 ddr_clk_ctrl; /* 0x124 */
|
||||
u32 dci_clk_ctrl; /* 0x128 */
|
||||
u32 aper_clk_ctrl; /* 0x12c */
|
||||
u32 reserved0_3[2];
|
||||
u32 gem0_rclk_ctrl; /* 0x138 */
|
||||
u32 gem1_rclk_ctrl; /* 0x13c */
|
||||
u32 gem0_clk_ctrl; /* 0x140 */
|
||||
u32 gem1_clk_ctrl; /* 0x144 */
|
||||
u32 smc_clk_ctrl; /* 0x148 */
|
||||
u32 lqspi_clk_ctrl; /* 0x14c */
|
||||
u32 sdio_clk_ctrl; /* 0x150 */
|
||||
u32 uart_clk_ctrl; /* 0x154 */
|
||||
u32 spi_clk_ctrl; /* 0x158 */
|
||||
u32 can_clk_ctrl; /* 0x15c */
|
||||
u32 can_mioclk_ctrl; /* 0x160 */
|
||||
u32 dbg_clk_ctrl; /* 0x164 */
|
||||
u32 pcap_clk_ctrl; /* 0x168 */
|
||||
u32 reserved0_4[1];
|
||||
u32 fpga0_clk_ctrl; /* 0x170 */
|
||||
u32 reserved0_5[3];
|
||||
u32 fpga1_clk_ctrl; /* 0x180 */
|
||||
u32 reserved0_6[3];
|
||||
u32 fpga2_clk_ctrl; /* 0x190 */
|
||||
u32 reserved0_7[3];
|
||||
u32 fpga3_clk_ctrl; /* 0x1a0 */
|
||||
u32 reserved0_8[8];
|
||||
u32 clk_621_true; /* 0x1c4 */
|
||||
u32 reserved1[14];
|
||||
u32 pss_rst_ctrl; /* 0x200 */
|
||||
u32 reserved2[15];
|
||||
u32 fpga_rst_ctrl; /* 0x240 */
|
||||
u32 reserved3[5];
|
||||
u32 reboot_status; /* 0x258 */
|
||||
u32 boot_mode; /* 0x25c */
|
||||
u32 reserved4[116];
|
||||
u32 trust_zone; /* 0x430 */ /* FIXME */
|
||||
u32 reserved5_1[63];
|
||||
u32 pss_idcode; /* 0x530 */
|
||||
u32 reserved5_2[51];
|
||||
u32 ddr_urgent; /* 0x600 */
|
||||
u32 reserved6[6];
|
||||
u32 ddr_urgent_sel; /* 0x61c */
|
||||
u32 reserved7[56];
|
||||
u32 mio_pin[54]; /* 0x700 - 0x7D4 */
|
||||
u32 reserved8[74];
|
||||
u32 lvl_shftr_en; /* 0x900 */
|
||||
u32 reserved9[3];
|
||||
u32 ocm_cfg; /* 0x910 */
|
||||
};
|
||||
|
||||
#define slcr_base ((struct slcr_regs *)ZYNQ_SYS_CTRL_BASEADDR)
|
||||
|
||||
struct devcfg_regs {
|
||||
u32 ctrl; /* 0x0 */
|
||||
u32 lock; /* 0x4 */
|
||||
u32 cfg; /* 0x8 */
|
||||
u32 int_sts; /* 0xc */
|
||||
u32 int_mask; /* 0x10 */
|
||||
u32 status; /* 0x14 */
|
||||
u32 dma_src_addr; /* 0x18 */
|
||||
u32 dma_dst_addr; /* 0x1c */
|
||||
u32 dma_src_len; /* 0x20 */
|
||||
u32 dma_dst_len; /* 0x24 */
|
||||
u32 rom_shadow; /* 0x28 */
|
||||
u32 reserved1[2];
|
||||
u32 unlock; /* 0x34 */
|
||||
u32 reserved2[18];
|
||||
u32 mctrl; /* 0x80 */
|
||||
u32 reserved3;
|
||||
u32 write_count; /* 0x88 */
|
||||
u32 read_count; /* 0x8c */
|
||||
};
|
||||
|
||||
#define devcfg_base ((struct devcfg_regs *)ZYNQ_DEV_CFG_APB_BASEADDR)
|
||||
|
||||
struct scu_regs {
|
||||
u32 reserved1[16];
|
||||
u32 filter_start; /* 0x40 */
|
||||
u32 filter_end; /* 0x44 */
|
||||
};
|
||||
|
||||
#define scu_base ((struct scu_regs *)ZYNQ_SCU_BASEADDR)
|
||||
|
||||
struct ddrc_regs {
|
||||
u32 ddrc_ctrl; /* 0x0 */
|
||||
u32 reserved[60];
|
||||
u32 ecc_scrub; /* 0xF4 */
|
||||
};
|
||||
#define ddrc_base ((struct ddrc_regs *)ZYNQ_DDRC_BASEADDR)
|
||||
|
||||
struct efuse_reg {
|
||||
u32 reserved1[4];
|
||||
u32 status;
|
||||
u32 reserved2[3];
|
||||
};
|
||||
|
||||
#define efuse_base ((struct efuse_reg *)ZYNQ_EFUSE_BASEADDR)
|
||||
|
||||
#endif /* _ASM_ARCH_HARDWARE_H */
|
||||
27
u-boot/arch/arm/mach-zynq/include/mach/sys_proto.h
Normal file
27
u-boot/arch/arm/mach-zynq/include/mach/sys_proto.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Xilinx Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _SYS_PROTO_H_
|
||||
#define _SYS_PROTO_H_
|
||||
|
||||
extern void zynq_slcr_lock(void);
|
||||
extern void zynq_slcr_unlock(void);
|
||||
extern void zynq_slcr_cpu_reset(void);
|
||||
extern void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate);
|
||||
extern void zynq_slcr_devcfg_disable(void);
|
||||
extern void zynq_slcr_devcfg_enable(void);
|
||||
extern u32 zynq_slcr_get_boot_mode(void);
|
||||
extern u32 zynq_slcr_get_idcode(void);
|
||||
extern int zynq_slcr_get_mio_pin_status(const char *periph);
|
||||
extern void zynq_ddrc_init(void);
|
||||
extern unsigned int zynq_get_silicon_version(void);
|
||||
|
||||
int zynq_board_read_rom_ethaddr(unsigned char *ethaddr);
|
||||
|
||||
/* Driver extern functions */
|
||||
extern void ps7_init(void);
|
||||
|
||||
#endif /* _SYS_PROTO_H_ */
|
||||
26
u-boot/arch/arm/mach-zynq/lowlevel_init.S
Normal file
26
u-boot/arch/arm/mach-zynq/lowlevel_init.S
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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)
|
||||
203
u-boot/arch/arm/mach-zynq/slcr.c
Normal file
203
u-boot/arch/arm/mach-zynq/slcr.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
zynq_slcr_unlock();
|
||||
|
||||
/* Disable AXI interface by asserting FPGA resets */
|
||||
writel(0xF, &slcr_base->fpga_rst_ctrl);
|
||||
|
||||
/* Disable Level shifters before setting PS-PL */
|
||||
reg_val = readl(&slcr_base->lvl_shftr_en);
|
||||
reg_val &= ~0xF;
|
||||
writel(reg_val, &slcr_base->lvl_shftr_en);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
117
u-boot/arch/arm/mach-zynq/spl.c
Normal file
117
u-boot/arch/arm/mach-zynq/spl.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* (C) Copyright 2014 Xilinx, Inc. Michal Simek
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <debug_uart.h>
|
||||
#include <spl.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/spl.h>
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/sys_proto.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
void board_init_f(ulong dummy)
|
||||
{
|
||||
ps7_init();
|
||||
|
||||
arch_cpu_init();
|
||||
/*
|
||||
* The debug UART can be used from this point:
|
||||
* debug_uart_init();
|
||||
* printch('x');
|
||||
*/
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_BOARD_INIT
|
||||
void spl_board_init(void)
|
||||
{
|
||||
preloader_console_init();
|
||||
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(const u32 boot_device)
|
||||
{
|
||||
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/(platform)/ps7_init_gpl.c, if it exists.
|
||||
*/
|
||||
}
|
||||
|
||||
__weak int ps7_post_config(void)
|
||||
{
|
||||
/*
|
||||
* This function is overridden by the one in
|
||||
* board/xilinx/zynq/(platform)/ps7_init_gpl.c, if it exists.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spl_board_prepare_for_boot(void)
|
||||
{
|
||||
ps7_post_config();
|
||||
debug("SPL bye\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPL_LOAD_FIT
|
||||
int board_fit_config_name_match(const char *name)
|
||||
{
|
||||
/* Just empty function now - can't decide what to choose */
|
||||
debug("%s: %s\n", __func__, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
87
u-boot/arch/arm/mach-zynq/timer.c
Normal file
87
u-boot/arch/arm/mach-zynq/timer.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 (timebase clock frequency).
|
||||
* On ARM it returns the number of timer ticks per second.
|
||||
*/
|
||||
ulong get_tbclk(void)
|
||||
{
|
||||
return gd->arch.timer_rate_hz;
|
||||
}
|
||||
65
u-boot/arch/arm/mach-zynq/u-boot-spl.lds
Normal file
65
u-boot/arch/arm/mach-zynq/u-boot-spl.lds
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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);
|
||||
.u_boot_list : {
|
||||
KEEP(*(SORT(.u_boot_list*)));
|
||||
} > .sram
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
_image_binary_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*) }
|
||||
}
|
||||
105
u-boot/arch/arm/mach-zynq/u-boot.lds
Normal file
105
u-boot/arch/arm/mach-zynq/u-boot.lds
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.*) }
|
||||
}
|
||||
Reference in New Issue
Block a user