diff options
47 files changed, 914 insertions, 50 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2167e29f6a..00be305c39 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -649,7 +649,7 @@ config TARGET_COLIBRI_VF bool "Support Colibri VF50/61" select CPU_V7 -config ZYNQ +config ARCH_ZYNQ bool "Xilinx Zynq Platform" select CPU_V7 select SUPPORT_SPL @@ -837,7 +837,7 @@ source "arch/arm/mach-uniphier/Kconfig" source "arch/arm/mach-versatile/Kconfig" -source "arch/arm/cpu/armv7/zynq/Kconfig" +source "arch/arm/mach-zynq/Kconfig" source "arch/arm/cpu/armv7/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index bd4749c55e..2a5620ddce 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -55,6 +55,7 @@ machine-$(CONFIG_ORION5X) += orion5x machine-$(CONFIG_TEGRA) += tegra machine-$(CONFIG_ARCH_UNIPHIER) += uniphier machine-$(CONFIG_ARCH_VERSATILE) += versatile +machine-$(CONFIG_ARCH_ZYNQ) += zynq machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y)) diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index e6249f13c8..fcccd0c9ba 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -56,4 +56,3 @@ obj-$(if $(filter stv0991,$(SOC)),y) += stv0991/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_U8500) += u8500/ obj-$(CONFIG_VF610) += vf610/ -obj-$(CONFIG_ZYNQ) += zynq/ diff --git a/arch/arm/cpu/armv7/zynq/config.mk b/arch/arm/cpu/armv7/zynq/config.mk deleted file mode 100644 index 778a377e8a..0000000000 --- a/arch/arm/cpu/armv7/zynq/config.mk +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (C) 2013 - 2015 Xilinx, Inc. All rights reserved. -# -# SPDX-License-Identifier: GPL-2.0 -# -# Allow NEON instructions (needed for lowlevel_init.S with GNU toolchain) -PLATFORM_RELFLAGS += -mfpu=neon diff --git a/arch/arm/cpu/armv8/zynqmp/Makefile b/arch/arm/cpu/armv8/zynqmp/Makefile index a997e045bd..efab5eabc9 100644 --- a/arch/arm/cpu/armv8/zynqmp/Makefile +++ b/arch/arm/cpu/armv8/zynqmp/Makefile @@ -7,3 +7,4 @@ obj-y += clk.o obj-y += cpu.o +obj-$(CONFIG_MP) += mp.o diff --git a/arch/arm/cpu/armv8/zynqmp/clk.c b/arch/arm/cpu/armv8/zynqmp/clk.c index 0af619d92f..9218586e94 100644 --- a/arch/arm/cpu/armv8/zynqmp/clk.c +++ b/arch/arm/cpu/armv8/zynqmp/clk.c @@ -6,6 +6,7 @@ */ #include <common.h> +#include <asm/arch/clk.h> #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> @@ -16,6 +17,8 @@ unsigned long get_uart_clk(int dev_id) u32 ver = zynqmp_get_silicon_version(); switch (ver) { + case ZYNQMP_CSU_VERSION_VELOCE: + return 48000; case ZYNQMP_CSU_VERSION_EP108: return 25000000; } diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c index 6fae03c1af..60d7d20e17 100644 --- a/arch/arm/cpu/armv8/zynqmp/cpu.c +++ b/arch/arm/cpu/armv8/zynqmp/cpu.c @@ -20,9 +20,175 @@ unsigned int zynqmp_get_silicon_version(void) gd->cpu_clk = get_tbclk(); switch (gd->cpu_clk) { + case 0 ... 1000000: + return ZYNQMP_CSU_VERSION_VELOCE; case 50000000: return ZYNQMP_CSU_VERSION_QEMU; } return ZYNQMP_CSU_VERSION_EP108; } + +#ifndef CONFIG_SYS_DCACHE_OFF +#include <asm/armv8/mmu.h> + +#define SECTION_SHIFT_L1 30UL +#define SECTION_SHIFT_L2 21UL +#define BLOCK_SIZE_L0 0x8000000000UL +#define BLOCK_SIZE_L1 (1 << SECTION_SHIFT_L1) +#define BLOCK_SIZE_L2 (1 << SECTION_SHIFT_L2) + +#define TCR_TG1_4K (1 << 31) +#define TCR_EPD1_DISABLE (1 << 23) +#define ZYNQMO_VA_BITS 40 +#define ZYNQMP_TCR TCR_TG1_4K | \ + TCR_EPD1_DISABLE | \ + TCR_SHARED_OUTER | \ + TCR_SHARED_INNER | \ + TCR_IRGN_WBWA | \ + TCR_ORGN_WBWA | \ + TCR_T0SZ(ZYNQMO_VA_BITS) + +#define MEMORY_ATTR PMD_SECT_AF | PMD_SECT_INNER_SHARE | \ + PMD_ATTRINDX(MT_NORMAL) | \ + PMD_TYPE_SECT +#define DEVICE_ATTR PMD_SECT_AF | PMD_SECT_PXN | \ + PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_NGNRNE) | \ + PMD_TYPE_SECT + +/* 4K size is required to place 512 entries in each level */ +#define TLB_TABLE_SIZE 0x1000 + +struct attr_tbl { + u32 num; + u64 attr; +}; + +static struct attr_tbl attr_tbll1t0[4] = { {16, 0x0}, + {8, DEVICE_ATTR}, + {32, MEMORY_ATTR}, + {456, DEVICE_ATTR} + }; +static struct attr_tbl attr_tbll2t3[4] = { {0x180, DEVICE_ATTR}, + {0x40, 0x0}, + {0x3F, DEVICE_ATTR}, + {0x1, MEMORY_ATTR} + }; + +/* + * This mmu table looks as below + * Level 0 table contains two entries to 512GB sizes. One is Level1 Table 0 + * and other Level1 Table1. + * Level1 Table0 contains entries for each 1GB from 0 to 511GB. + * Level1 Table1 contains entries for each 1GB from 512GB to 1TB. + * Level2 Table0, Level2 Table1, Level2 Table2 and Level2 Table3 contains + * entries for each 2MB starting from 0GB, 1GB, 2GB and 3GB respectively. + */ +static void zynqmp_mmu_setup(void) +{ + int el; + u32 index_attr; + u64 i, section_l1t0, section_l1t1; + u64 section_l2t0, section_l2t1, section_l2t2, section_l2t3; + u64 *level0_table = (u64 *)gd->arch.tlb_addr; + u64 *level1_table_0 = (u64 *)(gd->arch.tlb_addr + TLB_TABLE_SIZE); + u64 *level1_table_1 = (u64 *)(gd->arch.tlb_addr + (2 * TLB_TABLE_SIZE)); + u64 *level2_table_0 = (u64 *)(gd->arch.tlb_addr + (3 * TLB_TABLE_SIZE)); + u64 *level2_table_1 = (u64 *)(gd->arch.tlb_addr + (4 * TLB_TABLE_SIZE)); + u64 *level2_table_2 = (u64 *)(gd->arch.tlb_addr + (5 * TLB_TABLE_SIZE)); + u64 *level2_table_3 = (u64 *)(gd->arch.tlb_addr + (6 * TLB_TABLE_SIZE)); + + level0_table[0] = + (u64)level1_table_0 | PMD_TYPE_TABLE; + level0_table[1] = + (u64)level1_table_1 | PMD_TYPE_TABLE; + + /* + * set level 1 table 0, covering 0 to 512GB + * set level 1 table 1, covering 512GB to 1TB + */ + section_l1t0 = 0; + section_l1t1 = BLOCK_SIZE_L0; + + index_attr = 0; + for (i = 0; i < 512; i++) { + level1_table_0[i] = section_l1t0; + level1_table_0[i] |= attr_tbll1t0[index_attr].attr; + attr_tbll1t0[index_attr].num--; + if (attr_tbll1t0[index_attr].num == 0) + index_attr++; + level1_table_1[i] = section_l1t1; + level1_table_1[i] |= DEVICE_ATTR; + section_l1t0 += BLOCK_SIZE_L1; + section_l1t1 += BLOCK_SIZE_L1; + } + + level1_table_0[0] = + (u64)level2_table_0 | PMD_TYPE_TABLE; + level1_table_0[1] = + (u64)level2_table_1 | PMD_TYPE_TABLE; + level1_table_0[2] = + (u64)level2_table_2 | PMD_TYPE_TABLE; + level1_table_0[3] = + (u64)level2_table_3 | PMD_TYPE_TABLE; + + section_l2t0 = 0; + section_l2t1 = section_l2t0 + BLOCK_SIZE_L1; /* 1GB */ + section_l2t2 = section_l2t1 + BLOCK_SIZE_L1; /* 2GB */ + section_l2t3 = section_l2t2 + BLOCK_SIZE_L1; /* 3GB */ + + index_attr = 0; + + for (i = 0; i < 512; i++) { + level2_table_0[i] = section_l2t0 | MEMORY_ATTR; + level2_table_1[i] = section_l2t1 | MEMORY_ATTR; + level2_table_2[i] = section_l2t2 | DEVICE_ATTR; + level2_table_3[i] = section_l2t3 | + attr_tbll2t3[index_attr].attr; + attr_tbll2t3[index_attr].num--; + if (attr_tbll2t3[index_attr].num == 0) + index_attr++; + section_l2t0 += BLOCK_SIZE_L2; + section_l2t1 += BLOCK_SIZE_L2; + section_l2t2 += BLOCK_SIZE_L2; + section_l2t3 += BLOCK_SIZE_L2; + } + + /* flush new MMU table */ + flush_dcache_range(gd->arch.tlb_addr, + gd->arch.tlb_addr + gd->arch.tlb_size); + + /* point TTBR to the new table */ + el = current_el(); + set_ttbr_tcr_mair(el, gd->arch.tlb_addr, + ZYNQMP_TCR, MEMORY_ATTRIBUTES); + + set_sctlr(get_sctlr() | CR_M); +} + +int arch_cpu_init(void) +{ + icache_enable(); + __asm_invalidate_dcache_all(); + __asm_invalidate_tlb_all(); + return 0; +} + +/* + * This function is called from lib/board.c. + * It recreates MMU table in main memory. MMU and d-cache are enabled earlier. + * There is no need to disable d-cache for this operation. + */ +void enable_caches(void) +{ + /* The data cache is not active unless the mmu is enabled */ + if (!(get_sctlr() & CR_M)) { + invalidate_dcache_all(); + __asm_invalidate_tlb_all(); + zynqmp_mmu_setup(); + } + puts("Enabling Caches...\n"); + + set_sctlr(get_sctlr() | CR_C); +} +#endif diff --git a/arch/arm/cpu/armv8/zynqmp/mp.c b/arch/arm/cpu/armv8/zynqmp/mp.c new file mode 100644 index 0000000000..17e32a7b7c --- /dev/null +++ b/arch/arm/cpu/armv8/zynqmp/mp.c @@ -0,0 +1,242 @@ +/* + * (C) Copyright 2014 - 2015 Xilinx, Inc. + * Michal Simek <michal.simek@xilinx.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> + +#define LOCK 0 +#define SPLIT 1 + +#define HALT 0 +#define RELEASE 1 + +#define ZYNQMP_BOOTADDR_HIGH_MASK 0xFFFFFFFF +#define ZYNQMP_R5_HIVEC_ADDR 0xFFFF0000 +#define ZYNQMP_R5_LOVEC_ADDR 0x0 +#define ZYNQMP_RPU_CFG_CPU_HALT_MASK 0x01 +#define ZYNQMP_RPU_CFG_HIVEC_MASK 0x04 +#define ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK 0x08 +#define ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK 0x40 +#define ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK 0x10 + +#define ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK 0x04 +#define ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK 0x01 +#define ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK 0x02 +#define ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK 0x1000000 + +#define ZYNQMP_TCM_START_ADDRESS 0xFFE00000 +#define ZYNQMP_TCM_BOTH_SIZE 0x40000 + +#define ZYNQMP_CORE_APU0 0 +#define ZYNQMP_CORE_APU3 3 + +#define ZYNQMP_MAX_CORES 6 + +int is_core_valid(unsigned int core) +{ + if (core < ZYNQMP_MAX_CORES) + return 1; + + return 0; +} + +int cpu_reset(int nr) +{ + puts("Feature is not implemented.\n"); + return 0; +} + +static void set_r5_halt_mode(u8 halt, u8 mode) +{ + u32 tmp; + + tmp = readl(&rpu_base->rpu0_cfg); + if (halt == HALT) + tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK; + else + tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK; + writel(tmp, &rpu_base->rpu0_cfg); + + if (mode == LOCK) { + tmp = readl(&rpu_base->rpu1_cfg); + if (halt == HALT) + tmp &= ~ZYNQMP_RPU_CFG_CPU_HALT_MASK; + else + tmp |= ZYNQMP_RPU_CFG_CPU_HALT_MASK; + writel(tmp, &rpu_base->rpu1_cfg); + } +} + +static void set_r5_tcm_mode(u8 mode) +{ + u32 tmp; + + tmp = readl(&rpu_base->rpu_glbl_ctrl); + if (mode == LOCK) { + tmp &= ~ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK; + tmp |= ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK | + ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK; + } else { + tmp |= ZYNQMP_RPU_GLBL_CTRL_SPLIT_LOCK_MASK; + tmp &= ~(ZYNQMP_RPU_GLBL_CTRL_TCM_COMB_MASK | + ZYNQMP_RPU_GLBL_CTRL_SLCLAMP_MASK); + } + + writel(tmp, &rpu_base->rpu_glbl_ctrl); +} + +static void set_r5_reset(u8 mode) +{ + u32 tmp; + + tmp = readl(&crlapb_base->rst_lpd_top); + tmp |= (ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK | + ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK); + + if (mode == LOCK) + tmp |= ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK; + + writel(tmp, &crlapb_base->rst_lpd_top); +} + +static void release_r5_reset(u8 mode) +{ + u32 tmp; + + tmp = readl(&crlapb_base->rst_lpd_top); + tmp &= ~(ZYNQMP_CRLAPB_RST_LPD_AMBA_RST_MASK | + ZYNQMP_CRLAPB_RST_LPD_R50_RST_MASK); + + if (mode == LOCK) + tmp &= ~ZYNQMP_CRLAPB_RST_LPD_R51_RST_MASK; + + writel(tmp, &crlapb_base->rst_lpd_top); +} + +static void enable_clock_r5(void) +{ + u32 tmp; + + tmp = readl(&crlapb_base->cpu_r5_ctrl); + tmp |= ZYNQMP_CRLAPB_CPU_R5_CTRL_CLKACT_MASK; + writel(tmp, &crlapb_base->cpu_r5_ctrl); + + /* Give some delay for clock + * to propogate */ + udelay(0x500); +} + +int cpu_disable(int nr) +{ + if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) { + u32 val = readl(&crfapb_base->rst_fpd_apu); + val |= 1 << nr; + writel(val, &crfapb_base->rst_fpd_apu); + } else { + set_r5_reset(LOCK); + } + + return 0; +} + +int cpu_status(int nr) +{ + if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) { + u32 addr_low = readl(((u8 *)&apu_base->rvbar_addr0_l) + nr * 8); + u32 addr_high = readl(((u8 *)&apu_base->rvbar_addr0_h) + + nr * 8); + u32 val = readl(&crfapb_base->rst_fpd_apu); + val &= 1 << nr; + printf("APU CPU%d %s - starting address HI: %x, LOW: %x\n", + nr, val ? "OFF" : "ON" , addr_high, addr_low); + } else { + u32 val = readl(&crlapb_base->rst_lpd_top); + val &= 1 << (nr - 4); + printf("RPU CPU%d %s\n", nr - 4, val ? "OFF" : "ON"); + } + + return 0; +} + +static void set_r5_start(u8 high) +{ + u32 tmp; + + tmp = readl(&rpu_base->rpu0_cfg); + if (high) + tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK; + else + tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK; + writel(tmp, &rpu_base->rpu0_cfg); + + tmp = readl(&rpu_base->rpu1_cfg); + if (high) + tmp |= ZYNQMP_RPU_CFG_HIVEC_MASK; + else + tmp &= ~ZYNQMP_RPU_CFG_HIVEC_MASK; + writel(tmp, &rpu_base->rpu1_cfg); +} + +int cpu_release(int nr, int argc, char * const argv[]) +{ + if (nr >= ZYNQMP_CORE_APU0 && nr <= ZYNQMP_CORE_APU3) { + u64 boot_addr = simple_strtoull(argv[0], NULL, 16); + /* HIGH */ + writel((u32)(boot_addr >> 32), + ((u8 *)&apu_base->rvbar_addr0_h) + nr * 8); + /* LOW */ + writel((u32)(boot_addr & ZYNQMP_BOOTADDR_HIGH_MASK), + ((u8 *)&apu_base->rvbar_addr0_l) + nr * 8); + + u32 val = readl(&crfapb_base->rst_fpd_apu); + val &= ~(1 << nr); + writel(val, &crfapb_base->rst_fpd_apu); + } else { + if (argc != 2) { + printf("Invalid number of arguments to release.\n"); + printf("<addr> <mode>-Start addr lockstep or split\n"); + return 1; + } + + u32 boot_addr = simple_strtoul(argv[0], NULL, 16); + if (!(boot_addr == ZYNQMP_R5_LOVEC_ADDR || + boot_addr == ZYNQMP_R5_HIVEC_ADDR)) { + printf("Invalid starting address 0x%x\n", boot_addr); + printf("0 or 0xffff0000 are permitted\n"); + return 1; + } + + if (!strncmp(argv[1], "lockstep", 8)) { + printf("R5 lockstep mode\n"); + set_r5_tcm_mode(LOCK); + set_r5_halt_mode(HALT, LOCK); + + if (boot_addr == 0) + set_r5_start(0); + else + set_r5_start(1); + + enable_clock_r5(); + release_r5_reset(LOCK); + set_r5_halt_mode(RELEASE, LOCK); + } else if (!strncmp(argv[1], "split", 5)) { + printf("R5 split mode\n"); + set_r5_tcm_mode(SPLIT); + set_r5_halt_mode(HALT, SPLIT); + enable_clock_r5(); + release_r5_reset(SPLIT); + set_r5_halt_mode(RELEASE, SPLIT); + } else { + printf("Unsupported mode\n"); + return 1; + } + } + + return 0; +} diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 09708d9a41..46a6171966 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -39,11 +39,12 @@ dtb-$(CONFIG_ARCH_UNIPHIER) += \ uniphier-ph1-pro4-ref.dtb \ uniphier-ph1-ld4-ref.dtb \ uniphier-ph1-sld8-ref.dtb -dtb-$(CONFIG_ZYNQ) += zynq-zc702.dtb \ +dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb \ zynq-zc706.dtb \ zynq-zed.dtb \ zynq-zybo.dtb \ zynq-microzed.dtb \ + zynq-picozed.dtb \ zynq-zc770-xm010.dtb \ zynq-zc770-xm012.dtb \ zynq-zc770-xm013.dtb diff --git a/arch/arm/dts/zynq-picozed.dts b/arch/arm/dts/zynq-picozed.dts new file mode 100644 index 0000000000..686b98fe7e --- /dev/null +++ b/arch/arm/dts/zynq-picozed.dts @@ -0,0 +1,23 @@ +/* + * Avnet PicoZed board DTS + * + * Copyright (C) 2015 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +/dts-v1/; +#include "zynq-7000.dtsi" + +/ { + model = "Zynq PicoZed Board"; + compatible = "xlnx,zynq-picozed", "xlnx,zynq-7000"; + + aliases { + serial0 = &uart1; + }; + + memory { + device_type = "memory"; + reg = <0 0x40000000>; + }; +}; diff --git a/arch/arm/include/asm/arch-zynq/gpio.h b/arch/arm/include/asm/arch-zynq/gpio.h deleted file mode 100644 index a26ae87293..0000000000 --- a/arch/arm/include/asm/arch-zynq/gpio.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2013 Xilinx, Inc. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _ZYNQ_GPIO_H -#define _ZYNQ_GPIO_H - -#endif /* _ZYNQ_GPIO_H */ diff --git a/arch/arm/include/asm/arch-zynqmp/gpio.h b/arch/arm/include/asm/arch-zynqmp/gpio.h new file mode 100644 index 0000000000..098bbde06f --- /dev/null +++ b/arch/arm/include/asm/arch-zynqmp/gpio.h @@ -0,0 +1,12 @@ +/* + * Copyright 2015 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ARCH_ZYNQMP_GPIO_H +#define __ARCH_ZYNQMP_GPIO_H + +/* Empty file - sdhci requires this. */ + +#endif diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h index 97fb49a2a7..c9dc49d783 100644 --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@ -11,6 +11,12 @@ #define ZYNQ_SERIAL_BASEADDR0 0xFF000000 #define ZYNQ_SERIAL_BASEADDR1 0xFF001000 +#define ZYNQ_SPI_BASEADDR0 0xFF040000 +#define ZYNQ_SPI_BASEADDR1 0xFF050000 + +#define ZYNQ_I2C_BASEADDR0 0xFF020000 +#define ZYNQ_I2C_BASEADDR1 0xFF030000 + #define ZYNQ_SDHCI_BASEADDR0 0xFF160000 #define ZYNQ_SDHCI_BASEADDR1 0xFF170000 @@ -18,11 +24,15 @@ #define ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT 0x1000000 struct crlapb_regs { - u32 reserved0[74]; + u32 reserved0[36]; + u32 cpu_r5_ctrl; /* 0x90 */ + u32 reserved1[37]; u32 timestamp_ref_ctrl; /* 0x128 */ - u32 reserved0_1[53]; + u32 reserved2[53]; u32 boot_mode; /* 0x200 */ - u32 reserved1[26]; + u32 reserved3[14]; + u32 rst_lpd_top; /* 0x23C */ + u32 reserved4[26]; }; #define crlapb_base ((struct crlapb_regs *)ZYNQMP_CRL_APB_BASEADDR) @@ -41,12 +51,47 @@ struct iou_scntr { /* Bootmode setting values */ #define BOOT_MODES_MASK 0x0000000F -#define SD_MODE 0x00000005 +#define SD_MODE 0x00000003 +#define EMMC_MODE 0x00000006 #define JTAG_MODE 0x00000000 +#define ZYNQMP_RPU_BASEADDR 0xFF9A0000 + +struct rpu_regs { + u32 rpu_glbl_ctrl; + u32 reserved0[63]; + u32 rpu0_cfg; /* 0x100 */ + u32 reserved1[63]; + u32 rpu1_cfg; /* 0x200 */ +}; + +#define rpu_base ((struct rpu_regs *)ZYNQMP_RPU_BASEADDR) + +#define ZYNQMP_CRF_APB_BASEADDR 0xFD1A0000 + +struct crfapb_regs { + u32 reserved0[65]; + u32 rst_fpd_apu; /* 0x104 */ + u32 reserved1; +}; + +#define crfapb_base ((struct crfapb_regs *)ZYNQMP_CRF_APB_BASEADDR) + +#define ZYNQMP_APU_BASEADDR 0xFD5C0000 + +struct apu_regs { + u32 reserved0[16]; + u32 rvbar_addr0_l; /* 0x40 */ + u32 rvbar_addr0_h; /* 0x44 */ + u32 reserved1[20]; +}; + +#define apu_base ((struct apu_regs *)ZYNQMP_APU_BASEADDR) + /* Board version value */ #define ZYNQMP_CSU_VERSION_SILICON 0x0 #define ZYNQMP_CSU_VERSION_EP108 0x1 +#define ZYNQMP_CSU_VERSION_VELOCE 0x2 #define ZYNQMP_CSU_VERSION_QEMU 0x3 #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/cpu/armv7/zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 3a52535ce0..1046ece784 100644 --- a/arch/arm/cpu/armv7/zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -1,4 +1,4 @@ -if ZYNQ +if ARCH_ZYNQ choice prompt "Xilinx Zynq board select" @@ -9,6 +9,9 @@ config TARGET_ZYNQ_ZED config TARGET_ZYNQ_MICROZED bool "Zynq MicroZed" +config TARGET_ZYNQ_PICOZED + bool "Zynq PicoZed" + config TARGET_ZYNQ_ZC70X bool "Zynq ZC702/ZC706 Board" @@ -32,6 +35,7 @@ config SYS_SOC config SYS_CONFIG_NAME default "zynq_zed" if TARGET_ZYNQ_ZED default "zynq_microzed" if TARGET_ZYNQ_MICROZED + default "zynq_picozed" if TARGET_ZYNQ_PICOZED default "zynq_zc70x" if TARGET_ZYNQ_ZC70X default "zynq_zc770" if TARGET_ZYNQ_ZC770 default "zynq_zybo" if TARGET_ZYNQ_ZYBO diff --git a/arch/arm/cpu/armv7/zynq/Makefile b/arch/arm/mach-zynq/Makefile index 901f2ce4cb..bf29b4d396 100644 --- a/arch/arm/cpu/armv7/zynq/Makefile +++ b/arch/arm/mach-zynq/Makefile @@ -14,4 +14,5 @@ obj-y += ddrc.o obj-y += slcr.o obj-y += clk.o obj-y += lowlevel_init.o +AFLAGS_lowlevel_init.o := -mfpu=neon obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/arm/cpu/armv7/zynq/clk.c b/arch/arm/mach-zynq/clk.c index d2885dc2b9..d2885dc2b9 100644 --- a/arch/arm/cpu/armv7/zynq/clk.c +++ b/arch/arm/mach-zynq/clk.c diff --git a/arch/arm/cpu/armv7/zynq/cpu.c b/arch/arm/mach-zynq/cpu.c index 914b1feb68..914b1feb68 100644 --- a/arch/arm/cpu/armv7/zynq/cpu.c +++ b/arch/arm/mach-zynq/cpu.c diff --git a/arch/arm/cpu/armv7/zynq/ddrc.c b/arch/arm/mach-zynq/ddrc.c index 5b20accbcb..5b20accbcb 100644 --- a/arch/arm/cpu/armv7/zynq/ddrc.c +++ b/arch/arm/mach-zynq/ddrc.c diff --git a/arch/arm/include/asm/arch-zynq/clk.h b/arch/arm/mach-zynq/include/mach/clk.h index 250c5bc07b..250c5bc07b 100644 --- a/arch/arm/include/asm/arch-zynq/clk.h +++ b/arch/arm/mach-zynq/include/mach/clk.h diff --git a/arch/arm/mach-zynq/include/mach/gpio.h b/arch/arm/mach-zynq/include/mach/gpio.h new file mode 100644 index 0000000000..9e1e7da203 --- /dev/null +++ b/arch/arm/mach-zynq/include/mach/gpio.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013 Xilinx, Inc. + * Copyright (c) 2015 DAVE Embedded Systems + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _ZYNQ_GPIO_H +#define _ZYNQ_GPIO_H + +#define ZYNQ_GPIO_BASE_ADDRESS 0xE000A000 + +/* Maximum banks */ +#define ZYNQ_GPIO_MAX_BANK 4 + +#define ZYNQ_GPIO_BANK0_NGPIO 32 +#define ZYNQ_GPIO_BANK1_NGPIO 22 +#define ZYNQ_GPIO_BANK2_NGPIO 32 +#define ZYNQ_GPIO_BANK3_NGPIO 32 + +#define ZYNQ_GPIO_NR_GPIOS (ZYNQ_GPIO_BANK0_NGPIO + \ + ZYNQ_GPIO_BANK1_NGPIO + \ + ZYNQ_GPIO_BANK2_NGPIO + \ + ZYNQ_GPIO_BANK3_NGPIO) + +#define ZYNQ_GPIO_BANK0_PIN_MIN 0 +#define ZYNQ_GPIO_BANK0_PIN_MAX (ZYNQ_GPIO_BANK0_PIN_MIN + \ + ZYNQ_GPIO_BANK0_NGPIO - 1) +#define ZYNQ_GPIO_BANK1_PIN_MIN (ZYNQ_GPIO_BANK0_PIN_MAX + 1) +#define ZYNQ_GPIO_BANK1_PIN_MAX (ZYNQ_GPIO_BANK1_PIN_MIN + \ + ZYNQ_GPIO_BANK1_NGPIO - 1) +#define ZYNQ_GPIO_BANK2_PIN_MIN (ZYNQ_GPIO_BANK1_PIN_MAX + 1) +#define ZYNQ_GPIO_BANK2_PIN_MAX (ZYNQ_GPIO_BANK2_PIN_MIN + \ + ZYNQ_GPIO_BANK2_NGPIO - 1) +#define ZYNQ_GPIO_BANK3_PIN_MIN (ZYNQ_GPIO_BANK2_PIN_MAX + 1) +#define ZYNQ_GPIO_BANK3_PIN_MAX (ZYNQ_GPIO_BANK3_PIN_MIN + \ + ZYNQ_GPIO_BANK3_NGPIO - 1) + +/* Register offsets for the GPIO device */ +/* LSW Mask & Data -WO */ +#define ZYNQ_GPIO_DATA_LSW_OFFSET(BANK) (0x000 + (8 * BANK)) +/* MSW Mask & Data -WO */ +#define ZYNQ_GPIO_DATA_MSW_OFFSET(BANK) (0x004 + (8 * BANK)) +/* Data Register-RW */ +#define ZYNQ_GPIO_DATA_RO_OFFSET(BANK) (0x060 + (4 * BANK)) +/* Direction mode reg-RW */ +#define ZYNQ_GPIO_DIRM_OFFSET(BANK) (0x204 + (0x40 * BANK)) +/* Output enable reg-RW */ +#define ZYNQ_GPIO_OUTEN_OFFSET(BANK) (0x208 + (0x40 * BANK)) +/* Interrupt mask reg-RO */ +#define ZYNQ_GPIO_INTMASK_OFFSET(BANK) (0x20C + (0x40 * BANK)) +/* Interrupt enable reg-WO */ +#define ZYNQ_GPIO_INTEN_OFFSET(BANK) (0x210 + (0x40 * BANK)) +/* Interrupt disable reg-WO */ +#define ZYNQ_GPIO_INTDIS_OFFSET(BANK) (0x214 + (0x40 * BANK)) +/* Interrupt status reg-RO */ +#define ZYNQ_GPIO_INTSTS_OFFSET(BANK) (0x218 + (0x40 * BANK)) +/* Interrupt type reg-RW */ +#define ZYNQ_GPIO_INTTYPE_OFFSET(BANK) (0x21C + (0x40 * BANK)) +/* Interrupt polarity reg-RW */ +#define ZYNQ_GPIO_INTPOL_OFFSET(BANK) (0x220 + (0x40 * BANK)) +/* Interrupt on any, reg-RW */ +#define ZYNQ_GPIO_INTANY_OFFSET(BANK) (0x224 + (0x40 * BANK)) + +/* Disable all interrupts mask */ +#define ZYNQ_GPIO_IXR_DISABLE_ALL 0xFFFFFFFF + +/* Mid pin number of a bank */ +#define ZYNQ_GPIO_MID_PIN_NUM 16 + +/* GPIO upper 16 bit mask */ +#define ZYNQ_GPIO_UPPER_MASK 0xFFFF0000 + +#define BIT(x) (1<<x) + +#endif /* _ZYNQ_GPIO_H */ diff --git a/arch/arm/include/asm/arch-zynq/hardware.h b/arch/arm/mach-zynq/include/mach/hardware.h index e2e0b7321a..e2e0b7321a 100644 --- a/arch/arm/include/asm/arch-zynq/hardware.h +++ b/arch/arm/mach-zynq/include/mach/hardware.h diff --git a/arch/arm/include/asm/arch-zynq/sys_proto.h b/arch/arm/mach-zynq/include/mach/sys_proto.h index 9d50e2478f..9d50e2478f 100644 --- a/arch/arm/include/asm/arch-zynq/sys_proto.h +++ b/arch/arm/mach-zynq/include/mach/sys_proto.h diff --git a/arch/arm/cpu/armv7/zynq/lowlevel_init.S b/arch/arm/mach-zynq/lowlevel_init.S index 6d714b711c..6d714b711c 100644 --- a/arch/arm/cpu/armv7/zynq/lowlevel_init.S +++ b/arch/arm/mach-zynq/lowlevel_init.S diff --git a/arch/arm/cpu/armv7/zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 2521589c07..05f4099aae 100644 --- a/arch/arm/cpu/armv7/zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -129,11 +129,18 @@ out: void zynq_slcr_devcfg_disable(void) { + u32 reg_val; + zynq_slcr_unlock(); /* Disable AXI interface by asserting FPGA resets */ writel(0xF, &slcr_base->fpga_rst_ctrl); + /* Disable Level shifters before setting PS-PL */ + reg_val = readl(&slcr_base->lvl_shftr_en); + reg_val &= ~0xF; + writel(reg_val, &slcr_base->lvl_shftr_en); + /* Set Level Shifters DT618760 */ writel(0xA, &slcr_base->lvl_shftr_en); diff --git a/arch/arm/cpu/armv7/zynq/spl.c b/arch/arm/mach-zynq/spl.c index b80c35794a..13025f034b 100644 --- a/arch/arm/cpu/armv7/zynq/spl.c +++ b/arch/arm/mach-zynq/spl.c @@ -85,6 +85,6 @@ __weak void ps7_init(void) { /* * This function is overridden by the one in - * board/xilinx/zynq/ps7_init.c, if it exists. + * board/xilinx/zynq/ps7_init_gpl.c, if it exists. */ } diff --git a/arch/arm/cpu/armv7/zynq/timer.c b/arch/arm/mach-zynq/timer.c index 303dbcfcea..5ed9642df9 100644 --- a/arch/arm/cpu/armv7/zynq/timer.c +++ b/arch/arm/mach-zynq/timer.c @@ -93,7 +93,9 @@ ulong get_timer_masked(void) gd->arch.tbl += gd->arch.lastinc - now; } else { /* We have an overflow ... */ - gd->arch.tbl += gd->arch.lastinc + TIMER_LOAD_VAL - now + 1; + gd->arch.tbl += gd->arch.lastinc + (TIMER_LOAD_VAL / + (gd->arch.timer_rate_hz / CONFIG_SYS_HZ)) - + now + 1; } gd->arch.lastinc = now; diff --git a/arch/arm/cpu/armv7/zynq/u-boot-spl.lds b/arch/arm/mach-zynq/u-boot-spl.lds index 0f2f756f83..0f2f756f83 100644 --- a/arch/arm/cpu/armv7/zynq/u-boot-spl.lds +++ b/arch/arm/mach-zynq/u-boot-spl.lds diff --git a/arch/arm/cpu/armv7/zynq/u-boot.lds b/arch/arm/mach-zynq/u-boot.lds index 4dc9bb0102..4dc9bb0102 100644 --- a/arch/arm/cpu/armv7/zynq/u-boot.lds +++ b/arch/arm/mach-zynq/u-boot.lds diff --git a/board/xilinx/zynq/.gitignore b/board/xilinx/zynq/.gitignore index 7c36bc963f..c455361df6 100644 --- a/board/xilinx/zynq/.gitignore +++ b/board/xilinx/zynq/.gitignore @@ -1,2 +1 @@ -ps7_init.[ch] ps7_init_gpl.[ch] diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile index 3b1eb4f74a..054c3d821d 100644 --- a/board/xilinx/zynq/Makefile +++ b/board/xilinx/zynq/Makefile @@ -9,9 +9,7 @@ obj-y := board.o # Please copy ps7_init_gpl.c/h from hw project to this directory obj-$(CONFIG_SPL_BUILD) += \ - $(if $(wildcard $(srctree)/$(src)/ps7_init_gpl.c), ps7_init_gpl.o, \ - $(if $(wildcard $(srctree)/$(src)/ps7_init.c), ps7_init.o legacy.o)) + $(if $(wildcard $(srctree)/$(src)/ps7_init_gpl.c), ps7_init_gpl.o) # Suppress "warning: function declaration isn't a prototype" CFLAGS_REMOVE_ps7_init_gpl.o := -Wstrict-prototypes -CFLAGS_REMOVE_ps7_init.o := -Wstrict-prototypes diff --git a/board/xilinx/zynq/legacy.c b/board/xilinx/zynq/legacy.c deleted file mode 100644 index 4ae913eefe..0000000000 --- a/board/xilinx/zynq/legacy.c +++ /dev/null @@ -1,2 +0,0 @@ - -#warning usage of ps7_init files is deprecated please use ps7_init_gpl diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 1325bca5e5..f5ff64d988 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -56,14 +56,18 @@ int board_mmc_init(bd_t *bd) { int ret = 0; + u32 ver = zynqmp_get_silicon_version(); + + if (ver != ZYNQMP_CSU_VERSION_VELOCE) { #if defined(CONFIG_ZYNQ_SDHCI) # if defined(CONFIG_ZYNQ_SDHCI0) - ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0); + ret = zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR0); # endif # if defined(CONFIG_ZYNQ_SDHCI1) - ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1); + ret |= zynq_sdhci_init(ZYNQ_SDHCI_BASEADDR1); # endif #endif + } return ret; } @@ -79,6 +83,7 @@ int board_late_init(void) switch (bootmode) { case SD_MODE: + case EMMC_MODE: setenv("modeboot", "sdboot"); break; default: diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig index 95cfe8938d..40d675fd4a 100644 --- a/configs/zynq_microzed_defconfig +++ b/configs/zynq_microzed_defconfig @@ -1,6 +1,6 @@ CONFIG_SPL=y CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_MICROZED=y CONFIG_OF_CONTROL=y # CONFIG_SYS_MALLOC_F is not set diff --git a/configs/zynq_picozed_defconfig b/configs/zynq_picozed_defconfig new file mode 100644 index 0000000000..61852cbaad --- /dev/null +++ b/configs/zynq_picozed_defconfig @@ -0,0 +1,6 @@ +CONFIG_SPL=y +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y +CONFIG_TARGET_ZYNQ_PICOZED=y +CONFIG_OF_CONTROL=n +CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed" diff --git a/configs/zynq_zc70x_defconfig b/configs/zynq_zc70x_defconfig index 81fb4af4f9..7c3cb2de9e 100644 --- a/configs/zynq_zc70x_defconfig +++ b/configs/zynq_zc70x_defconfig @@ -1,6 +1,6 @@ CONFIG_SPL=y CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_ZC70X=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702" diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig index fc39cca1b8..36b95fa321 100644 --- a/configs/zynq_zc770_xm010_defconfig +++ b/configs/zynq_zc770_xm010_defconfig @@ -1,7 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010" CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_ZC770=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010" diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig index 21e52fbf1f..6c5eecc164 100644 --- a/configs/zynq_zc770_xm012_defconfig +++ b/configs/zynq_zc770_xm012_defconfig @@ -1,7 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012" CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_ZC770=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012" diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig index 2c38012643..eabc10663e 100644 --- a/configs/zynq_zc770_xm013_defconfig +++ b/configs/zynq_zc770_xm013_defconfig @@ -1,7 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013" CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_ZC770=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013" diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig index d4dc5bb83b..b2b4b99fad 100644 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@ -1,6 +1,6 @@ CONFIG_SPL=y CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_ZED=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zed" diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig index 7d06073cad..da55320adf 100644 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@ -1,6 +1,6 @@ CONFIG_SPL=y CONFIG_ARM=y -CONFIG_ZYNQ=y +CONFIG_ARCH_ZYNQ=y CONFIG_TARGET_ZYNQ_ZYBO=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 8ca8b05ebf..fb40e09020 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -43,3 +43,4 @@ oby-$(CONFIG_SX151X) += sx151x.o obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o +obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o diff --git a/drivers/gpio/zynq_gpio.c b/drivers/gpio/zynq_gpio.c new file mode 100644 index 0000000000..83a2c465d0 --- /dev/null +++ b/drivers/gpio/zynq_gpio.c @@ -0,0 +1,220 @@ +/* + * Xilinx Zynq GPIO device driver + * + * Copyright (C) 2015 DAVE Embedded Systems <devel@dave.eu> + * + * Most of code taken from linux kernel driver (linux/drivers/gpio/gpio-zynq.c) + * Copyright (C) 2009 - 2014 Xilinx, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <asm/errno.h> + +/** + * zynq_gpio_get_bank_pin - Get the bank number and pin number within that bank + * for a given pin in the GPIO device + * @pin_num: gpio pin number within the device + * @bank_num: an output parameter used to return the bank number of the gpio + * pin + * @bank_pin_num: an output parameter used to return pin number within a bank + * for the given gpio pin + * + * Returns the bank number and pin offset within the bank. + */ +static inline void zynq_gpio_get_bank_pin(unsigned int pin_num, + unsigned int *bank_num, + unsigned int *bank_pin_num) +{ + switch (pin_num) { + case ZYNQ_GPIO_BANK0_PIN_MIN ... ZYNQ_GPIO_BANK0_PIN_MAX: + *bank_num = 0; + *bank_pin_num = pin_num; + break; + case ZYNQ_GPIO_BANK1_PIN_MIN ... ZYNQ_GPIO_BANK1_PIN_MAX: + *bank_num = 1; + *bank_pin_num = pin_num - ZYNQ_GPIO_BANK1_PIN_MIN; + break; + case ZYNQ_GPIO_BANK2_PIN_MIN ... ZYNQ_GPIO_BANK2_PIN_MAX: + *bank_num = 2; + *bank_pin_num = pin_num - ZYNQ_GPIO_BANK2_PIN_MIN; + break; + case ZYNQ_GPIO_BANK3_PIN_MIN ... ZYNQ_GPIO_BANK3_PIN_MAX: + *bank_num = 3; + *bank_pin_num = pin_num - ZYNQ_GPIO_BANK3_PIN_MIN; + break; + default: + printf("invalid GPIO pin number: %u\n", pin_num); + *bank_num = 0; + *bank_pin_num = 0; + break; + } +} + +int gpio_is_valid(unsigned gpio) +{ + return (gpio >= 0) && (gpio < ZYNQ_GPIO_NR_GPIOS); +} + +static int check_gpio(unsigned gpio) +{ + if (!gpio_is_valid(gpio)) { + printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); + return -1; + } + return 0; +} + +/** + * gpio_get_value - Get the state of the specified pin of GPIO device + * @gpio: gpio pin number within the device + * + * This function reads the state of the specified pin of the GPIO device. + * + * Return: 0 if the pin is low, 1 if pin is high. + */ +int gpio_get_value(unsigned gpio) +{ + u32 data; + unsigned int bank_num, bank_pin_num; + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + data = readl(ZYNQ_GPIO_BASE_ADDRESS + + ZYNQ_GPIO_DATA_RO_OFFSET(bank_num)); + + return (data >> bank_pin_num) & 1; +} + +/** + * gpio_set_value - Modify the value of the pin with specified value + * @gpio: gpio pin number within the device + * @value: value used to modify the value of the specified pin + * + * This function calculates the register offset (i.e to lower 16 bits or + * upper 16 bits) based on the given pin number and sets the value of a + * gpio pin to the specified value. The value is either 0 or non-zero. + */ +int gpio_set_value(unsigned gpio, int value) +{ + unsigned int reg_offset, bank_num, bank_pin_num; + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + if (bank_pin_num >= ZYNQ_GPIO_MID_PIN_NUM) { + /* only 16 data bits in bit maskable reg */ + bank_pin_num -= ZYNQ_GPIO_MID_PIN_NUM; + reg_offset = ZYNQ_GPIO_DATA_MSW_OFFSET(bank_num); + } else { + reg_offset = ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num); + } + + /* + * get the 32 bit value to be written to the mask/data register where + * the upper 16 bits is the mask and lower 16 bits is the data + */ + value = !!value; + value = ~(1 << (bank_pin_num + ZYNQ_GPIO_MID_PIN_NUM)) & + ((value << bank_pin_num) | ZYNQ_GPIO_UPPER_MASK); + + writel(value, ZYNQ_GPIO_BASE_ADDRESS + reg_offset); + + return 0; +} + +/** + * gpio_direction_input - Set the direction of the specified GPIO pin as input + * @gpio: gpio pin number within the device + * + * This function uses the read-modify-write sequence to set the direction of + * the gpio pin as input. + * + * Return: -1 if invalid gpio specified, 0 if successul + */ +int gpio_direction_input(unsigned gpio) +{ + u32 reg; + unsigned int bank_num, bank_pin_num; + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + /* bank 0 pins 7 and 8 are special and cannot be used as inputs */ + if (bank_num == 0 && (bank_pin_num == 7 || bank_pin_num == 8)) + return -1; + + /* clear the bit in direction mode reg to set the pin as input */ + reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + reg &= ~BIT(bank_pin_num); + writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + + return 0; +} + +/** + * gpio_direction_output - Set the direction of the specified GPIO pin as output + * @gpio: gpio pin number within the device + * @value: value to be written to specified pin + * + * This function sets the direction of specified GPIO pin as output, configures + * the Output Enable register for the pin and uses zynq_gpio_set to set + * the value of the pin to the value specified. + * + * Return: 0 always + */ +int gpio_direction_output(unsigned gpio, int value) +{ + u32 reg; + unsigned int bank_num, bank_pin_num; + + if (check_gpio(gpio) < 0) + return -1; + + zynq_gpio_get_bank_pin(gpio, &bank_num, &bank_pin_num); + + /* set the GPIO pin as output */ + reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + reg |= BIT(bank_pin_num); + writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_DIRM_OFFSET(bank_num)); + + /* configure the output enable reg for the pin */ + reg = readl(ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); + reg |= BIT(bank_pin_num); + writel(reg, ZYNQ_GPIO_BASE_ADDRESS + ZYNQ_GPIO_OUTEN_OFFSET(bank_num)); + + /* set the state of the pin */ + gpio_set_value(gpio, value); + return 0; +} + +/** + * Request a gpio before using it. + * + * NOTE: Argument 'label' is unused. + */ +int gpio_request(unsigned gpio, const char *label) +{ + if (check_gpio(gpio) < 0) + return -1; + + return 0; +} + +/** + * Reset and free the gpio after using it. + */ +int gpio_free(unsigned gpio) +{ + return 0; +} diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 7887f11c64..d4f3882cbd 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -25,7 +25,7 @@ int zynq_sdhci_init(phys_addr_t regbase) host->name = "zynq_sdhci"; host->ioaddr = (void *)regbase; - host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD | + host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; host->version = sdhci_readw(host, SDHCI_HOST_VERSION); diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 3e2b8dc183..9278763164 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -48,10 +48,16 @@ static void uart_zynq_serial_setbrg(const int port) /* Calculation results. */ unsigned int calc_bauderror, bdiv, bgen; unsigned long calc_baud = 0; - unsigned long baud = gd->baudrate; + unsigned long baud; unsigned long clock = get_uart_clk(port); struct uart_zynq *regs = uart_zynq_ports[port]; + /* Covering case where input clock is so slow */ + if (clock < 1000000 && gd->baudrate > 4800) + gd->baudrate = 4800; + + baud = gd->baudrate; + /* master clock * Baud rate = ------------------ * bgen * (bdiv + 1) diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 511ecca0b8..880d29ca71 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -36,7 +36,7 @@ #define CPU_RELEASE_ADDR 0xFFFFFF0 /* Cache Definitions */ -#define CONFIG_SYS_DCACHE_OFF +#define CONFIG_SYS_CACHELINE_SIZE 64 #define CONFIG_IDENT_STRING " Xilinx ZynqMP" @@ -61,13 +61,25 @@ #define CONFIG_SYS_BAUDRATE_TABLE \ { 4800, 9600, 19200, 38400, 57600, 115200 } +#define CONFIG_ZYNQ_SDHCI0 + /* Command line configuration */ #define CONFIG_CMD_ENV #define CONFIG_CMD_EXT2 #define CONFIG_CMD_EXT4 #define CONFIG_CMD_FAT +#define CONFIG_CMD_FS_GENERIC #define CONFIG_CMD_MEMORY #define CONFIG_DOS_PARTITION +#define CONFIG_CMD_ELF +#define CONFIG_MP + +/* SPI */ +#ifdef CONFIG_ZYNQ_SPI +# define CONFIG_SPI_FLASH +# define CONFIG_SPI_FLASH_SST +# define CONFIG_CMD_SF +#endif #if defined(CONFIG_ZYNQ_SDHCI0) || defined(CONFIG_ZYNQ_SDHCI1) # define CONFIG_MMC @@ -90,8 +102,8 @@ "kernel_addr=0x80000\0" \ "fdt_addr=0x7000000\0" \ "fdt_high=0x10000000\0" \ - "sdboot=mmcinfo && fatload mmc 0:0 $fdt_addr system.dtb && " \ - "fatload mmc 0:0 $kernel_addr Image && booti $kernel_addr - $fdt_addr\0" + "sdboot=mmcinfo && load mmc 0:0 $fdt_addr system.dtb && " \ + "load mmc 0:0 $kernel_addr Image && booti $kernel_addr - $fdt_addr\0" #define CONFIG_BOOTARGS "setenv bootargs console=ttyPS0,${baudrate} " \ "earlycon=cdns,mmio,0xff000000,${baudrate}n8" @@ -117,6 +129,29 @@ #define CONFIG_CMDLINE_EDITING #define CONFIG_SYS_MAXARGS 64 +#define CONFIG_ZYNQ_I2C0 +#define CONFIG_SYS_I2C_ZYNQ + +/* I2C */ +#if defined(CONFIG_SYS_I2C_ZYNQ) +# define CONFIG_CMD_I2C +# define CONFIG_SYS_I2C +# define CONFIG_SYS_I2C_ZYNQ_SPEED 100000 +# define CONFIG_SYS_I2C_ZYNQ_SLAVE 0 +#endif + +#define CONFIG_ZYNQMP_EEPROM + +/* EEPROM */ +#ifdef CONFIG_ZYNQMP_EEPROM +# define CONFIG_CMD_EEPROM +# define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 +# define CONFIG_SYS_I2C_EEPROM_ADDR 0x54 +# define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +# define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5 +# define CONFIG_SYS_EEPROM_SIZE (64 * 1024) +#endif + #define CONFIG_FIT #define CONFIG_FIT_VERBOSE /* enable fit_format_{error,warning}() */ diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index 485babd824..b83e037f6f 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -39,6 +39,9 @@ # define CONFIG_ZYNQ_SERIAL #endif +#define CONFIG_ZYNQ_GPIO +#define CONFIG_CMD_GPIO + /* Ethernet driver */ #if defined(CONFIG_ZYNQ_GEM0) || defined(CONFIG_ZYNQ_GEM1) # define CONFIG_NET_MULTI @@ -291,7 +294,7 @@ # define CONFIG_SYS_MMC_MAX_DEVICE 1 #endif -#define CONFIG_SYS_LDSCRIPT "arch/arm/cpu/armv7/zynq/u-boot.lds" +#define CONFIG_SYS_LDSCRIPT "arch/arm/mach-zynq/u-boot.lds" /* Commands */ #include <config_cmd_default.h> @@ -309,7 +312,7 @@ #define CONFIG_SPL_SERIAL_SUPPORT #define CONFIG_SPL_BOARD_INIT -#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/zynq/u-boot-spl.lds" +#define CONFIG_SPL_LDSCRIPT "arch/arm/mach-zynq/u-boot-spl.lds" /* MMC support */ #ifdef CONFIG_ZYNQ_SDHCI0 diff --git a/include/configs/zynq_picozed.h b/include/configs/zynq_picozed.h new file mode 100644 index 0000000000..d116e05ac7 --- /dev/null +++ b/include/configs/zynq_picozed.h @@ -0,0 +1,27 @@ +/* + * (C) Copyright 2015 Xilinx, Inc. + * + * Configuration for PicoZed + * See zynq-common.h for Zynq common configs + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ZYNQ_PICOZED_H +#define __CONFIG_ZYNQ_PICOZED_H + +#define CONFIG_SYS_SDRAM_SIZE (1024 * 1024 * 1024) + +#define CONFIG_ZYNQ_SERIAL_UART1 +#define CONFIG_ZYNQ_GEM0 +#define CONFIG_ZYNQ_GEM_PHY_ADDR0 0 + +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_ZYNQ_SDHCI1 +#define CONFIG_ZYNQ_USB +#define CONFIG_ZYNQ_BOOT_FREEBSD + +#include <configs/zynq-common.h> + +#endif /* __CONFIG_ZYNQ_PICOZED_H */ |