From a89e378be07ca03f4d12b0dc871298211ce4ad31 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 26 Mar 2013 10:11:22 +0100 Subject: [PATCH 1/9] serial: Add driver for Cadence UART Support for Cadence UART core. Signed-off-by: Steffen Trumtrar Signed-off-by: Sascha Hauer --- 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 48bea603e..11fc15507 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -117,4 +117,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 4a23aefdd..93790b534 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -16,3 +16,4 @@ 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_AUART) += serial_auart.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 000000000..c29c39102 --- /dev/null +++ b/drivers/serial/serial_cadence.c @@ -0,0 +1,307 @@ +/* + * (c) 2012 Steffen Trumtrar + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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); From 1bb8460fc19dee2199a74f0fd2c2e8f841d22abe Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 26 Mar 2013 10:11:23 +0100 Subject: [PATCH 2/9] ARM: zynq: Add new architecture zynq 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 Signed-off-by: Sascha Hauer --- 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 ++ .../include/mach/zynq-flash-header.h | 38 +++++ .../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 7ac134e15..bd88131da 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -128,6 +128,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 @@ -146,6 +150,7 @@ source arch/arm/mach-samsung/Kconfig source arch/arm/mach-versatile/Kconfig source arch/arm/mach-vexpress/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 b98d6b86a..3e48a6840 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -66,6 +66,7 @@ machine-$(CONFIG_ARCH_SAMSUNG) := samsung machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_VEXPRESS) := vexpress machine-$(CONFIG_ARCH_TEGRA) := tegra +machine-$(CONFIG_ARCH_ZYNQ) := zynq # Board directory name. This list is sorted alphanumerically # by CONFIG_* macro name. @@ -162,6 +163,7 @@ 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_SABRESD) := freescale-mx6-sabresd +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 000000000..5bbd6483c --- /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 000000000..459c95762 --- /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 000000000..777bb8765 --- /dev/null +++ b/arch/arm/mach-zynq/devices.c @@ -0,0 +1,8 @@ +#include +#include +#include + +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 000000000..3d35fe988 --- /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 000000000..6c20dd534 --- /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 +#include + +#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 000000000..281d7c620 --- /dev/null +++ b/arch/arm/mach-zynq/include/mach/devices.h @@ -0,0 +1,13 @@ +#include + +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); +} diff --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 000000000..3b67e55a7 --- /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 + +#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 000000000..f5ccbb037 --- /dev/null +++ b/arch/arm/mach-zynq/include/mach/zynq7000-regs.h @@ -0,0 +1,132 @@ +/* + * (c) 2012 Steffen Trumtrar + * + * 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 000000000..bd29e1337 --- /dev/null +++ b/arch/arm/mach-zynq/zynq.c @@ -0,0 +1,56 @@ +/* + * (c) 2012 Steffen Trumtrar + * + * 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 +#include +#include +#include +#include + +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 b2bd19ef2..0b98c962c 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 #endif From 097513b8f82404f0e522b2f358195d75f13aa5a5 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 26 Mar 2013 10:11:24 +0100 Subject: [PATCH 3/9] ARM: zynq: add clk support for zynq7000 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 Signed-off-by: Sascha Hauer --- 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 000000000..1e03514f3 --- /dev/null +++ b/arch/arm/mach-zynq/clk-zynq7000.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2013 Josh Cartwright + * Copyright (c) 2013 Steffen Trumtrar + * + * Based on drivers/clk-zynq.c from Linux. + * + * Copyright (c) 2012 National Instruments + * + * Josh Cartwright + * + * 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 . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +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 000000000..31f703514 --- /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 From 26121ef51d4d52482cb98c29ba3f0a337aa1a8c5 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 26 Mar 2013 10:11:25 +0100 Subject: [PATCH 4/9] ARM: zynq: add zynq fsbl checksum script 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 Signed-off-by: Sascha Hauer --- .gitignore | 1 + arch/arm/Makefile | 8 ++++ scripts/.gitignore | 1 + scripts/Makefile | 1 + scripts/zynq_mkimage.c | 86 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 scripts/zynq_mkimage.c diff --git a/.gitignore b/.gitignore index 064753d21..d1971967f 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ barebox.netx barebox.s5p barebox.spi barebox.ubl +barebox.zynq barebox.uimage barebox.map barebox-flash-image diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 3e48a6840..2a59bfec1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -249,6 +249,14 @@ KBUILD_TARGET := barebox.spi KBUILD_IMAGE := barebox.spi endif +barebox.zynq: $(KBUILD_BINARY) + $(Q)scripts/zynq_mkimage $< $@ + +ifeq ($(machine-y),zynq) +KBUILD_TARGET := barebox.zynq +KBUILD_IMAGE := barebox.zynq +endif + pbl := arch/arm/pbl zbarebox.S zbarebox.bin zbarebox: barebox.bin $(Q)$(MAKE) $(build)=$(pbl) $(pbl)/$@ diff --git a/scripts/.gitignore b/scripts/.gitignore index 1ca66030c..bff805ddf 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -7,3 +7,4 @@ mkimage mkublheader omap_signGP omap4_usbboot +zynq_mkimage diff --git a/scripts/Makefile b/scripts/Makefile index 08b325cb5..fd526e549 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_mkimage HOSTLOADLIBES_omap4_usbboot = -lpthread omap4_usbboot-objs := usb_linux.o omap4_usbboot.o diff --git a/scripts/zynq_mkimage.c b/scripts/zynq_mkimage.c new file mode 100644 index 000000000..a096b834d --- /dev/null +++ b/scripts/zynq_mkimage.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 Steffen Trumtrar + * + * 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 +#include +#include +#include +#include +#include + +static void usage(char *name) +{ + printf("Usage: %s barebox-flash-image \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(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; +} From 960a3d216a608567d4adccd08006090e694d273c Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 26 Mar 2013 10:11:26 +0100 Subject: [PATCH 5/9] ARM: zynq: Add support for the Avnet Zedboard 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 Signed-off-by: Sascha Hauer --- arch/arm/boards/avnet-zedboard/Makefile | 3 + arch/arm/boards/avnet-zedboard/board.c | 38 +++ arch/arm/boards/avnet-zedboard/config.h | 4 + .../avnet-zedboard/env/init/config-board | 7 + arch/arm/boards/avnet-zedboard/flash_header.c | 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 000000000..a2c3104e6 --- /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 000000000..4e3d5a58c --- /dev/null +++ b/arch/arm/boards/avnet-zedboard/board.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2013 Steffen Trumtrar + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +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 000000000..ca1513681 --- /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 000000000..99576533c --- /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" diff --git a/arch/arm/boards/avnet-zedboard/flash_header.c b/arch/arm/boards/avnet-zedboard/flash_header.c new file mode 100644 index 000000000..ea2052405 --- /dev/null +++ b/arch/arm/boards/avnet-zedboard/flash_header.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 Steffen Trumtrar + * + * 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 +#include +#include +#include +#include + +#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 000000000..b50886ebc --- /dev/null +++ b/arch/arm/boards/avnet-zedboard/lowlevel.c @@ -0,0 +1,252 @@ +/* + * + * (c) 2013 Steffen Trumtrar + * + * 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 +#include +#include +#include +#include + +#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 000000000..773177c9e --- /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 From 28acd8331de84b4ecb8bc91f56292697bb977b99 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Fri, 15 Mar 2013 18:26:00 -0500 Subject: [PATCH 6/9] macb: rename platform data The macb/gem core is used by the Zynq SoC. In preparation of sharing the macb driver between at91 and Zynq, rename the platform data to 'struct macb_platform_data', and move the definition to a common location. Signed-off-by: Josh Cartwright Signed-off-by: Sascha Hauer --- arch/arm/boards/animeo_ip/init.c | 2 +- arch/arm/boards/at91rm9200ek/init.c | 2 +- arch/arm/boards/at91sam9260ek/init.c | 2 +- arch/arm/boards/at91sam9263ek/init.c | 2 +- arch/arm/boards/at91sam9m10g45ek/init.c | 2 +- arch/arm/boards/at91sam9m10ihd/init.c | 2 +- arch/arm/boards/at91sam9x5ek/init.c | 2 +- arch/arm/boards/dss11/init.c | 2 +- arch/arm/boards/mmccpu/init.c | 2 +- arch/arm/boards/pm9263/init.c | 2 +- arch/arm/boards/pm9g45/init.c | 2 +- arch/arm/boards/qil-a9260/init.c | 2 +- arch/arm/boards/sama5d3xek/init.c | 4 ++-- arch/arm/boards/telit-evk-pro3/init.c | 2 +- arch/arm/boards/tny-a926x/init.c | 2 +- arch/arm/boards/usb-a926x/init.c | 2 +- arch/arm/mach-at91/at91rm9200_devices.c | 4 ++-- arch/arm/mach-at91/at91sam9260_devices.c | 4 ++-- arch/arm/mach-at91/at91sam9263_devices.c | 4 ++-- arch/arm/mach-at91/at91sam9g45_devices.c | 4 ++-- arch/arm/mach-at91/at91sam9x5_devices.c | 4 ++-- arch/arm/mach-at91/include/mach/board.h | 11 ++------- arch/arm/mach-at91/sama5d3_devices.c | 4 ++-- drivers/net/at91_ether.c | 2 +- drivers/net/macb.c | 4 ++-- include/platform_data/macb.h | 30 ++++++++++++++++++++++++ 26 files changed, 64 insertions(+), 41 deletions(-) create mode 100644 include/platform_data/macb.h diff --git a/arch/arm/boards/animeo_ip/init.c b/arch/arm/boards/animeo_ip/init.c index ada3bb044..07525b7ae 100644 --- a/arch/arm/boards/animeo_ip/init.c +++ b/arch/arm/boards/animeo_ip/init.c @@ -120,7 +120,7 @@ static void animeo_ip_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_addr = 0, }; diff --git a/arch/arm/boards/at91rm9200ek/init.c b/arch/arm/boards/at91rm9200ek/init.c index eec71bb07..30aaae274 100644 --- a/arch/arm/boards/at91rm9200ek/init.c +++ b/arch/arm/boards/at91rm9200ek/init.c @@ -32,7 +32,7 @@ #include #include -static struct at91_ether_platform_data ether_pdata = { +static struct macb_platform_data ether_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/at91sam9260ek/init.c b/arch/arm/boards/at91sam9260ek/init.c index dc2976a0c..4e4a69df1 100644 --- a/arch/arm/boards/at91sam9260ek/init.c +++ b/arch/arm/boards/at91sam9260ek/init.c @@ -114,7 +114,7 @@ static void ek_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/at91sam9263ek/init.c b/arch/arm/boards/at91sam9263ek/init.c index 90fdbeca7..a731d5864 100644 --- a/arch/arm/boards/at91sam9263ek/init.c +++ b/arch/arm/boards/at91sam9263ek/init.c @@ -82,7 +82,7 @@ static void ek_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/at91sam9m10g45ek/init.c b/arch/arm/boards/at91sam9m10g45ek/init.c index 0ae717135..f32215dee 100644 --- a/arch/arm/boards/at91sam9m10g45ek/init.c +++ b/arch/arm/boards/at91sam9m10g45ek/init.c @@ -105,7 +105,7 @@ static void ek_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/at91sam9m10ihd/init.c b/arch/arm/boards/at91sam9m10ihd/init.c index df63a9176..fe77b3a5b 100644 --- a/arch/arm/boards/at91sam9m10ihd/init.c +++ b/arch/arm/boards/at91sam9m10ihd/init.c @@ -79,7 +79,7 @@ static void ek_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/at91sam9x5ek/init.c b/arch/arm/boards/at91sam9x5ek/init.c index 4e1e06956..74cc7ab41 100644 --- a/arch/arm/boards/at91sam9x5ek/init.c +++ b/arch/arm/boards/at91sam9x5ek/init.c @@ -105,7 +105,7 @@ static void ek_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/dss11/init.c b/arch/arm/boards/dss11/init.c index 77ae46fcc..b33cd1220 100644 --- a/arch/arm/boards/dss11/init.c +++ b/arch/arm/boards/dss11/init.c @@ -73,7 +73,7 @@ static void dss11_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_addr = 0, .flags = AT91SAM_ETX2_ETX3_ALTERNATIVE, }; diff --git a/arch/arm/boards/mmccpu/init.c b/arch/arm/boards/mmccpu/init.c index 1e6bbab99..b7a94cca3 100644 --- a/arch/arm/boards/mmccpu/init.c +++ b/arch/arm/boards/mmccpu/init.c @@ -33,7 +33,7 @@ #include #include -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_flags = PHYLIB_FORCE_LINK, .phy_addr = 4, }; diff --git a/arch/arm/boards/pm9263/init.c b/arch/arm/boards/pm9263/init.c index 4afa09536..ff405bd2f 100644 --- a/arch/arm/boards/pm9263/init.c +++ b/arch/arm/boards/pm9263/init.c @@ -88,7 +88,7 @@ static void pm_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = -1, }; diff --git a/arch/arm/boards/pm9g45/init.c b/arch/arm/boards/pm9g45/init.c index 69c66d5aa..c3886bb0b 100644 --- a/arch/arm/boards/pm9g45/init.c +++ b/arch/arm/boards/pm9g45/init.c @@ -112,7 +112,7 @@ static void __init pm9g45_add_device_usbh(void) static void __init pm9g45_add_device_usbh(void) {} #endif -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/qil-a9260/init.c b/arch/arm/boards/qil-a9260/init.c index e96204aa7..56b51c245 100644 --- a/arch/arm/boards/qil-a9260/init.c +++ b/arch/arm/boards/qil-a9260/init.c @@ -79,7 +79,7 @@ static void qil_a9260_add_device_mci(void) {} #endif #ifdef CONFIG_CALAO_MB_QIL_A9260 -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = -1, }; diff --git a/arch/arm/boards/sama5d3xek/init.c b/arch/arm/boards/sama5d3xek/init.c index d17e4c2d2..743b907d7 100644 --- a/arch/arm/boards/sama5d3xek/init.c +++ b/arch/arm/boards/sama5d3xek/init.c @@ -110,12 +110,12 @@ static void ek_add_device_nand(void) {} #endif #if defined(CONFIG_DRIVER_NET_MACB) -static struct at91_ether_platform_data gmac_pdata = { +static struct macb_platform_data gmac_pdata = { .phy_interface = PHY_INTERFACE_MODE_RGMII, .phy_addr = 7, }; -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/telit-evk-pro3/init.c b/arch/arm/boards/telit-evk-pro3/init.c index d5f1b3ea2..9900dd1ed 100644 --- a/arch/arm/boards/telit-evk-pro3/init.c +++ b/arch/arm/boards/telit-evk-pro3/init.c @@ -62,7 +62,7 @@ static void evk_add_device_nand(void) at91_add_device_nand(&nand_pdata); } -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = 0, }; diff --git a/arch/arm/boards/tny-a926x/init.c b/arch/arm/boards/tny-a926x/init.c index 5ea6c538c..43c227b17 100644 --- a/arch/arm/boards/tny-a926x/init.c +++ b/arch/arm/boards/tny-a926x/init.c @@ -112,7 +112,7 @@ static void tny_a9260_add_device_nand(void) } #ifdef CONFIG_DRIVER_NET_MACB -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = -1, }; diff --git a/arch/arm/boards/usb-a926x/init.c b/arch/arm/boards/usb-a926x/init.c index 7ae902030..0c89d39ab 100644 --- a/arch/arm/boards/usb-a926x/init.c +++ b/arch/arm/boards/usb-a926x/init.c @@ -117,7 +117,7 @@ static void usb_a9260_add_device_nand(void) {} #endif #if defined(CONFIG_DRIVER_NET_MACB) -static struct at91_ether_platform_data macb_pdata = { +static struct macb_platform_data macb_pdata = { .phy_interface = PHY_INTERFACE_MODE_RMII, .phy_addr = -1, }; diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 82862d7c3..ee07848d3 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -86,7 +86,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_DRIVER_NET_AT91_ETHER) -void __init at91_add_device_eth(int id, struct at91_ether_platform_data *data) +void __init at91_add_device_eth(int id, struct macb_platform_data *data) { if (!data) return; @@ -118,7 +118,7 @@ void __init at91_add_device_eth(int id, struct at91_ether_platform_data *data) IORESOURCE_MEM, data); } #else -void __init at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} +void __init at91_add_device_eth(int id, struct macb_platform_data *data) {} #endif /* -------------------------------------------------------------------- diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 1c375eef9..cff0d901e 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -81,7 +81,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} #endif #if defined(CONFIG_DRIVER_NET_MACB) -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) +void at91_add_device_eth(int id, struct macb_platform_data *data) { if (!data) return; @@ -118,7 +118,7 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) IORESOURCE_MEM, data); } #else -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} +void at91_add_device_eth(int id, struct macb_platform_data *data) {} #endif #if defined(CONFIG_NAND_ATMEL) diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index f47a5febf..a93220d16 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -81,7 +81,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} #endif #if defined(CONFIG_DRIVER_NET_MACB) -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) +void at91_add_device_eth(int id, struct macb_platform_data *data) { if (!data) return; @@ -112,7 +112,7 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) IORESOURCE_MEM, data); } #else -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} +void at91_add_device_eth(int id, struct macb_platform_data *data) {} #endif #if defined(CONFIG_NAND_ATMEL) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index bde3429ed..68ed84179 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -82,7 +82,7 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {} #endif #if defined(CONFIG_DRIVER_NET_MACB) -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) +void at91_add_device_eth(int id, struct macb_platform_data *data) { if (!data) return; @@ -114,7 +114,7 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) IORESOURCE_MEM, data); } #else -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} +void at91_add_device_eth(int id, struct macb_platform_data *data) {} #endif #if defined(CONFIG_NAND_ATMEL) diff --git a/arch/arm/mach-at91/at91sam9x5_devices.c b/arch/arm/mach-at91/at91sam9x5_devices.c index 9f211e3bd..d12ee57c0 100644 --- a/arch/arm/mach-at91/at91sam9x5_devices.c +++ b/arch/arm/mach-at91/at91sam9x5_devices.c @@ -83,7 +83,7 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {} #endif #if defined(CONFIG_DRIVER_NET_MACB) -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) +void at91_add_device_eth(int id, struct macb_platform_data *data) { resource_size_t start; @@ -147,7 +147,7 @@ void at91_add_device_eth(int id, struct at91_ether_platform_data *data) IORESOURCE_MEM, data); } #else -void at91_add_device_eth(int id, struct at91_ether_platform_data *data) {} +void at91_add_device_eth(int id, struct macb_platform_data *data) {} #endif #if defined(CONFIG_MCI_ATMEL) diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 71267e11e..3ecc6038f 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -28,6 +28,7 @@ #include