* [PATCH v3 1/5] serial: Add driver for Cadence UART
2013-03-25 13:02 [PATCH v3 0/5] ARM: add support for Zynq Steffen Trumtrar
@ 2013-03-25 13:02 ` Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v3 2/5] ARM: zynq: Add new architecture zynq Steffen Trumtrar
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2013-03-25 13:02 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Support for Cadence UART core.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
Changes since v2:
- remove superfluous Kconfig option
- add help text to Kconfig option
drivers/serial/Kconfig | 5 +
drivers/serial/Makefile | 1 +
drivers/serial/serial_cadence.c | 307 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 313 insertions(+)
create mode 100644 drivers/serial/serial_cadence.c
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index f61d670..73cb9f8 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -113,4 +113,9 @@ config DRIVER_SERIAL_OMAP4_USBBOOT
help
Enable this to get console support over the usb bus used to boot an OMAP4
+config DRIVER_SERIAL_CADENCE
+ bool "Cadence UART driver"
+ help
+ Say Y here if you have a Cadence serial IP core.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 893e282..963a7df 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_DRIVER_SERIAL_ALTERA) += serial_altera.o
obj-$(CONFIG_DRIVER_SERIAL_ALTERA_JTAG) += serial_altera_jtag.o
obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o
obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o
+obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o
diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
new file mode 100644
index 0000000..c29c391
--- /dev/null
+++ b/drivers/serial/serial_cadence.c
@@ -0,0 +1,307 @@
+/*
+ * (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <notifier.h>
+#include <io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#define CADENCE_UART_CONTROL 0x00
+#define CADENCE_UART_MODE 0x04
+#define CADENCE_UART_BAUD_GEN 0x18
+#define CADENCE_UART_CHANNEL_STS 0x2C
+#define CADENCE_UART_RXTXFIFO 0x30
+#define CADENCE_UART_BAUD_DIV 0x34
+
+#define CADENCE_CTRL_RXRES (1 << 0)
+#define CADENCE_CTRL_TXRES (1 << 1)
+#define CADENCE_CTRL_RXEN (1 << 2)
+#define CADENCE_CTRL_RXDIS (1 << 3)
+#define CADENCE_CTRL_TXEN (1 << 4)
+#define CADENCE_CTRL_TXDIS (1 << 5)
+#define CADENCE_CTRL_RSTTO (1 << 6)
+#define CADENCE_CTRL_STTBRK (1 << 7)
+#define CADENCE_CTRL_STPBRK (1 << 8)
+
+#define CADENCE_MODE_CLK_REF (0 << 0)
+#define CADENCE_MODE_CLK_REF_DIV (1 << 0)
+#define CADENCE_MODE_CHRL_6 (3 << 1)
+#define CADENCE_MODE_CHRL_7 (2 << 1)
+#define CADENCE_MODE_CHRL_8 (0 << 1)
+#define CADENCE_MODE_PAR_EVEN (0 << 3)
+#define CADENCE_MODE_PAR_ODD (1 << 3)
+#define CADENCE_MODE_PAR_SPACE (2 << 3)
+#define CADENCE_MODE_PAR_MARK (3 << 3)
+#define CADENCE_MODE_PAR_NONE (4 << 3)
+
+#define CADENCE_STS_REMPTY (1 << 1)
+#define CADENCE_STS_RFUL (1 << 2)
+#define CADENCE_STS_TEMPTY (1 << 3)
+#define CADENCE_STS_TFUL (1 << 4)
+
+/*
+ * create default values for different platforms
+ */
+struct cadence_serial_devtype_data {
+ u32 ctrl;
+ u32 mode;
+};
+
+static struct cadence_serial_devtype_data cadence_r1p08_data = {
+ .ctrl = CADENCE_CTRL_RXEN | CADENCE_CTRL_TXEN,
+ .mode = CADENCE_MODE_CLK_REF | CADENCE_MODE_CHRL_8 | CADENCE_MODE_PAR_NONE,
+};
+
+struct cadence_serial_priv {
+ struct console_device cdev;
+ int baudrate;
+ struct notifier_block notify;
+ void __iomem *regs;
+ struct clk *clk;
+ struct cadence_serial_devtype_data *devtype;
+};
+
+static int cadence_serial_reset(struct console_device *cdev)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+
+ /* Soft-Reset Tx/Rx paths */
+ writel(CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES, priv->regs +
+ CADENCE_UART_CONTROL);
+
+ while (readl(priv->regs + CADENCE_UART_CONTROL) &
+ (CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES))
+ ;
+
+ return 0;
+}
+
+static int cadence_serial_setbaudrate(struct console_device *cdev, int baudrate)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+ unsigned int gen, div;
+ int calc_rate;
+ unsigned long clk;
+ int error;
+ int val;
+
+ clk = clk_get_rate(priv->clk);
+ priv->baudrate = baudrate;
+
+ /* disable transmitter and receiver */
+ val = readl(priv->regs + CADENCE_UART_CONTROL);
+ val &= ~CADENCE_CTRL_TXEN & ~CADENCE_CTRL_RXEN;
+ writel(val, priv->regs + CADENCE_UART_CONTROL);
+
+ /*
+ * clk
+ * rate = -----------
+ * gen*(div+1)
+ */
+
+ for (div = 4; div < 256; div++) {
+ gen = clk / (baudrate * (div + 1));
+
+ if (gen < 1 || gen > 65535)
+ continue;
+
+ calc_rate = clk / (gen * (div + 1));
+ error = baudrate - calc_rate;
+ if (error < 0)
+ error *= -1;
+ if (((error * 100) / baudrate) < 3)
+ break;
+ }
+
+ writel(gen, priv->regs + CADENCE_UART_BAUD_GEN);
+ writel(div, priv->regs + CADENCE_UART_BAUD_DIV);
+
+ /* Soft-Reset Tx/Rx paths */
+ writel(CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES, priv->regs +
+ CADENCE_UART_CONTROL);
+
+ while (readl(priv->regs + CADENCE_UART_CONTROL) &
+ (CADENCE_CTRL_RXRES | CADENCE_CTRL_TXRES))
+ ;
+
+ /* Enable UART */
+ writel(priv->devtype->ctrl, priv->regs + CADENCE_UART_CONTROL);
+
+ return 0;
+}
+
+static int cadence_serial_init_port(struct console_device *cdev)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+
+ cadence_serial_reset(cdev);
+
+ /* Enable UART */
+ writel(priv->devtype->ctrl, priv->regs + CADENCE_UART_CONTROL);
+ writel(priv->devtype->mode, priv->regs + CADENCE_UART_MODE);
+
+ return 0;
+}
+
+static void cadence_serial_putc(struct console_device *cdev, char c)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+
+ while ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
+ CADENCE_STS_TFUL) != 0)
+ ;
+
+ writel(c, priv->regs + CADENCE_UART_RXTXFIFO);
+}
+
+static int cadence_serial_tstc(struct console_device *cdev)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+
+ return ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
+ CADENCE_STS_REMPTY) == 0);
+}
+
+static int cadence_serial_getc(struct console_device *cdev)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+
+ while (!cadence_serial_tstc(cdev))
+ ;
+
+ return readl(priv->regs + CADENCE_UART_RXTXFIFO);
+}
+
+static void cadence_serial_flush(struct console_device *cdev)
+{
+ struct cadence_serial_priv *priv = container_of(cdev,
+ struct cadence_serial_priv, cdev);
+
+ while ((readl(priv->regs + CADENCE_UART_CHANNEL_STS) &
+ CADENCE_STS_TEMPTY) != 0)
+ ;
+}
+
+static int cadence_clocksource_clock_change(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct cadence_serial_priv *priv = container_of(nb,
+ struct cadence_serial_priv, notify);
+
+ cadence_serial_setbaudrate(&priv->cdev, priv->baudrate);
+
+ return 0;
+}
+
+static int cadence_serial_probe(struct device_d *dev)
+{
+ struct console_device *cdev;
+ struct cadence_serial_priv *priv;
+ struct cadence_serial_devtype_data *devtype;
+ int ret;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
+ if (ret)
+ return ret;
+
+ priv = xzalloc(sizeof(*priv));
+ priv->devtype = devtype;
+ cdev = &priv->cdev;
+ dev->priv = priv;
+
+ priv->clk = clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ if (devtype->mode & CADENCE_MODE_CLK_REF_DIV)
+ clk_set_rate(priv->clk, clk_get_rate(priv->clk) / 8);
+
+ priv->regs = dev_request_mem_region(dev, 0);
+ if (!priv->regs) {
+ ret = -EBUSY;
+ goto err_free;
+ }
+
+ cdev->dev = dev;
+ cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
+ cdev->tstc = cadence_serial_tstc;
+ cdev->putc = cadence_serial_putc;
+ cdev->getc = cadence_serial_getc;
+ cdev->flush = cadence_serial_flush;
+ cdev->setbrg = cadence_serial_setbaudrate;
+
+ cadence_serial_init_port(cdev);
+
+ console_register(cdev);
+ priv->notify.notifier_call = cadence_clocksource_clock_change;
+ clock_register_client(&priv->notify);
+
+ return 0;
+
+err_free:
+ free(priv);
+ return ret;
+}
+
+static void cadence_serial_remove(struct device_d *dev)
+{
+ struct cadence_serial_priv *priv = dev->priv;
+
+ console_unregister(&priv->cdev);
+ free(priv);
+}
+
+static __maybe_unused struct of_device_id cadence_serial_dt_ids[] = {
+ {
+ .compatible = "xlnx,xuartps",
+ .data = (unsigned long)&cadence_r1p08_data,
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct platform_device_id cadence_serial_ids[] = {
+ {
+ .name = "cadence-uart",
+ .driver_data = (unsigned long)&cadence_r1p08_data,
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d cadence_serial_driver = {
+ .name = "cadence_serial",
+ .probe = cadence_serial_probe,
+ .remove = cadence_serial_remove,
+ .of_compatible = DRV_OF_COMPAT(cadence_serial_dt_ids),
+ .id_table = cadence_serial_ids,
+};
+
+static int cadence_serial_init(void)
+{
+ return platform_driver_register(&cadence_serial_driver);
+}
+console_initcall(cadence_serial_init);
--
1.8.2.rc2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 2/5] ARM: zynq: Add new architecture zynq
2013-03-25 13:02 [PATCH v3 0/5] ARM: add support for Zynq Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v3 1/5] serial: Add driver for Cadence UART Steffen Trumtrar
@ 2013-03-25 13:02 ` Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000 Steffen Trumtrar
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2013-03-25 13:02 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
Add basic support for the Xilinx Zynq-7000 EPP architecture.
The Zynq-7000 is an embedded processing platform that combines a Cortex A9
dualcore MPSoC with an Artix-7 FPGA.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
Changes since v2:
- don't force serial driver in Kconfig
- remove MACH_HAS_LOWLEVEL_INIT
- use (void __iomem *) in debug_ll.h
- remove zynq_add_device inline function
- use resource_size_t instead of void *
- use __le32 consistently in zynq-flash-header.h
- remove useless flash_header_start section
arch/arm/Kconfig | 5 +
arch/arm/Makefile | 2 +
arch/arm/mach-zynq/Kconfig | 38 ++++++
arch/arm/mach-zynq/Makefile | 1 +
arch/arm/mach-zynq/devices.c | 8 ++
arch/arm/mach-zynq/include/mach/barebox.lds.h | 8 ++
arch/arm/mach-zynq/include/mach/debug_ll.h | 37 ++++++
arch/arm/mach-zynq/include/mach/devices.h | 13 ++
| 38 ++++++
arch/arm/mach-zynq/include/mach/zynq7000-regs.h | 132 +++++++++++++++++++++
arch/arm/mach-zynq/zynq.c | 56 +++++++++
include/asm-generic/barebox.lds.h | 3 +-
12 files changed, 340 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/mach-zynq/Kconfig
create mode 100644 arch/arm/mach-zynq/Makefile
create mode 100644 arch/arm/mach-zynq/devices.c
create mode 100644 arch/arm/mach-zynq/include/mach/barebox.lds.h
create mode 100644 arch/arm/mach-zynq/include/mach/debug_ll.h
create mode 100644 arch/arm/mach-zynq/include/mach/devices.h
create mode 100644 arch/arm/mach-zynq/include/mach/zynq-flash-header.h
create mode 100644 arch/arm/mach-zynq/include/mach/zynq7000-regs.h
create mode 100644 arch/arm/mach-zynq/zynq.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 28332ec..8431fa8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -110,6 +110,10 @@ config ARCH_TEGRA
select CPU_ARM926T
select HAS_DEBUG_LL
+config ARCH_ZYNQ
+ bool "Xilinx Zynq-based boards"
+ select HAS_DEBUG_LL
+
endchoice
source arch/arm/cpu/Kconfig
@@ -126,6 +130,7 @@ source arch/arm/mach-pxa/Kconfig
source arch/arm/mach-samsung/Kconfig
source arch/arm/mach-versatile/Kconfig
source arch/arm/mach-tegra/Kconfig
+source arch/arm/mach-zynq/Kconfig
config ARM_ASM_UNIFIED
bool
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index fcb2969..ceb45dc 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -64,6 +64,7 @@ machine-$(CONFIG_ARCH_PXA) := pxa
machine-$(CONFIG_ARCH_SAMSUNG) := samsung
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_TEGRA) := tegra
+machine-$(CONFIG_ARCH_ZYNQ) := zynq
# Board directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
@@ -157,6 +158,7 @@ board-$(CONFIG_MACH_SABRELITE) := freescale-mx6-sabrelite
board-$(CONFIG_MACH_TX53) := karo-tx53
board-$(CONFIG_MACH_GUF_VINCELL) := guf-vincell
board-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) := efika-mx-smartbook
+board-$(CONFIG_MACH_ZEDBOARD) := avnet-zedboard
machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig
new file mode 100644
index 0000000..5bbd648
--- /dev/null
+++ b/arch/arm/mach-zynq/Kconfig
@@ -0,0 +1,38 @@
+if ARCH_ZYNQ
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x1ff00000 if MACH_ZEDBOARD
+
+config ZYNQ_DEBUG_LL_UART_BASE
+ hex
+ default 0xe0001000 if MACH_ZEDBOARD
+
+config BOARDINFO
+ default "ZedBoard" if MACH_ZEDBOARD
+
+choice
+ prompt "Xilinx Zynq type board"
+
+config ARCH_ZYNQ7000
+ bool "Zynq-7000"
+ select CPU_V7
+ select CLKDEV_LOOKUP
+ select COMMON_CLK
+ select ARM_SMP_TWD
+
+endchoice
+
+if ARCH_ZYNQ7000
+
+choice
+ prompt "Zynq-7000 Board Type"
+
+config MACH_ZEDBOARD
+ bool "Avnet Zynq-7000 ZedBoard"
+ select DRIVER_SERIAL_CADENCE
+
+endchoice
+endif
+
+endif
diff --git a/arch/arm/mach-zynq/Makefile b/arch/arm/mach-zynq/Makefile
new file mode 100644
index 0000000..459c957
--- /dev/null
+++ b/arch/arm/mach-zynq/Makefile
@@ -0,0 +1 @@
+obj-y += zynq.o devices.o clk-zynq7000.o
diff --git a/arch/arm/mach-zynq/devices.c b/arch/arm/mach-zynq/devices.c
new file mode 100644
index 0000000..777bb87
--- /dev/null
+++ b/arch/arm/mach-zynq/devices.c
@@ -0,0 +1,8 @@
+#include <common.h>
+#include <driver.h>
+#include <mach/devices.h>
+
+struct device_d *zynq_add_uart(resource_size_t base, int id)
+{
+ return add_generic_device("cadence-uart", id, NULL, base, 0x1000, IORESOURCE_MEM, NULL);
+}
diff --git a/arch/arm/mach-zynq/include/mach/barebox.lds.h b/arch/arm/mach-zynq/include/mach/barebox.lds.h
new file mode 100644
index 0000000..3d35fe9
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/barebox.lds.h
@@ -0,0 +1,8 @@
+#define PRE_IMAGE \
+ .pre_image : { \
+ . = 0x20; \
+ KEEP(*(.flash_header_0x0*)) \
+ . = 0xa0; \
+ KEEP(*(.ps7reg_entry_0x0A0)) \
+ . = 0x8c0; \
+ }
diff --git a/arch/arm/mach-zynq/include/mach/debug_ll.h b/arch/arm/mach-zynq/include/mach/debug_ll.h
new file mode 100644
index 0000000..6c20dd5
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/debug_ll.h
@@ -0,0 +1,37 @@
+/*
+ * based on mach-imx/include/mach/debug_ll.h
+ */
+
+#ifndef __MACH_DEBUG_LL_H__
+#define __MACH_DEBUG_LL_H__
+
+#include <io.h>
+#include <mach/zynq7000-regs.h>
+
+#ifndef CONFIG_ZYNQ_DEBUG_LL_UART_BASE
+#warning define ZYNQ_DEBUG_LL_UART_BASE properly for debug_ll
+#define ZYNQ_DEBUG_LL_UART_BASE ZYNQ_UART1_BASE_ADDR
+#else
+#define ZYNQ_DEBUG_LL_UART_BASE CONFIG_ZYNQ_DEBUG_LL_UART_BASE
+#endif
+
+#define ZYNQ_UART_RXTXFIFO 0x30
+#define ZYNQ_UART_CHANNEL_STS 0x2C
+
+#define ZYNQ_UART_STS_TFUL (1 << 4)
+#define ZYNQ_UART_TXDIS (1 << 5)
+
+static inline void PUTC_LL(int c)
+{
+ void __iomem *base = (void __iomem *)ZYNQ_DEBUG_LL_UART_BASE;
+
+ if (readl(base) & ZYNQ_UART_TXDIS)
+ return;
+
+ while ((readl(base + ZYNQ_UART_CHANNEL_STS) & ZYNQ_UART_STS_TFUL) != 0)
+ ;
+
+ writel(c, base + ZYNQ_UART_RXTXFIFO);
+}
+
+#endif
diff --git a/arch/arm/mach-zynq/include/mach/devices.h b/arch/arm/mach-zynq/include/mach/devices.h
new file mode 100644
index 0000000..281d7c6
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/devices.h
@@ -0,0 +1,13 @@
+#include <mach/zynq7000-regs.h>
+
+struct device_d *zynq_add_uart(resource_size_t base, int id);
+
+static inline struct device_d *zynq_add_uart0(void)
+{
+ return zynq_add_uart((resource_size_t)ZYNQ_UART0_BASE_ADDR, 0);
+}
+
+static inline struct device_d *zynq_add_uart1(void)
+{
+ return zynq_add_uart((resource_size_t)ZYNQ_UART1_BASE_ADDR, 1);
+}
--git a/arch/arm/mach-zynq/include/mach/zynq-flash-header.h b/arch/arm/mach-zynq/include/mach/zynq-flash-header.h
new file mode 100644
index 0000000..3b67e55
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq-flash-header.h
@@ -0,0 +1,38 @@
+#ifndef __MACH_FLASH_HEADER_H
+#define __MACH_FLASH_HEADER_H
+
+#include <asm-generic/sections.h>
+
+#define __flash_header_section __section(.flash_header_0x0)
+#define __ps7reg_entry_section __section(.ps7reg_entry_0x0A0)
+#define __image_len_section __section(.image_len_0x08c0)
+#define FLASH_HEADER_OFFSET 0x0
+#define IMAGE_OFFSET 0x8c0
+
+#define DEST_BASE 0x8c0
+#define FLASH_HEADER_BASE (DEST_BASE + FLASH_HEADER_OFFSET)
+
+struct zynq_reg_entry {
+ __le32 addr;
+ __le32 val;
+};
+
+#define WIDTH_DETECTION_MAGIC 0xAA995566
+#define IMAGE_IDENTIFICATION 0x584C4E58 /* "XLNX" */
+
+struct zynq_flash_header {
+ __le32 width_det;
+ __le32 image_id;
+ __le32 enc_stat;
+ __le32 user;
+ __le32 flash_offset;
+ __le32 length;
+ __le32 res0;
+ __le32 start_of_exec;
+ __le32 total_len;
+ __le32 res1;
+ __le32 checksum;
+ __le32 res2;
+};
+
+#endif /* __MACH_FLASH_HEADER_H */
diff --git a/arch/arm/mach-zynq/include/mach/zynq7000-regs.h b/arch/arm/mach-zynq/include/mach/zynq7000-regs.h
new file mode 100644
index 0000000..f5ccbb0
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/zynq7000-regs.h
@@ -0,0 +1,132 @@
+/*
+ * (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define ZYNQ_UART0_BASE_ADDR 0xE0000000
+#define ZYNQ_UART1_BASE_ADDR 0xE0001000
+#define ZYNQ_I2C0_BASE_ADDR 0xE0004000
+#define ZYNQ_I2C1_BASE_ADDR 0xE0005000
+#define ZYNQ_SPI0_BASE_ADDR 0xE0006000
+#define ZYNQ_SPI1_BASE_ADDR 0xE0007000
+#define ZYNQ_CAN0_BASE_ADDR 0xE0008000
+#define ZYNQ_CAN1_BASE_ADDR 0xE0009000
+#define ZYNQ_GPIO_BASE_ADDR 0xE000A000
+
+#define ZYNQ_SLCR_BASE 0xF8000000
+#define ZYNQ_SLCR_SCL (ZYNQ_SLCR_BASE + 0x000)
+#define ZYNQ_SLCR_LOCK (ZYNQ_SLCR_BASE + 0x004)
+#define ZYNQ_SLCR_UNLOCK (ZYNQ_SLCR_BASE + 0x008)
+#define ZYNQ_SLCR_LOCKSTA (ZYNQ_SLCR_BASE + 0x00C)
+#define ZYNQ_CLOCK_CTRL_BASE (ZYNQ_SLCR_BASE + 0x100)
+#define ZYNQ_ARM_PLL_CTRL 0x000
+#define ZYNQ_DDR_PLL_CTRL 0x004
+#define ZYNQ_IO_PLL_CTRL 0x008
+#define ZYNQ_PLL_STATUS 0x00C
+#define ZYNQ_ARM_PLL_CFG 0x010
+#define ZYNQ_DDR_PLL_CFG 0x014
+#define ZYNQ_IO_PLL_CFG 0x018
+#define ZYNQ_ARM_CLK_CTRL 0x020
+#define ZYNQ_DDR_CLK_CTRL 0x024
+#define ZYNQ_DCI_CLK_CTRL 0x028
+#define ZYNQ_APER_CLK_CTRL 0x02C
+#define ZYNQ_USB0_CLK_CTRL 0x030
+#define ZYNQ_USB1_CLK_CTRL 0x034
+#define ZYNQ_GEM0_RCLK_CTRL 0x038
+#define ZYNQ_GEM1_RCLK_CTRL 0x03C
+#define ZYNQ_GEM0_CLK_CTRL 0x040
+#define ZYNQ_GEM1_CLK_CTRL 0x044
+#define ZYNQ_SMC_CLK_CTRL 0x048
+#define ZYNQ_LQSPI_CLK_CTRL 0x04C
+#define ZYNQ_SDIO_CLK_CTRL 0x050
+#define ZYNQ_UART_CLK_CTRL 0x054
+#define ZYNQ_SPI_CLK_CTRL 0x058
+#define ZYNQ_CAN_CLK_CTRL 0x05C
+#define ZYNQ_CAN_MIOCLK_CTRL 0x060
+#define ZYNQ_DBG_CLK_CTRL 0x064
+#define ZYNQ_PCAP_CLK_CTRL 0x068
+#define ZYNQ_TOPSW_CLK_CTRL 0x06C
+#define ZYNQ_FPGA0_CLK_CTRL 0x070
+#define ZYNQ_FPGA1_CLK_CTRL 0x080
+#define ZYNQ_FPGA2_CLK_CTRL 0x090
+#define ZYNQ_FPGA3_CLK_CTRL 0x0A0
+#define ZYNQ_CLK_621_TRUE 0x0C4
+#define ZYNQ_RST_CTRL_BASE (ZYNQ_SLCR_BASE + 0x200)
+#define ZYNQ_PSS_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x000)
+#define ZYNQ_DDR_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x004)
+#define ZYNQ_TOPSW_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x008)
+#define ZYNQ_DMAC_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x00C)
+#define ZYNQ_USB_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x010)
+#define ZYNQ_GEM_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x014)
+#define ZYNQ_SDIO_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x018)
+#define ZYNQ_SPI_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x01C)
+#define ZYNQ_CAN_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x020)
+#define ZYNQ_I2C_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x024)
+#define ZYNQ_UART_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x028)
+#define ZYNQ_GPIO_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x02C)
+#define ZYNQ_LQSPI_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x030)
+#define ZYNQ_SMC_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x034)
+#define ZYNQ_OCM_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x038)
+#define ZYNQ_DEVCI_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x03C)
+#define ZYNQ_FPGA_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x040)
+#define ZYNQ_A9_CPU_RST_CTRL (ZYNQ_RST_CTRL_BASE + 0x044)
+#define ZYNQ_RS_AWDT_CTRL (ZYNQ_RST_CTRL_BASE + 0x04C)
+#define ZYNQ_REBOOT_STATUS (ZYNQ_SLCR_BASE + 0x258)
+#define ZYNQ_BOOT_MODE (ZYNQ_SLCR_BASE + 0x25C)
+#define ZYNQ_APU_CTRL (ZYNQ_SLCR_BASE + 0x300)
+#define ZYNQ_WDT_CLK_SEL (ZYNQ_SLCR_BASE + 0x304)
+#define ZYNQ_PSS_IDCODE (ZYNQ_SLCR_BASE + 0x530)
+#define ZYNQ_DDR_URGENT (ZYNQ_SLCR_BASE + 0x600)
+#define ZYNQ_DDR_CAL_START (ZYNQ_SLCR_BASE + 0x60C)
+#define ZYNQ_DDR_REF_START (ZYNQ_SLCR_BASE + 0x614)
+#define ZYNQ_DDR_CMD_STA (ZYNQ_SLCR_BASE + 0x618)
+#define ZYNQ_DDR_URGENT_SEL (ZYNQ_SLCR_BASE + 0x61C)
+#define ZYNQ_DDR_DFI_STATUS (ZYNQ_SLCR_BASE + 0x620)
+#define ZYNQ_MIO_BASE (ZYNQ_SLCR_BASE + 0x700)
+#define ZYNQ_MIO_LOOPBACK (ZYNQ_MIO_BASE + 0x104)
+#define ZYNQ_MIO_MST_TRI0 (ZYNQ_MIO_BASE + 0x10C)
+#define ZYNQ_MIO_MST_TRI1 (ZYNQ_MIO_BASE + 0x110)
+#define ZYNQ_SD0_WP_SEL (ZYNQ_SLCR_BASE + 0x830)
+#define ZYNQ_SD1_WP_SEL (ZYNQ_SLCR_BASE + 0x834)
+#define ZYNQ_LVL_SHIFTR_EN (ZYNQ_SLCR_BASE + 0x900)
+#define ZYNQ_OCM_CFG (ZYNQ_SLCR_BASE + 0x910)
+#define ZYNQ_GPIOB_BASE (ZYNQ_SLCR_BASE + 0xB00)
+#define ZYNQ_GPIOB_CTRL (ZYNQ_GPIOB_BASE + 0x000)
+#define ZYNQ_GPIOB_CFG_CMOS18 (ZYNQ_GPIOB_BASE + 0x004)
+#define ZYNQ_GPIOB_CFG_CMOS25 (ZYNQ_GPIOB_BASE + 0x008)
+#define ZYNQ_GPIOB_CFG_CMOS33 (ZYNQ_GPIOB_BASE + 0x00C)
+#define ZYNQ_GPIOB_CFG_LVTTL (ZYNQ_GPIOB_BASE + 0x010)
+#define ZYNQ_GPIOB_CFG_HSTL (ZYNQ_GPIOB_BASE + 0x014)
+#define ZYNQ_GPIOB_DRV_BIAS_CTRL (ZYNQ_GPIOB_BASE + 0x018)
+#define ZYNQ_DDRIOB_BASE (ZYNQ_SLCR_BASE + 0xB40)
+#define ZYNQ_DDRIOB_ADDR0 (ZYNQ_DDRIOB_BASE + 0x000)
+#define ZYNQ_DDRIOB_ADDR1 (ZYNQ_DDRIOB_BASE + 0x004)
+#define ZYNQ_DDRIOB_DATA0 (ZYNQ_DDRIOB_BASE + 0x008)
+#define ZYNQ_DDRIOB_DATA1 (ZYNQ_DDRIOB_BASE + 0x00C)
+#define ZYNQ_DDRIOB_DIFF0 (ZYNQ_DDRIOB_BASE + 0x010)
+#define ZYNQ_DDRIOB_DIFF1 (ZYNQ_DDRIOB_BASE + 0x014)
+#define ZYNQ_DDRIOB_CLOCK (ZYNQ_DDRIOB_BASE + 0x018)
+#define ZYNQ_DDRIOB_DRIVE_SLEW_ADDR (ZYNQ_DDRIOB_BASE + 0x01C)
+#define ZYNQ_DDRIOB_DRIVE_SLEW_DATA (ZYNQ_DDRIOB_BASE + 0x020)
+#define ZYNQ_DDRIOB_DRIVE_SLEW_DIFF (ZYNQ_DDRIOB_BASE + 0x024)
+#define ZYNQ_DDRIOB_DRIVE_SLEW_CLOCK (ZYNQ_DDRIOB_BASE + 0x028)
+#define ZYNQ_DDRIOB_DDR_CTRL (ZYNQ_DDRIOB_BASE + 0x02C)
+#define ZYNQ_DDRIOB_DCI_CTRL (ZYNQ_DDRIOB_BASE + 0x030)
+#define ZYNQ_DDRIOB_DCI_STATUS (ZYNQ_DDRIOB_BASE + 0x034)
+
+#define ZYNQ_TTC0_BASE_ADDR 0xF8001000
+#define ZYNQ_TTC1_BASE_ADDR 0xF8002000
+
+#define ZYNQ_DDRC_BASE 0xF8006000
+
+#define CORTEXA9_SCU_TIMER_BASE_ADDR 0xF8F00600
diff --git a/arch/arm/mach-zynq/zynq.c b/arch/arm/mach-zynq/zynq.c
new file mode 100644
index 0000000..bd29e13
--- /dev/null
+++ b/arch/arm/mach-zynq/zynq.c
@@ -0,0 +1,56 @@
+/*
+ * (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <asm/system.h>
+#include <asm-generic/io.h>
+#include <common.h>
+#include <init.h>
+#include <mach/zynq7000-regs.h>
+
+static int zynq_init(void)
+{
+ u32 val;
+
+ dsb();
+ isb();
+ writel(0xDF0D, ZYNQ_SLCR_UNLOCK);
+ /* remap ocm high */
+ writel(0x0000000F, 0xf8000910);
+ /* mpcore.filtering_start_address */
+ writel(0x00000000, 0xf8f00040);
+ /* mpcore.filtering_end_address */
+ writel(0xffe00000, 0xf8f00044);
+ val = readl(0xf8f00000);
+ val |= 0x2;
+ writel(val, 0xf8f00000);
+ dmb();
+
+ add_generic_device("zynq-clock", 0, NULL, ZYNQ_SLCR_BASE, 0x4000, IORESOURCE_MEM, NULL);
+ add_generic_device("smp_twd", 0, NULL, CORTEXA9_SCU_TIMER_BASE_ADDR,
+ 0x4000, IORESOURCE_MEM, NULL);
+ return 0;
+}
+postcore_initcall(zynq_init);
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+ /* write unlock key to slcr */
+ writel(0xDF0D, ZYNQ_SLCR_UNLOCK);
+ /* reset */
+ writel(0x1, ZYNQ_PSS_RST_CTRL);
+
+ while (1)
+ ;
+}
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h
index b2bd19e..0b98c96 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -5,7 +5,8 @@
defined CONFIG_ARCH_IMX53 || \
defined CONFIG_ARCH_IMX6 || \
defined CONFIG_X86 || \
- defined CONFIG_ARCH_EP93XX
+ defined CONFIG_ARCH_EP93XX || \
+ defined CONFIG_ARCH_ZYNQ
#include <mach/barebox.lds.h>
#endif
--
1.8.2.rc2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000
2013-03-25 13:02 [PATCH v3 0/5] ARM: add support for Zynq Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v3 1/5] serial: Add driver for Cadence UART Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v3 2/5] ARM: zynq: Add new architecture zynq Steffen Trumtrar
@ 2013-03-25 13:02 ` Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v2 4/5] ARM: zynq: add zynq fsbl checksum script Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v3 5/5] ARM: zynq: Add support for the Avnet Zedboard Steffen Trumtrar
4 siblings, 0 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2013-03-25 13:02 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
This adds support for the clocktree on zynq7000 SoCs.
The patch is based on clocks.c from the larger patch
ARM: zynq: add suppport for Zynq 7000 SoC
by Josh Cartwright.
The driver in that patch is converted to a platform_driver and code to
enable plls was added.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
arch/arm/mach-zynq/clk-zynq7000.c | 417 +++++++++++++++++++++++++++++++
arch/arm/mach-zynq/include/mach/clkdev.h | 6 +
2 files changed, 423 insertions(+)
create mode 100644 arch/arm/mach-zynq/clk-zynq7000.c
create mode 100644 arch/arm/mach-zynq/include/mach/clkdev.h
diff --git a/arch/arm/mach-zynq/clk-zynq7000.c b/arch/arm/mach-zynq/clk-zynq7000.c
new file mode 100644
index 0000000..1e03514
--- /dev/null
+++ b/arch/arm/mach-zynq/clk-zynq7000.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2013 Josh Cartwright <joshc@eso.teric.us>
+ * Copyright (c) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * Based on drivers/clk-zynq.c from Linux.
+ *
+ * Copyright (c) 2012 National Instruments
+ *
+ * Josh Cartwright <josh.cartwright@ni.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <mach/zynq7000-regs.h>
+#include <malloc.h>
+
+enum zynq_clks {
+ dummy, ps_clk, arm_pll, ddr_pll, io_pll, uart_clk, uart0, uart1,
+ cpu_clk, cpu_6x4x, cpu_3x2x, cpu_2x, cpu_1x, clks_max
+};
+
+enum zynq_pll_type {
+ ZYNQ_PLL_ARM,
+ ZYNQ_PLL_DDR,
+ ZYNQ_PLL_IO,
+};
+
+#define PLL_STATUS_ARM_PLL_LOCK (1 << 0)
+#define PLL_STATUS_DDR_PLL_LOCK (1 << 1)
+#define PLL_STATUS_IO_PLL_LOCK (1 << 2)
+#define PLL_STATUS_ARM_PLL_STABLE (1 << 0)
+#define PLL_STATUS_DDR_PLL_STABLE (1 << 1)
+#define PLL_STATUS_IO_PLL_STABLE (1 << 2)
+#define PLL_CTRL_BYPASS_FORCE (1 << 4)
+
+static struct clk *clks[clks_max];
+
+struct zynq_pll_clk {
+ struct clk clk;
+ u32 pll_lock;
+ void __iomem *pll_ctrl;
+};
+
+#define to_zynq_pll_clk(c) container_of(c, struct zynq_pll_clk, clk)
+
+#define PLL_CTRL_FDIV(x) (((x) >> 12) & 0x7F)
+
+static unsigned long zynq_pll_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+ return parent_rate * PLL_CTRL_FDIV(readl(pll->pll_ctrl));
+}
+
+static int zynq_pll_enable(struct clk *clk)
+{
+ struct zynq_pll_clk *pll = to_zynq_pll_clk(clk);
+ u32 val;
+ int timeout = 10000;
+
+ val = readl(pll->pll_ctrl);
+ val &= ~PLL_CTRL_BYPASS_FORCE;
+ writel(val, pll->pll_ctrl);
+
+ while (timeout--) {
+ if (readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & pll->pll_lock)
+ break;
+ }
+
+ if (!timeout)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static struct clk_ops zynq_pll_clk_ops = {
+ .recalc_rate = zynq_pll_recalc_rate,
+ .enable = zynq_pll_enable,
+};
+
+static inline struct clk *zynq_pll_clk(enum zynq_pll_type type,
+ const char *name,
+ void __iomem *pll_ctrl)
+{
+ static const char *pll_parent = "ps_clk";
+ struct zynq_pll_clk *pll;
+ int ret;
+
+ pll = xzalloc(sizeof(*pll));
+ pll->pll_ctrl = pll_ctrl;
+ pll->clk.ops = &zynq_pll_clk_ops;
+ pll->clk.name = name;
+ pll->clk.parent_names = &pll_parent;
+ pll->clk.num_parents = 1;
+
+ switch(type) {
+ case ZYNQ_PLL_ARM:
+ pll->pll_lock = PLL_STATUS_ARM_PLL_LOCK;
+ break;
+ case ZYNQ_PLL_DDR:
+ pll->pll_lock = PLL_STATUS_DDR_PLL_LOCK;
+ break;
+ case ZYNQ_PLL_IO:
+ pll->pll_lock = PLL_STATUS_IO_PLL_LOCK;
+ break;
+ }
+
+ ret = clk_register(&pll->clk);
+ if (ret) {
+ free(pll);
+ return ERR_PTR(ret);
+ }
+
+ return &pll->clk;
+}
+
+struct zynq_periph_clk {
+ struct clk clk;
+ void __iomem *clk_ctrl;
+};
+
+#define to_zynq_periph_clk(c) container_of(c, struct zynq_periph_clk, c)
+
+static const u8 periph_clk_parent_map[] = {
+ 0, 0, 1, 2
+};
+#define PERIPH_CLK_CTRL_SRC(x) (periph_clk_parent_map[((x) & 0x30) >> 4])
+#define PERIPH_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_periph_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(clk);
+ return parent_rate / PERIPH_CLK_CTRL_DIV(readl(periph->clk_ctrl));
+}
+
+static int zynq_periph_get_parent(struct clk *clk)
+{
+ struct zynq_periph_clk *periph = to_zynq_periph_clk(clk);
+ return PERIPH_CLK_CTRL_SRC(readl(periph->clk_ctrl));
+}
+
+static const struct clk_ops zynq_periph_clk_ops = {
+ .recalc_rate = zynq_periph_recalc_rate,
+ .get_parent = zynq_periph_get_parent,
+};
+
+static struct clk *zynq_periph_clk(const char *name, void __iomem *clk_ctrl)
+{
+ static const char *peripheral_parents[] = {
+ "io_pll",
+ "arm_pll",
+ "ddr_pll",
+ };
+ struct zynq_periph_clk *periph;
+ int ret;
+
+ periph = xzalloc(sizeof(*periph));
+
+ periph->clk_ctrl = clk_ctrl;
+ periph->clk.name = name;
+ periph->clk.ops = &zynq_periph_clk_ops;
+ periph->clk.parent_names = peripheral_parents;
+ periph->clk.num_parents = ARRAY_SIZE(peripheral_parents);
+
+ ret = clk_register(&periph->clk);
+ if (ret) {
+ free(periph);
+ return ERR_PTR(ret);
+ }
+
+ return &periph->clk;
+}
+
+/* CPU Clock domain is modelled as a mux with 4 children subclks, whose
+ * derivative rates depend on CLK_621_TRUE
+ */
+
+struct zynq_cpu_clk {
+ struct clk clk;
+ void __iomem *clk_ctrl;
+};
+
+#define to_zynq_cpu_clk(c) container_of(c, struct zynq_cpu_clk, c)
+
+static const u8 zynq_cpu_clk_parent_map[] = {
+ 1, 1, 2, 0
+};
+#define CPU_CLK_SRCSEL(x) (zynq_cpu_clk_parent_map[(((x) & 0x30) >> 4)])
+#define CPU_CLK_CTRL_DIV(x) (((x) & 0x3F00) >> 8)
+
+static unsigned long zynq_cpu_clk_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(clk);
+ return parent_rate / CPU_CLK_CTRL_DIV(readl(cpuclk->clk_ctrl));
+}
+
+static int zynq_cpu_clk_get_parent(struct clk *clk)
+{
+ struct zynq_cpu_clk *cpuclk = to_zynq_cpu_clk(clk);
+ return CPU_CLK_SRCSEL(readl(cpuclk->clk_ctrl));
+}
+
+static const struct clk_ops zynq_cpu_clk_ops = {
+ .get_parent = zynq_cpu_clk_get_parent,
+ .recalc_rate = zynq_cpu_clk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_clk(const char *name, void __iomem *clk_ctrl)
+{
+ static const char *cpu_parents[] = {
+ "io_pll",
+ "arm_pll",
+ "ddr_pll",
+ };
+ struct zynq_cpu_clk *cpu;
+ int ret;
+
+ cpu = xzalloc(sizeof(*cpu));
+
+ cpu->clk_ctrl = clk_ctrl;
+ cpu->clk.ops = &zynq_cpu_clk_ops;
+ cpu->clk.name = name;
+ cpu->clk.parent_names = cpu_parents;
+ cpu->clk.num_parents = ARRAY_SIZE(cpu_parents);
+
+ ret = clk_register(&cpu->clk);
+ if (ret) {
+ free(cpu);
+ return ERR_PTR(ret);
+ }
+
+ return &cpu->clk;
+}
+
+enum zynq_cpu_subclk_which {
+ CPU_SUBCLK_6X4X,
+ CPU_SUBCLK_3X2X,
+ CPU_SUBCLK_2X,
+ CPU_SUBCLK_1X,
+};
+
+struct zynq_cpu_subclk {
+ struct clk clk;
+ void __iomem *clk_ctrl;
+ void __iomem *clk_621;
+ enum zynq_cpu_subclk_which which;
+};
+
+#define CLK_621_TRUE(x) ((x) & 1)
+
+#define to_zynq_cpu_subclk(c) container_of(c, struct zynq_cpu_subclk, c);
+
+static unsigned long zynq_cpu_subclk_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+ unsigned long uninitialized_var(rate);
+ struct zynq_cpu_subclk *subclk;
+ bool is_621;
+
+ subclk = to_zynq_cpu_subclk(clk);
+ is_621 = CLK_621_TRUE(readl(subclk->clk_621));
+
+ switch (subclk->which) {
+ case CPU_SUBCLK_6X4X:
+ rate = parent_rate;
+ break;
+ case CPU_SUBCLK_3X2X:
+ rate = parent_rate / 2;
+ break;
+ case CPU_SUBCLK_2X:
+ rate = parent_rate / (is_621 ? 3 : 2);
+ break;
+ case CPU_SUBCLK_1X:
+ rate = parent_rate / (is_621 ? 6 : 4);
+ break;
+ };
+
+ return rate;
+}
+
+static int zynq_cpu_subclk_enable(struct clk *clk)
+{
+ struct zynq_cpu_subclk *subclk;
+ u32 tmp;
+
+ subclk = to_zynq_cpu_subclk(clk);
+
+ tmp = readl(subclk->clk_ctrl);
+ tmp |= 1 << (24 + subclk->which);
+ writel(tmp, subclk->clk_ctrl);
+
+ return 0;
+}
+
+static void zynq_cpu_subclk_disable(struct clk *clk)
+{
+ struct zynq_cpu_subclk *subclk;
+ u32 tmp;
+
+ subclk = to_zynq_cpu_subclk(clk);
+
+ tmp = readl(subclk->clk_ctrl);
+ tmp &= ~(1 << (24 + subclk->which));
+ writel(tmp, subclk->clk_ctrl);
+}
+
+static const struct clk_ops zynq_cpu_subclk_ops = {
+ .enable = zynq_cpu_subclk_enable,
+ .disable = zynq_cpu_subclk_disable,
+ .recalc_rate = zynq_cpu_subclk_recalc_rate,
+};
+
+static struct clk *zynq_cpu_subclk(const char *name,
+ enum zynq_cpu_subclk_which which,
+ void __iomem *clk_ctrl,
+ void __iomem *clk_621)
+{
+ static const char *subclk_parent = "cpu_clk";
+ struct zynq_cpu_subclk *subclk;
+ int ret;
+
+ subclk = xzalloc(sizeof(*subclk));
+
+ subclk->clk_ctrl = clk_ctrl;
+ subclk->clk_621 = clk_621;
+ subclk->which = which;
+ subclk->clk.name = name;
+ subclk->clk.ops = &zynq_cpu_subclk_ops;
+
+ subclk->clk.parent_names = &subclk_parent;
+ subclk->clk.num_parents = 1;
+
+ ret = clk_register(&subclk->clk);
+ if (ret) {
+ free(subclk);
+ return ERR_PTR(ret);
+ }
+
+ return &subclk->clk;
+}
+
+static int zynq_clock_probe(struct device_d *dev)
+{
+ void __iomem *slcr_base;
+ unsigned long ps_clk_rate = 33333330;
+
+ slcr_base = dev_request_mem_region(dev, 0);
+ if (!slcr_base)
+ return -EBUSY;
+
+ clks[ps_clk] = clk_fixed("ps_clk", ps_clk_rate);
+
+ clks[arm_pll] = zynq_pll_clk(ZYNQ_PLL_ARM, "arm_pll", slcr_base + 0x100);
+ clks[ddr_pll] = zynq_pll_clk(ZYNQ_PLL_DDR, "ddr_pll", slcr_base + 0x104);
+ clks[io_pll] = zynq_pll_clk(ZYNQ_PLL_IO, "io_pll", slcr_base + 0x108);
+
+ clks[uart_clk] = zynq_periph_clk("uart_clk", slcr_base + 0x154);
+
+ clks[uart0] = clk_gate("uart0", "uart_clk", slcr_base + 0x154, 0);
+ clks[uart1] = clk_gate("uart1", "uart_clk", slcr_base + 0x154, 1);
+
+ clks[cpu_clk] = zynq_cpu_clk("cpu_clk", slcr_base + 0x120);
+
+ clks[cpu_6x4x] = zynq_cpu_subclk("cpu_6x4x", CPU_SUBCLK_6X4X,
+ slcr_base + 0x120, slcr_base + 0x1C4);
+ clks[cpu_3x2x] = zynq_cpu_subclk("cpu_3x2x", CPU_SUBCLK_3X2X,
+ slcr_base + 0x120, slcr_base + 0x1C4);
+ clks[cpu_2x] = zynq_cpu_subclk("cpu_2x", CPU_SUBCLK_2X,
+ slcr_base + 0x120, slcr_base + 0x1C4);
+ clks[cpu_1x] = zynq_cpu_subclk("cpu_1x", CPU_SUBCLK_1X,
+ slcr_base + 0x120, slcr_base + 0x1C4);
+
+ clk_register_clkdev(clks[cpu_3x2x], NULL, "arm_smp_twd");
+ clk_register_clkdev(clks[uart0], NULL, "zynq_serial0");
+ clk_register_clkdev(clks[uart1], NULL, "zynq_serial1");
+
+ clkdev_add_physbase(clks[cpu_3x2x], CORTEXA9_SCU_TIMER_BASE_ADDR, NULL);
+ clkdev_add_physbase(clks[uart1], ZYNQ_UART1_BASE_ADDR, NULL);
+ return 0;
+}
+
+static __maybe_unused struct of_device_id zynq_clock_dt_ids[] = {
+ {
+ .compatible = "xlnx,zynq-clock",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d zynq_clock_driver = {
+ .probe = zynq_clock_probe,
+ .name = "zynq-clock",
+ .of_compatible = DRV_OF_COMPAT(zynq_clock_dt_ids),
+};
+
+static int zynq_clock_init(void)
+{
+ return platform_driver_register(&zynq_clock_driver);
+}
+postcore_initcall(zynq_clock_init);
diff --git a/arch/arm/mach-zynq/include/mach/clkdev.h b/arch/arm/mach-zynq/include/mach/clkdev.h
new file mode 100644
index 0000000..31f7035
--- /dev/null
+++ b/arch/arm/mach-zynq/include/mach/clkdev.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+#endif
--
1.8.2.rc2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/5] ARM: zynq: add zynq fsbl checksum script
2013-03-25 13:02 [PATCH v3 0/5] ARM: add support for Zynq Steffen Trumtrar
` (2 preceding siblings ...)
2013-03-25 13:02 ` [PATCH v2 3/5] ARM: zynq: add clk support for zynq7000 Steffen Trumtrar
@ 2013-03-25 13:02 ` Steffen Trumtrar
2013-03-25 13:02 ` [PATCH v3 5/5] ARM: zynq: Add support for the Avnet Zedboard Steffen Trumtrar
4 siblings, 0 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2013-03-25 13:02 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
The bootrom only reads an image if the correct checksum is present in the
header. The calculation is pretty simple:
sum over all words from 0x20 to 0x44
Two of this words are the image length. That is why the checksum can not be
calculated until barebox_image_size is known.
The easiest solution is a program that has to be run after make.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
scripts/Makefile | 1 +
scripts/zynq_checksum.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 scripts/zynq_checksum.c
diff --git a/scripts/Makefile b/scripts/Makefile
index 08b325c..41c892e 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -12,6 +12,7 @@ hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image
hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-am35xx-spi-image
hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum
hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader
+hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_checksum
HOSTLOADLIBES_omap4_usbboot = -lpthread
omap4_usbboot-objs := usb_linux.o omap4_usbboot.o
diff --git a/scripts/zynq_checksum.c b/scripts/zynq_checksum.c
new file mode 100644
index 0000000..f32db61
--- /dev/null
+++ b/scripts/zynq_checksum.c
@@ -0,0 +1,72 @@
+#include <endian.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+static void usage(char *name)
+{
+ printf("Usage: %s barebox.bin <outfile>\n", name);
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *ifile, *ofile;
+ unsigned int *buf;
+ const char *infile;
+ const char *outfile;
+ struct stat st;
+ unsigned int i;
+ unsigned long sum = 0;
+
+ if (argc != 3) {
+ usage(argv[0]);
+ exit(1);
+ }
+
+ infile = argv[1];
+ outfile = argv[2];
+
+ if (stat(infile, &st) == -1) {
+ perror("stat");
+ exit(EXIT_FAILURE);
+ }
+
+ buf = malloc(sizeof(*buf) * st.st_size);
+ if (!buf) {
+ fprintf(stderr, "Unable to allocate buffer\n");
+ return -1;
+ }
+ ifile = fopen(infile, "rb");
+ if (!ifile) {
+ fprintf(stderr, "Cannot open %s for reading\n",
+ infile);
+ free(buf);
+ exit(EXIT_FAILURE);
+ }
+ ofile = fopen(outfile, "wb");
+ if (!ofile) {
+ fprintf(stderr, "Cannot open %s for writing\n",
+ outfile);
+ fclose(ifile);
+ free(buf);
+ exit(EXIT_FAILURE);
+ }
+
+ fread(buf, 4, st.st_size, ifile);
+
+ for (i = 0x8; i < 0x12; i++)
+ sum += htole32(buf[i]);
+
+ sum = ~sum;
+ buf[i] = sum;
+
+ fwrite(buf, st.st_size / 4, 4, ofile);
+
+ fclose(ofile);
+ fclose(ifile);
+ free(buf);
+
+ return 0;
+}
--
1.8.2.rc2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v3 5/5] ARM: zynq: Add support for the Avnet Zedboard
2013-03-25 13:02 [PATCH v3 0/5] ARM: add support for Zynq Steffen Trumtrar
` (3 preceding siblings ...)
2013-03-25 13:02 ` [PATCH v2 4/5] ARM: zynq: add zynq fsbl checksum script Steffen Trumtrar
@ 2013-03-25 13:02 ` Steffen Trumtrar
4 siblings, 0 replies; 6+ messages in thread
From: Steffen Trumtrar @ 2013-03-25 13:02 UTC (permalink / raw)
To: barebox; +Cc: Steffen Trumtrar
The Avnet ZedBoard is an evalboard with a Zynq-7020 based MPSoC.
There is also a Digilent ZedBoard, that is the same but only for
academic customers.
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
Changes since v2:
- use pbl image
- remove useless flash_header_start
arch/arm/boards/avnet-zedboard/Makefile | 3 +
arch/arm/boards/avnet-zedboard/board.c | 38 ++++
arch/arm/boards/avnet-zedboard/config.h | 4 +
.../boards/avnet-zedboard/env/init/config-board | 7 +
| 62 +++++
arch/arm/boards/avnet-zedboard/lowlevel.c | 252 +++++++++++++++++++++
arch/arm/configs/zedboard_defconfig | 49 ++++
7 files changed, 415 insertions(+)
create mode 100644 arch/arm/boards/avnet-zedboard/Makefile
create mode 100644 arch/arm/boards/avnet-zedboard/board.c
create mode 100644 arch/arm/boards/avnet-zedboard/config.h
create mode 100644 arch/arm/boards/avnet-zedboard/env/init/config-board
create mode 100644 arch/arm/boards/avnet-zedboard/flash_header.c
create mode 100644 arch/arm/boards/avnet-zedboard/lowlevel.c
create mode 100644 arch/arm/configs/zedboard_defconfig
diff --git a/arch/arm/boards/avnet-zedboard/Makefile b/arch/arm/boards/avnet-zedboard/Makefile
new file mode 100644
index 0000000..a2c3104
--- /dev/null
+++ b/arch/arm/boards/avnet-zedboard/Makefile
@@ -0,0 +1,3 @@
+obj-y += board.o
+lwl-y += lowlevel.o
+lwl-y += flash_header.o
diff --git a/arch/arm/boards/avnet-zedboard/board.c b/arch/arm/boards/avnet-zedboard/board.c
new file mode 100644
index 0000000..4e3d5a5
--- /dev/null
+++ b/arch/arm/boards/avnet-zedboard/board.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/armlinux.h>
+#include <common.h>
+#include <environment.h>
+#include <generated/mach-types.h>
+#include <init.h>
+#include <mach/devices.h>
+#include <mach/zynq7000-regs.h>
+#include <sizes.h>
+
+static int zedboard_mem_init(void)
+{
+ arm_add_mem_device("ram0", 0, SZ_512M);
+
+ return 0;
+}
+mem_initcall(zedboard_mem_init);
+
+static int zedboard_console_init(void)
+{
+ zynq_add_uart1();
+
+ return 0;
+}
+console_initcall(zedboard_console_init);
diff --git a/arch/arm/boards/avnet-zedboard/config.h b/arch/arm/boards/avnet-zedboard/config.h
new file mode 100644
index 0000000..ca15136
--- /dev/null
+++ b/arch/arm/boards/avnet-zedboard/config.h
@@ -0,0 +1,4 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#endif /* __CONFIG_H */
diff --git a/arch/arm/boards/avnet-zedboard/env/init/config-board b/arch/arm/boards/avnet-zedboard/env/init/config-board
new file mode 100644
index 0000000..9957653
--- /dev/null
+++ b/arch/arm/boards/avnet-zedboard/env/init/config-board
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# board defaults, do not change in running system. Change /env/config
+# instead
+
+global.hostname=ZedBoard
+global.linux.bootargs.base="console=ttyPS1,115200"
--git a/arch/arm/boards/avnet-zedboard/flash_header.c b/arch/arm/boards/avnet-zedboard/flash_header.c
new file mode 100644
index 0000000..ea20524
--- /dev/null
+++ b/arch/arm/boards/avnet-zedboard/flash_header.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <asm/byteorder.h>
+#include <mach/zynq-flash-header.h>
+#include <mach/zynq7000-regs.h>
+#include <asm/barebox-arm-head.h>
+
+#define REG(a, v) { .addr = cpu_to_le32(a), .val = cpu_to_le32(v), }
+
+struct zynq_reg_entry __ps7reg_entry_section reg_entry[] = {
+ REG(ZYNQ_SLCR_UNLOCK, 0x0000DF0D),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_CLK_621_TRUE, 0x00000001),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_APER_CLK_CTRL, 0x01FC044D),
+
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL, 0x00028008),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CFG, 0x000FA220),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL, 0x00028010),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL, 0x00028011),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL, 0x00028010),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL, 0x00028000),
+
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL, 0x0001E008),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CFG, 0x001452C0),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL, 0x0001E010),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL, 0x0001E011),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL, 0x0001E010),
+ REG(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL, 0x0001E000),
+
+ REG(0xf8000150, 0x00000a03),
+
+ /* stop */
+ REG(0xFFFFFFFF, 0x00000000),
+};
+
+struct zynq_flash_header __flash_header_section flash_header = {
+ .width_det = WIDTH_DETECTION_MAGIC,
+ .image_id = IMAGE_IDENTIFICATION,
+ .enc_stat = 0x0,
+ .user = 0x0,
+ .flash_offset = 0x8c0,
+ .length = barebox_image_size,
+ .res0 = 0x0,
+ .start_of_exec = 0x0,
+ .total_len = barebox_image_size,
+ .res1 = 0x1,
+ .checksum = 0x0,
+ .res2 = 0x0,
+};
diff --git a/arch/arm/boards/avnet-zedboard/lowlevel.c b/arch/arm/boards/avnet-zedboard/lowlevel.c
new file mode 100644
index 0000000..b50886e
--- /dev/null
+++ b/arch/arm/boards/avnet-zedboard/lowlevel.c
@@ -0,0 +1,252 @@
+/*
+ *
+ * (c) 2013 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <io.h>
+#include <asm/barebox-arm.h>
+#include <asm/barebox-arm-head.h>
+#include <mach/zynq7000-regs.h>
+
+#define DCI_DONE (1 << 13)
+#define PLL_ARM_LOCK (1 << 0)
+#define PLL_DDR_LOCK (1 << 1)
+#define PLL_IO_LOCK (1 << 2)
+
+void __naked barebox_arm_reset_vector(void)
+{
+ /* open sesame */
+ writel(0x0000DF0D, ZYNQ_SLCR_UNLOCK);
+
+ /* turn on LD9 */
+ writel(0x00000200, 0xF800071C);
+ writel(0x00000080, 0xE000A204);
+ writel(0x00000080, 0xE000A000);
+
+ /* ps7_clock_init_data */
+ writel(0x1F000200, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_CLK_CTRL);
+ writel(0x00F00701, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DCI_CLK_CTRL);
+ writel(0x00002803, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_UART_CLK_CTRL);
+ writel(0x00000A03, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DBG_CLK_CTRL);
+ writel(0x00000501, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PCAP_CLK_CTRL);
+ writel(0x00000000, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_TOPSW_CLK_CTRL);
+ writel(0x00100A00, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_FPGA0_CLK_CTRL);
+ writel(0x00100700, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_FPGA1_CLK_CTRL);
+ writel(0x00101400, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_FPGA2_CLK_CTRL);
+ writel(0x00101400, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_FPGA3_CLK_CTRL);
+ /* 6:2:1 mode */
+ writel(0x00000001, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_CLK_621_TRUE);
+ writel(0x01FC044D, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_APER_CLK_CTRL);
+
+ /* configure the PLLs */
+ /* ARM PLL */
+ writel(0x00028008, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL);
+ writel(0x000FA220, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CFG);
+ writel(0x00028010, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL);
+ writel(0x00028011, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL);
+ writel(0x00028010, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL);
+
+ while (!(readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & PLL_ARM_LOCK))
+ ;
+ writel(0x00028000, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_ARM_PLL_CTRL);
+
+ /* DDR PLL */
+ /* set to bypass mode */
+ writel(0x0001A018, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_PLL_CTRL);
+ /* assert reset */
+ writel(0x0001A019, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_PLL_CTRL);
+ /* set feedback divs */
+ writel(0x00020019, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_PLL_CTRL);
+ writel(0x0012C220, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_PLL_CFG);
+ /* set ddr2xclk and ddr3xclk: 3,2 */
+ writel(0x0C200003, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_CLK_CTRL);
+ /* deassert reset */
+ writel(0x00020018, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_PLL_CTRL);
+ /* wait pll lock */
+ while (!(readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & PLL_DDR_LOCK))
+ ;
+ /* remove bypass mode */
+ writel(0x00020008, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_DDR_PLL_CTRL);
+
+ /* IO PLL */
+ writel(0x0001E008, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL);
+ writel(0x001452C0, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CFG);
+ writel(0x0001E010, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL);
+ writel(0x0001E011, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL);
+ writel(0x0001E010, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL);
+
+ while (!(readl(ZYNQ_CLOCK_CTRL_BASE + ZYNQ_PLL_STATUS) & PLL_IO_LOCK))
+ ;
+ writel(0x0001E000, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_IO_PLL_CTRL);
+
+ /*
+ * INP_TYPE[1:2] = {off, vref, diff, lvcmos}
+ * DCI_UPDATE[3], TERM_EN[4]
+ * DCI_TYPE[5:6] = {off, drive, res, term}
+ * IBUF_DISABLE_MODE[7] = {ibuf, ibuf_disable}
+ * TERM_DISABLE_MODE[8] = {always, dynamic}
+ * OUTPUT_EN[9:10] = {ibuf, res, res, obuf}
+ * PULLUP_EN[11]
+ */
+ writel(0x00000600, ZYNQ_DDRIOB_ADDR0);
+ writel(0x00000600, ZYNQ_DDRIOB_ADDR1);
+ writel(0x00000672, ZYNQ_DDRIOB_DATA0);
+ writel(0x00000672, ZYNQ_DDRIOB_DATA1);
+ writel(0x00000674, ZYNQ_DDRIOB_DIFF0);
+ writel(0x00000674, ZYNQ_DDRIOB_DIFF1);
+ writel(0x00000600, ZYNQ_DDRIOB_CLOCK);
+ /*
+ * Drive_P[0:6], Drive_N[7:13]
+ * Slew_P[14:18], Slew_N[19:23]
+ * GTL[24:26], RTerm[27:31]
+ */
+ writel(0x00D6861C, ZYNQ_DDRIOB_DRIVE_SLEW_ADDR);
+ writel(0x00F9861C, ZYNQ_DDRIOB_DRIVE_SLEW_DATA);
+ writel(0x00F9861C, ZYNQ_DDRIOB_DRIVE_SLEW_DIFF);
+ writel(0x00D6861C, ZYNQ_DDRIOB_DRIVE_SLEW_CLOCK);
+ /*
+ * VREF_INT_EN[0]
+ * VREF_SEL[1:4] = {0001=0.6V, 0100=0.75V, 1000=0.9V}
+ * VREF_EXT_EN[5:6] = {dis/dis, dis/en, en/dis, en/en}
+ * RES[7:8], REFIO_EN[9]
+ */
+ /* FIXME: Xilinx sets this to internal, but Zedboard should support
+ external VRef, too */
+ writel(0x00000E09, ZYNQ_DDRIOB_DDR_CTRL);
+ /*
+ * RESET[0], ENABLE[1]
+ * NREF_OPT1[6:7], NREF_OPT2[8:10], NREF_OPT4[11:13]
+ * PREF_OPT1[14:15], PREF_OPT2[17:19], UPDATE_CONTROL[20]
+ */
+ writel(0x00000021, ZYNQ_DDRIOB_DCI_CTRL);
+ writel(0x00000020, ZYNQ_DDRIOB_DCI_CTRL);
+ writel(0x00100823, ZYNQ_DDRIOB_DCI_CTRL);
+
+ while (!(readl(ZYNQ_DDRIOB_DCI_STATUS) & DCI_DONE))
+ ;
+
+ writel(0x0E00E07F, 0xF8007000);
+
+ /* ps7_ddr_init_data */
+ writel(0x00000080, 0XF8006000);
+ writel(0x00081081, 0XF8006004);
+ writel(0x03C0780F, 0XF8006008);
+ writel(0x02001001, 0XF800600C);
+ writel(0x00014001, 0XF8006010);
+ writel(0x0004159B, 0XF8006014);
+ writel(0x452460D2, 0XF8006018);
+ writel(0x720238E5, 0XF800601C);
+ writel(0x272872D0, 0XF8006020);
+ writel(0x0000003C, 0XF8006024);
+ writel(0x00002007, 0XF8006028);
+ writel(0x00000008, 0XF800602C);
+ writel(0x00040930, 0XF8006030);
+ writel(0x00010694, 0XF8006034);
+ writel(0x00000000, 0XF8006038);
+ writel(0x00000777, 0XF800603C);
+ writel(0xFFF00000, 0XF8006040);
+ writel(0x0FF66666, 0XF8006044);
+ writel(0x0003C248, 0XF8006048);
+ writel(0x77010800, 0XF8006050);
+ writel(0x00000101, 0XF8006058);
+ writel(0x00005003, 0XF800605C);
+ writel(0x0000003E, 0XF8006060);
+ writel(0x00020000, 0XF8006064);
+ writel(0x00284141, 0XF8006068);
+ writel(0x00001610, 0XF800606C);
+ writel(0x00008000, 0XF80060A0);
+ writel(0x10200802, 0XF80060A4);
+ writel(0x0690CB73, 0XF80060A8);
+ writel(0x000001FE, 0XF80060AC);
+ writel(0x1CFFFFFF, 0XF80060B0);
+ writel(0x00000200, 0XF80060B4);
+ writel(0x00200066, 0XF80060B8);
+ writel(0x00000000, 0XF80060BC);
+ writel(0x00000000, 0XF80060C4);
+ writel(0x00000000, 0XF80060C8);
+ writel(0x00000000, 0XF80060DC);
+ writel(0x00000000, 0XF80060F0);
+ writel(0x00000008, 0XF80060F4);
+ writel(0x00000000, 0XF8006114);
+ writel(0x40000001, 0XF8006118);
+ writel(0x40000001, 0XF800611C);
+ writel(0x40000001, 0XF8006120);
+ writel(0x40000001, 0XF8006124);
+ writel(0x00033C03, 0XF800612C);
+ writel(0x00034003, 0XF8006130);
+ writel(0x0002F400, 0XF8006134);
+ writel(0x00030400, 0XF8006138);
+ writel(0x00000035, 0XF8006140);
+ writel(0x00000035, 0XF8006144);
+ writel(0x00000035, 0XF8006148);
+ writel(0x00000035, 0XF800614C);
+ writel(0x00000083, 0XF8006154);
+ writel(0x00000083, 0XF8006158);
+ writel(0x0000007F, 0XF800615C);
+ writel(0x00000078, 0XF8006160);
+ writel(0x00000124, 0XF8006168);
+ writel(0x00000125, 0XF800616C);
+ writel(0x00000112, 0XF8006170);
+ writel(0x00000116, 0XF8006174);
+ writel(0x000000C3, 0XF800617C);
+ writel(0x000000C3, 0XF8006180);
+ writel(0x000000BF, 0XF8006184);
+ writel(0x000000B8, 0XF8006188);
+ writel(0x10040080, 0XF8006190);
+ writel(0x0001FC82, 0XF8006194);
+ writel(0x00000000, 0XF8006204);
+ writel(0x000803FF, 0XF8006208);
+ writel(0x000803FF, 0XF800620C);
+ writel(0x000803FF, 0XF8006210);
+ writel(0x000803FF, 0XF8006214);
+ writel(0x000003FF, 0XF8006218);
+ writel(0x000003FF, 0XF800621C);
+ writel(0x000003FF, 0XF8006220);
+ writel(0x000003FF, 0XF8006224);
+ writel(0x00000000, 0XF80062A8);
+ writel(0x00000000, 0XF80062AC);
+ writel(0x00005125, 0XF80062B0);
+ writel(0x000012A8, 0XF80062B4);
+ writel(0x00000081, 0XF8006000);
+
+ /* poor mans pinctrl */
+ writel(0x000002E0, ZYNQ_MIO_BASE + 0xC0);
+ writel(0x000002E1, ZYNQ_MIO_BASE + 0xC4);
+ /* UART1 pinmux */
+ writel(0x000002E1, ZYNQ_MIO_BASE + 0xC8);
+ writel(0x000002E0, ZYNQ_MIO_BASE + 0xCC);
+
+ /* poor mans clkctrl */
+ writel(0x00001403, ZYNQ_CLOCK_CTRL_BASE + ZYNQ_UART_CLK_CTRL);
+
+ writel(0x00000001, 0xf8000138);
+ writel(0x00100801, 0xf8000140);
+ writel(0x00000302, 0xf8000740);
+ writel(0x00000302, 0xf8000744);
+ writel(0x00000302, 0xf8000748);
+ writel(0x00000302, 0xf800074C);
+ writel(0x00000302, 0xf8000750);
+ writel(0x00000302, 0xf8000754);
+
+ writel(0x00000001, 0xf8000B00);
+
+ /* lock up. secure, secure */
+ writel(0x0000767B, ZYNQ_SLCR_LOCK);
+
+ arm_cpu_lowlevel_init();
+ barebox_arm_entry(0, SZ_512M, 0);
+}
diff --git a/arch/arm/configs/zedboard_defconfig b/arch/arm/configs/zedboard_defconfig
new file mode 100644
index 0000000..773177c
--- /dev/null
+++ b/arch/arm/configs/zedboard_defconfig
@@ -0,0 +1,49 @@
+CONFIG_ARCH_ZYNQ=y
+CONFIG_AEABI=y
+CONFIG_CMD_ARM_MMUINFO=y
+CONFIG_ARM_UNWIND=y
+CONFIG_PBL_IMAGE=y
+CONFIG_MMU=y
+CONFIG_STACK_SIZE=0xf000
+CONFIG_MALLOC_SIZE=0x8000000
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
+CONFIG_LONGHELP=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/avnet-zedboard/env"
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_DIRNAME=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_READLINK=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_OFTREE_PROBE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_CLK=y
+CONFIG_NET=y
+CONFIG_NET_DHCP=y
+# CONFIG_SPI is not set
+CONFIG_FS_TFTP=y
+CONFIG_DIGEST=y
+CONFIG_MD5=y
--
1.8.2.rc2
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 6+ messages in thread