diff options
Diffstat (limited to 'arch/arm/boards/zii-vf610-dev')
7 files changed, 553 insertions, 0 deletions
diff --git a/arch/arm/boards/zii-vf610-dev/Makefile b/arch/arm/boards/zii-vf610-dev/Makefile new file mode 100644 index 0000000000..1297d815e3 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/Makefile @@ -0,0 +1,3 @@ +obj-y += board.o +lwl-y += lowlevel.o +bbenv-y += defaultenv-zii-vf610-dev diff --git a/arch/arm/boards/zii-vf610-dev/board.c b/arch/arm/boards/zii-vf610-dev/board.c new file mode 100644 index 0000000000..eea3828aa7 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/board.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2016 Zodiac Inflight Innovation + * Author: Andrey Smirnov <andrew.smirnov@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <init.h> +#include <gpio.h> +#include <environment.h> +#include <linux/clk.h> +#include <dt-bindings/clock/vf610-clock.h> +#include <envfs.h> + + +static int expose_signals(const struct gpio *signals, + size_t signal_num) +{ + int ret, i; + + ret = gpio_request_array(signals, signal_num); + if (ret) + return ret; + + for (i = 0; i < signal_num; i++) + export_env_ull(signals[i].label, signals[i].gpio); + + return 0; +} + +static int zii_vf610_cfu1_expose_signals(void) +{ + static const struct gpio signals[] = { + { + .gpio = 132, + .flags = GPIOF_IN, + .label = "fim_sd", + }, + { + .gpio = 118, + .flags = GPIOF_OUT_INIT_LOW, + .label = "fim_tdis", + }, + }; + + if (!of_machine_is_compatible("zii,vf610cfu1-a")) + return 0; + + return expose_signals(signals, ARRAY_SIZE(signals)); +} +late_initcall(zii_vf610_cfu1_expose_signals); + +static int zii_vf610_cfu1_spu3_expose_signals(void) +{ + static const struct gpio signals[] = { + { + .gpio = 107, + .flags = GPIOF_OUT_INIT_LOW, + .label = "soc_sw_rstn", + }, + { + .gpio = 98, + .flags = GPIOF_IN, + .label = "e6352_intn", + }, + }; + + if (!of_machine_is_compatible("zii,vf610spu3-a") && + !of_machine_is_compatible("zii,vf610cfu1-a")) + return 0; + + return expose_signals(signals, ARRAY_SIZE(signals)); +} +late_initcall(zii_vf610_cfu1_spu3_expose_signals); + +static int zii_vf610_dev_print_clocks(void) +{ + int i; + struct clk *clk; + struct device_node *ccm_np; + const unsigned long MHz = 1000000; + const char *clk_names[] = { "cpu", "ddr", "bus", "ipg" }; + + if (!of_machine_is_compatible("zii,vf610dev")) + return 0; + + ccm_np = of_find_compatible_node(NULL, NULL, "fsl,vf610-ccm"); + if (!ccm_np) { + pr_err("Couln't get CCM node\n"); + return -ENOENT; + } + + for (i = 0; i < ARRAY_SIZE(clk_names); i++) { + unsigned long rate; + const char *name = clk_names[i]; + + clk = of_clk_get_by_name(ccm_np, name); + if (IS_ERR(clk)) { + pr_err("Failed to get '%s' clock (%ld)\n", + name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + + rate = clk_get_rate(clk); + + pr_info("%s clock : %8lu MHz\n", name, rate / MHz); + } + + return 0; +} +late_initcall(zii_vf610_dev_print_clocks); + +static int zii_vf610_dev_set_hostname(void) +{ + size_t i; + static const struct { + const char *compatible; + const char *hostname; + } boards[] = { + { "zii,vf610spu3-a", "spu3-rev-a" }, + { "zii,vf610cfu1-a", "cfu1-rev-a" }, + { "zii,vf610dev-b", "dev-rev-b" }, + { "zii,vf610dev-c", "dev-rev-c" }, + { "zii,vf610scu4-aib-c", "scu4-aib-rev-c" }, + }; + + if (!of_machine_is_compatible("zii,vf610dev")) + return 0; + + for (i = 0; i < ARRAY_SIZE(boards); i++) { + if (of_machine_is_compatible(boards[i].compatible)) { + barebox_set_hostname(boards[i].hostname); + break; + } + } + + defaultenv_append_directory(defaultenv_zii_vf610_dev); + return 0; +} +late_initcall(zii_vf610_dev_set_hostname); diff --git a/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/boot/sd b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/boot/sd new file mode 100644 index 0000000000..cf8eec363c --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/boot/sd @@ -0,0 +1,4 @@ +#!/bin/sh + +global.bootm.image=/mnt/sd/zImage +global.bootm.oftree=/mnt/sd/${global.bootm.oftree} diff --git a/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/automount-sd b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/automount-sd new file mode 100644 index 0000000000..f44dab34e4 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/automount-sd @@ -0,0 +1,13 @@ +#!/bin/sh + +if [ x${global.hostname} = xdev-rev-b -o x${global.hostname} = xdev-rev-c ]; +then + global sd=0 +else + global sd=1 +fi + +mkdir -p /mnt/sd +automount /mnt/sd 'mci${global.sd}.probe=1 && mount /dev/disk${global.sd}.0 /mnt/sd' + +exit 0 diff --git a/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/choose-dtb b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/choose-dtb new file mode 100644 index 0000000000..41a74c3a98 --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/defaultenv-zii-vf610-dev/init/choose-dtb @@ -0,0 +1,4 @@ +#!/bin/sh + +global.bootm.oftree=vf610-zii-${global.hostname}.dtb + diff --git a/arch/arm/boards/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg b/arch/arm/boards/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg new file mode 100644 index 0000000000..177f4e8bdc --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/flash-header-zii-vf610-dev.imxcfg @@ -0,0 +1,243 @@ +soc vf610 +loadaddr 0x80000000 +dcdofs 0x400 + +#define VF610_DDR_PAD_CTRL 0x00000180 /* 25 Ohm drive strength */ +#define VF610_DDR_PAD_CTRL_1 0x00010180 /* 25 Ohm drive strength + differential input */ + +#define DDRMC_PHY_DQ_TIMING 0x00002613 +#define DDRMC_PHY_DQS_TIMING 0x00002615 +#define DDRMC_PHY_CTRL 0x00210000 +#define DDRMC_PHY_MASTER_CTRL 0x0001012a +#define DDRMC_PHY_SLAVE_CTRL 0x00002000 +#define DDRMC_PHY_OFF 0x00000000 +#define DDRMC_PHY_PROC_PAD_ODT 0x00010101 + +#define CHECKPOINT(n) wm 32 0x3f000000 n + +CHECKPOINT(1) + +/* ======================= Clock initialization =======================*/ + +/* + * Ungate all IP block clocks + */ +wm 32 0x4006b040 0xffffffff +wm 32 0x4006b044 0xffffffff +wm 32 0x4006b048 0xffffffff +wm 32 0x4006b04c 0xffffffff +wm 32 0x4006b050 0xffffffff +wm 32 0x4006b058 0xffffffff +wm 32 0x4006b05c 0xffffffff +wm 32 0x4006b060 0xffffffff +wm 32 0x4006b064 0xffffffff +wm 32 0x4006b068 0xffffffff +wm 32 0x4006b06c 0xffffffff + + +/* + * Turn PLL2 on + */ +wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */ + +CHECKPOINT(2) + +/* + * Wait for PLLs to lock + */ +check 32 while_any_bit_clear 0x40050030 0x80000000 + + +CHECKPOINT(3) + +clear_bits 32 0x4006b008 0x00000040 +set_bits 32 0x4006b008 0x00002000 + + + +/* ======================= DDR IOMUX =======================*/ + +CHECKPOINT(4) + +wm 32 0x40048220 0x00000180 +wm 32 0x40048224 0x00000180 +wm 32 0x40048228 0x00000180 +wm 32 0x4004822c 0x00000180 +wm 32 0x40048230 0x00000180 +wm 32 0x40048234 0x00000180 +wm 32 0x40048238 0x00000180 +wm 32 0x4004823c 0x00000180 +wm 32 0x40048240 0x00000180 +wm 32 0x40048244 0x00000180 +wm 32 0x40048248 0x00000180 +wm 32 0x4004824c 0x00000180 +wm 32 0x40048250 0x00000180 +wm 32 0x40048254 0x00000180 +wm 32 0x40048258 0x00000180 +wm 32 0x4004825c 0x00000180 +wm 32 0x40048260 0x00000180 +wm 32 0x40048264 0x00000180 +wm 32 0x40048268 0x00000180 +wm 32 0x4004826c 0x00000180 +wm 32 0x40048270 0x00000180 +wm 32 0x40048274 0x00000180 +wm 32 0x40048278 0x00000180 +wm 32 0x4004827c 0x00010180 +wm 32 0x40048280 0x00010180 +wm 32 0x40048284 0x00010180 +wm 32 0x40048288 0x00010180 +wm 32 0x4004828c 0x00010180 +wm 32 0x40048290 0x00010180 +wm 32 0x40048294 0x00010180 +wm 32 0x40048298 0x00010180 +wm 32 0x4004829c 0x00010180 +wm 32 0x400482a0 0x00010180 +wm 32 0x400482a4 0x00010180 +wm 32 0x400482a8 0x00010180 +wm 32 0x400482ac 0x00010180 +wm 32 0x400482b0 0x00010180 +wm 32 0x400482b4 0x00010180 +wm 32 0x400482b8 0x00010180 +wm 32 0x400482bc 0x00010180 +wm 32 0x400482c0 0x00010180 +wm 32 0x400482c4 0x00010180 +wm 32 0x400482c8 0x00010180 +wm 32 0x400482cc 0x00000180 +wm 32 0x400482d0 0x00000180 +wm 32 0x400482d4 0x00000180 +wm 32 0x400482d8 0x00000180 +wm 32 0x4004821c 0x00000180 + +/* ======================= DDR Controller =======================*/ + +CHECKPOINT(5) +wm 32 0x400ae000 0x00000600 +wm 32 0x400ae008 0x00000005 +wm 32 0x400ae028 0x00013880 +wm 32 0x400ae02c 0x00030d40 +wm 32 0x400ae030 0x00000506 +wm 32 0x400ae034 0x06040400 +wm 32 0x400ae038 0x1006040e +wm 32 0x400ae040 0x04040000 +wm 32 0x400ae044 0x006db00c +wm 32 0x400ae048 0x00000403 +wm 32 0x400ae050 0x01000000 +wm 32 0x400ae054 0x00060001 +wm 32 0x400ae058 0x000c0000 +wm 32 0x400ae05c 0x03000200 +wm 32 0x400ae060 0x00000006 +wm 32 0x400ae064 0x00010000 +wm 32 0x400ae068 0x0c300068 +wm 32 0x400ae070 0x00000000 +wm 32 0x400ae074 0x00000003 +wm 32 0x400ae078 0x0000000a +wm 32 0x400ae07c 0x006c0200 +wm 32 0x400ae084 0x00010000 +wm 32 0x400ae088 0x00050500 +wm 32 0x400ae098 0x00000000 +wm 32 0x400ae09c 0x04001002 +wm 32 0x400ae0a4 0x00000001 +wm 32 0x400ae0c0 0x00460420 +wm 32 0x400ae0c4 0x00000000 +wm 32 0x400ae0cc 0x00000000 +wm 32 0x400ae0e4 0x02000000 +wm 32 0x400ae108 0x01000200 +wm 32 0x400ae10c 0x00000040 +wm 32 0x400ae114 0x00000200 +wm 32 0x400ae118 0x00000040 +wm 32 0x400ae120 0x00000000 +wm 32 0x400ae124 0x0a010100 +wm 32 0x400ae128 0x01014040 +wm 32 0x400ae12c 0x01010101 +wm 32 0x400ae130 0x03030000 +wm 32 0x400ae134 0x01000101 +wm 32 0x400ae138 0x0700000c +wm 32 0x400ae13c 0x00000000 +wm 32 0x400ae148 0x10000000 +wm 32 0x400ae15c 0x01000000 +wm 32 0x400ae160 0x00040000 +wm 32 0x400ae164 0x00000002 +wm 32 0x400ae16c 0x00020000 +wm 32 0x400ae180 0x00002819 +wm 32 0x400ae184 0x01000000 +wm 32 0x400ae188 0x00000000 +wm 32 0x400ae18c 0x00000000 +wm 32 0x400ae198 0x00000000 +wm 32 0x400ae1a4 0x00000c00 +wm 32 0x400ae1a8 0x00000000 +wm 32 0x400ae1b8 0x0000000c +wm 32 0x400ae1c8 0x00000000 +wm 32 0x400ae1cc 0x00000000 +wm 32 0x400ae1d4 0x00000000 +wm 32 0x400ae1d8 0x01010000 +wm 32 0x400ae1e0 0x02020000 +wm 32 0x400ae1e4 0x00000202 +wm 32 0x400ae1e8 0x01010064 +wm 32 0x400ae1ec 0x00010101 +wm 32 0x400ae1f0 0x00000064 +wm 32 0x400ae1f8 0x00000800 +wm 32 0x400ae210 0x00000506 +wm 32 0x400ae224 0x00020000 +wm 32 0x400ae228 0x01000000 +wm 32 0x400ae22c 0x04070303 +wm 32 0x400ae230 0x00000040 +wm 32 0x400ae23c 0x06000080 +wm 32 0x400ae240 0x04070303 +wm 32 0x400ae244 0x00000040 +wm 32 0x400ae248 0x00000040 +wm 32 0x400ae24c 0x000f0000 +wm 32 0x400ae250 0x000f0000 +wm 32 0x400ae25c 0x00000101 +wm 32 0x400ae268 0x682c4000 +wm 32 0x400ae26c 0x00000012 +wm 32 0x400ae278 0x00000006 +wm 32 0x400ae284 0x00010202 + +/* ======================= DDR PHY =======================*/ + +CHECKPOINT(6) + +wm 32 0x400ae400 0x00002613 +wm 32 0x400ae440 0x00002613 +wm 32 0x400ae480 0x00002613 +wm 32 0x400ae404 0x00002615 +wm 32 0x400ae444 0x00002615 +wm 32 0x400ae408 0x00210000 +wm 32 0x400ae448 0x00210000 +wm 32 0x400ae488 0x00210000 +wm 32 0x400ae40c 0x0001012a +wm 32 0x400ae44c 0x0001012a +wm 32 0x400ae48c 0x0001012a +wm 32 0x400ae410 0x00002000 +wm 32 0x400ae450 0x00002000 +wm 32 0x400ae490 0x00002000 +wm 32 0x400ae4c4 0x00000000 +wm 32 0x400ae4c8 0x00001100 +wm 32 0x400ae4d0 0x00010101 +wm 32 0x400ae000 0x00000601 + +CHECKPOINT(7) + +check 32 while_any_bit_clear 0x400ae140 0x100 +# check 32 while_any_bit_clear 0x400ae42c 0x1 +# check 32 while_any_bit_clear 0x400ae46c 0x1 +# check 32 while_any_bit_clear 0x400ae4ac 0x1 + +CHECKPOINT(8) + +wm 32 0x80000000 0xa5a5a5a5 +check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5 + +wm 32 0x400ae000 0x00000600 +wm 32 0x400ae000 0x00000601 + +check 32 while_any_bit_clear 0x400ae140 0x100 +# check 32 while_any_bit_clear 0x400ae42c 0x1 +# check 32 while_any_bit_clear 0x400ae46c 0x1 +# check 32 while_any_bit_clear 0x400ae4ac 0x1 + +/* wm 32 0x3f040000 0xf0 + check 32 while_any_bit_clear 0x3f040000 0x0f */ + + +CHECKPOINT(9) diff --git a/arch/arm/boards/zii-vf610-dev/lowlevel.c b/arch/arm/boards/zii-vf610-dev/lowlevel.c new file mode 100644 index 0000000000..95b68d5dce --- /dev/null +++ b/arch/arm/boards/zii-vf610-dev/lowlevel.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 Zodiac Inflight Innovation + * Author: Andrey Smirnov <andrew.smirnov@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <linux/sizes.h> +#include <mach/generic.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> +#include <mach/vf610-regs.h> +#include <mach/clock-vf610.h> +#include <mach/iomux-vf610.h> +#include <debug_ll.h> + +static inline void setup_uart(void) +{ + void __iomem *iomux = IOMEM(VF610_IOMUXC_BASE_ADDR); + + vf610_ungate_all_peripherals(); + vf610_setup_pad(iomux, VF610_PAD_PTB10__UART0_TX); + vf610_uart_setup_ll(); + + putc_ll('>'); +} + +enum zii_platform_vf610_type { + ZII_PLATFORM_VF610_DEV_REV_B = 0x01, + ZII_PLATFORM_VF610_SCU4_AIB = 0x02, + ZII_PLATFORM_VF610_SPU3 = 0x03, + ZII_PLATFORM_VF610_CFU1 = 0x04, + ZII_PLATFORM_VF610_DEV_REV_C = 0x05, +}; + +unsigned int get_system_type(void) +{ +#define GPIO_PDIR 0x10 + + u32 pdir; + void __iomem *gpio2 = IOMEM(VF610_GPIO2_BASE_ADDR); + void __iomem *iomux = IOMEM(VF610_IOMUXC_BASE_ADDR); + unsigned low, high; + + /* + * System type is encoded as a 4-bit number specified by the + * following pins (pulled up or down with resistors on the + * board). + */ + vf610_setup_pad(iomux, VF610_PAD_PTD16__GPIO_78); + vf610_setup_pad(iomux, VF610_PAD_PTD17__GPIO_77); + vf610_setup_pad(iomux, VF610_PAD_PTD18__GPIO_76); + vf610_setup_pad(iomux, VF610_PAD_PTD19__GPIO_75); + + pdir = readl(gpio2 + GPIO_PDIR); + + low = 75 % 32; + high = 78 % 32; + + pdir &= GENMASK(high, low); + pdir >>= low; + + return pdir; +} + +extern char __dtb_vf610_zii_dev_rev_b_start[]; +extern char __dtb_vf610_zii_dev_rev_c_start[]; +extern char __dtb_vf610_zii_cfu1_rev_a_start[]; +extern char __dtb_vf610_zii_spu3_rev_a_start[]; +extern char __dtb_vf610_zii_scu4_aib_rev_c_start[]; + +ENTRY_FUNCTION(start_zii_vf610_dev, r0, r1, r2) +{ + void *fdt; + const unsigned int system_type = get_system_type(); + + vf610_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); + + switch (system_type) { + default: + /* + * GCC can be smart enough to, when DEBUG_LL is + * disabled, reduce this switch statement to a LUT + * fetch. Unfortunately here, this early in the boot + * process before any relocation/address fixups could + * happen, the address of that LUT used by the code is + * incorrect and any access to it would result in + * bogus values. + * + * Adding the following barrier() statement seem to + * force the compiler to always translate this block + * to a sequence of consecutive checks and jumps with + * relative fetches, which should work with or without + * relocation/fixups. + */ + barrier(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) { + relocate_to_current_adr(); + setup_c(); + puts_ll("*********************************\n"); + puts_ll("* Unknown system type: "); + puthex_ll(system_type); + puts_ll("\n* Assuming devboard revision B\n"); + puts_ll("*********************************\n"); + } + case ZII_PLATFORM_VF610_DEV_REV_B: /* FALLTHROUGH */ + fdt = __dtb_vf610_zii_dev_rev_b_start; + break; + case ZII_PLATFORM_VF610_SCU4_AIB: + fdt = __dtb_vf610_zii_scu4_aib_rev_c_start; + break; + case ZII_PLATFORM_VF610_DEV_REV_C: + fdt = __dtb_vf610_zii_dev_rev_c_start; + break; + case ZII_PLATFORM_VF610_CFU1: + fdt = __dtb_vf610_zii_cfu1_rev_a_start; + break; + case ZII_PLATFORM_VF610_SPU3: + fdt = __dtb_vf610_zii_spu3_rev_a_start; + break; + } + + barebox_arm_entry(0x80000000, SZ_512M, fdt - get_runtime_offset()); +} |