diff mbox

[6/6] ARM64: HiKey: hi6220: Add u-boot support for the 96boards CE HiKey board.

Message ID 1431437141-18096-7-git-send-email-peter.griffin@linaro.org
State New
Headers show

Commit Message

Peter Griffin May 12, 2015, 1:25 p.m. UTC
HiKey is the first 96boards consumer edition compliant board. It features a hi6220
SoC which has eight ARM A53 cpu's.

This initial port adds support for: -
1) Serial
2) eMMC / sd card
3) USB
4) GPIO

It has been tested with Arm Trusted Firmware running u-boot as the BL33 executable.

Notes:

eMMC has been tested with basic reading of eMMC partition intto DDR. I have not
tested writing / erasing. I suspect due to lack of clock control it won't be
running in the most performant high speed mode.

SD card slot has been tested for reading and booting kernels into DDR.
It is also currently used for saving the u-boot enviroment.

USB has been tested with ASIX networking adapter to tftpboot kernels
into DDR. USB mass storage device enumeration doesn't currently work for
an unkown reason.

GPIO has been tested using gpio toggle GPIO4_1-3 to flash LEDs.

Basic SoC datasheet can be found here: -
https://github.com/96boards/documentation/blob/master/hikey/
Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf

Board schematic can be found here: -
https://github.com/96boards/documentation/blob/master/hikey/
96Boards-Hikey-Rev-A1.pdf

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 arch/arm/Kconfig                |   5 +
 board/96boards/hikey64/Kconfig  |  12 ++
 board/96boards/hikey64/Makefile |   8 +
 board/96boards/hikey64/hikey.c  | 439 ++++++++++++++++++++++++++++++++++++++++
 configs/hikey_aemv8a_defconfig  |   5 +
 include/configs/hikey_aemv8a.h  | 187 +++++++++++++++++
 6 files changed, 656 insertions(+)
 create mode 100644 board/96boards/hikey64/Kconfig
 create mode 100644 board/96boards/hikey64/Makefile
 create mode 100644 board/96boards/hikey64/hikey.c
 create mode 100644 configs/hikey_aemv8a_defconfig
 create mode 100644 include/configs/hikey_aemv8a.h

Comments

Peter Griffin June 25, 2015, 3:08 p.m. UTC | #1
Hi Rob,

On 12 May 2015 at 19:29, Rob Herring <robherring2@gmail.com> wrote:

> On Tue, May 12, 2015 at 8:25 AM, Peter Griffin <peter.griffin@linaro.org>
> wrote:
> > HiKey is the first 96boards consumer edition compliant board. It
> features a hi6220
> > SoC which has eight ARM A53 cpu's.
>

Thanks for reviewing the patches. Also sorry for the long lag in replying
to you. I have been
a bit busy on other activities recently.

<snip>

>  arch/arm/Kconfig                |   5 +
>  board/96boards/hikey64/Kconfig  |  12 ++
>  board/96boards/hikey64/Makefile |   8 +
>  board/96boards/hikey64/hikey.c  | 439
++++++++++++++++++++++++++++++++++++++++

This is more likely to have common parts with other HiSi boards than
> other 96boards compliant boards.
>

OK, I've renamed the directory hisilicon in v2 which seems to match with how
other semi vendors have done it e.g. ti, samsung and broadcom


> >  configs/hikey_aemv8a_defconfig  |   5 +
> >  include/configs/hikey_aemv8a.h  | 187 +++++++++++++++++
>
> aemv8a seems to be leftover from VExpress. Just hikey should be enough.
>

Yes your right, I've removed it in v2

>
> >  6 files changed, 656 insertions(+)
> >  create mode 100644 board/96boards/hikey64/Kconfig
> >  create mode 100644 board/96boards/hikey64/Makefile
> >  create mode 100644 board/96boards/hikey64/hikey.c
> >  create mode 100644 configs/hikey_aemv8a_defconfig
> >  create mode 100644 include/configs/hikey_aemv8a.h
> >
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 7ed0e20..0b6de5d 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -656,6 +656,10 @@ config TARGET_LS2085A_SIMU
> >         select ARM64
> >         select ARMV8_MULTIENTRY
> >
> > +config TARGET_96BOARDS_HIKEY
> > +       bool "Support HiKey 96boards Consumer Edition Platform"
> > +       select ARM64
> > +
> >  config TARGET_LS1021AQDS
> >         bool "Support ls1021aqds"
> >         select CPU_V7
> > @@ -787,6 +791,7 @@ source "board/armadeus/apf27/Kconfig"
> >  source "board/armltd/integrator/Kconfig"
> >  source "board/armltd/vexpress/Kconfig"
> >  source "board/armltd/vexpress64/Kconfig"
> > +source "board/96boards/hikey64/Kconfig"
> >  source "board/bachmann/ot1200/Kconfig"
> >  source "board/balloon3/Kconfig"
> >  source "board/barco/platinum/Kconfig"
> > diff --git a/board/96boards/hikey64/Kconfig
> b/board/96boards/hikey64/Kconfig
> > new file mode 100644
> > index 0000000..eb1709b
> > --- /dev/null
> > +++ b/board/96boards/hikey64/Kconfig
> > @@ -0,0 +1,12 @@
> > +if TARGET_96BOARDS_HIKEY
> > +
> > +config SYS_BOARD
> > +       default "hikey64"
> > +
> > +config SYS_VENDOR
> > +       default "96boards"
>
> 96boards doesn't really make boards. This should be CircuitCo or HiSilicon.
>

Renamed to be HiSilicon in v2


>
> > +
> > +config SYS_CONFIG_NAME
> > +       default "hikey_aemv8a"
> > +
> > +endif
> > diff --git a/board/96boards/hikey64/Makefile
> b/board/96boards/hikey64/Makefile
> > new file mode 100644
> > index 0000000..d4ec8c7
>

<snip>


> > +#endif
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +#if defined(CONFIG_SHOW_BOOT_PROGRESS)
> > +void show_boot_progress(int progress)
> > +{
> > +       printf("Boot reached stage %d\n", progress);
>
> Nothing h/w specific here. I'd remove or make this be the default
> (weak) implementation.
>

I've removed it in v2


>
> > +}
> > +#endif
> > +
> > +static inline void delay(ulong loops)
>
> udelay/mdelay does not work for you?
>

This was left over from vexpress. I will remove in v2 (after double checking
that udelay and mdelay are indeed working properly).

> +{
> +       __asm__ volatile ("1:\n"
> +               "subs %0, %1, #1\n"
> +               "bne 1b" : "=r" (loops) : "0" (loops));
> +}
> +
> +
> +#define EYE_PATTERN    0x70533483
> +
> +static void init_usb_and_picophy(void)
> +{
> +       unsigned int data;
> +
> +       /* enable USB clock */
> +       writel(PERI_CLK0_USBOTG, PERI_SC_PERIPH_CLK0_EN);
> +       do {
> +               data = readl(PERI_SC_PERIPH_CLK0_STAT);
> +       } while ((data & PERI_CLK0_USBOTG) == 0);
> +
> +       /* take usb IPs out of reset */
> +       writel(PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
> +               PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K,
> +               PERI_SC_PERIPH_RST0_DIS);
> +       do {
> +               data = readl(PERI_SC_PERIPH_RST0_STAT);
> +               data &= PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
> +                       PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K;
> +       } while (data);
> +
> +       /*CTRL 5*/
> +       data = readl(PERI_SC_PERIPH_CTRL5);
> +       data &= ~PERI_CTRL5_PICOPHY_BC_MODE;
> +       data |= PERI_CTRL5_USBOTG_RES_SEL | PERI_CTRL5_PICOPHY_ACAENB;
> +       data |= 0x300;
> +       writel(data, PERI_SC_PERIPH_CTRL5);
> +
> +       /*CTRL 4*/
> +
> +       /* configure USB PHY */
> +       data = readl(PERI_SC_PERIPH_CTRL4);
> +
> +       /* make PHY out of low power mode */
> +       data &= ~PERI_CTRL4_PICO_SIDDQ;
> +       data &= ~PERI_CTRL4_PICO_OGDISABLE;
> +       data |= PERI_CTRL4_PICO_VBUSVLDEXTSEL |
PERI_CTRL4_PICO_VBUSVLDEXT;
> +       writel(data, PERI_SC_PERIPH_CTRL4);
> +
> +       writel(EYE_PATTERN, PERI_SC_PERIPH_CTRL8);
> +
> +       delay(20000);
> +}
> +
> +static int sd_card_detect(void)
> +{
> +       int ret;
> +
> +       /* configure GPIO8 as nopull */
> +       writel(0, 0xf8001830);
> +
> +       gpio_request(8, "SD CD");
> +
> +       gpio_direction_input(8);
> +       ret = gpio_get_value(8);
> +
> +       if (!ret) {
> +               printf("%s: SD card present\n", __func__);
> +               return 1;
> +       }
> +
> +       printf("%s: SD card not present\n", __func__);
> +       return 0;
> +}
> +
> +static void mmc1_setup_pinmux(void)
> +{
> +       /* switch pinmux to SD */
> +       writel(0, 0xf701000c);
> +       writel(0, 0xf7010010);
> +       writel(0, 0xf7010014);
> +       writel(0, 0xf7010018);
> +       writel(0, 0xf701001c);
> +       writel(0, 0xf7010020);
> +
> +       /* input, 16mA or 12mA */
> +       writel(0x64, 0xf701080c);
> +       writel(0x54, 0xf7010810);
> +       writel(0x54, 0xf7010814);
> +       writel(0x54, 0xf7010818);
> +       writel(0x54, 0xf701081c);
> +       writel(0x54, 0xf7010820);
> +
> +       sd_card_detect();
> +}
> +
> +static void mmc1_init_pll(void)
> +{
> +       uint32_t data;
> +
> +       /* select SYSPLL as the source of MMC1 */
> +       /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
> +       writel(1 << 11 | 1 << 27, PERI_SC_CLK0_SEL);
> +       do {
> +               data = readl(PERI_SC_CLK0_SEL);
> +       } while (!(data & (1 << 11)));
> +
> +       /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
> +       writel(1 << 30, PERI_SC_CLK0_SEL);
> +       do {
> +               data = readl(PERI_SC_CLK0_SEL);
> +       } while (data & (1 << 14));
> +
> +       writel((1 << 1), PERI_SC_PERIPH_CLK0_EN);
> +       do {
> +               data = readl(PERI_SC_PERIPH_CLK0_STAT);
> +       } while (!(data & (1 << 1)));
> +
> +       data = readl(PERI_SC_PERIPH_CLK12_EN);
> +       data |= 1 << 2;
> +       writel(data, PERI_SC_PERIPH_CLK12_EN);
> +
> +       do {
> +               /* 1.2GHz / 50 = 24MHz */
> +               writel(0x31 | (1 << 7), PERI_SC_CLKCFG8BIT2);
> +               data = readl(PERI_SC_CLKCFG8BIT2);
> +       } while ((data & 0x31) != 0x31);
> +}
> +
> +static void mmc1_reset_clk(void)
> +{
> +       unsigned int data;
> +
> +       /* disable mmc1 bus clock */
> +       writel(PERI_CLK0_MMC1, PERI_SC_PERIPH_CLK0_DIS);
> +       do {
> +               data = readl(PERI_SC_PERIPH_CLK0_STAT);
> +       } while (data & PERI_CLK0_MMC1);
> +
> +       /* enable mmc1 bus clock */
> +       writel(PERI_CLK0_MMC1, PERI_SC_PERIPH_CLK0_EN);
> +       do {
> +               data = readl(PERI_SC_PERIPH_CLK0_STAT);
> +       } while (!(data & PERI_CLK0_MMC1));
> +
> +       /* reset mmc1 clock domain */
> +       writel(PERI_RST0_MMC1, PERI_SC_PERIPH_RST0_EN);
> +
> +       /* bypass mmc1 clock phase */
> +       data = readl(PERI_SC_PERIPH_CTRL2);
> +       data |= 3 << 2;
> +       writel(data, PERI_SC_PERIPH_CTRL2);
> +
> +       /* disable low power */
> +       data = readl(PERI_SC_PERIPH_CTRL13);
> +       data |= 1 << 4;
> +       writel(data, PERI_SC_PERIPH_CTRL13);
> +       do {
> +               data = readl(PERI_SC_PERIPH_RST0_STAT);
> +       } while (!(data & PERI_RST0_MMC1));
> +
> +       /* unreset mmc0 clock domain */
> +       writel(PERI_RST0_MMC1, PERI_SC_PERIPH_RST0_DIS);
> +       do {
> +               data = readl(PERI_SC_PERIPH_RST0_STAT);
> +       } while (data & PERI_RST0_MMC1);
> +}
> +
> +/* PMU SSI is the IP that maps the external PMU hi6553 registers as IO */
> +static void hi6220_pmussi_init(void)
> +{
> +       uint32_t data;
> +
> +       /* Take PMUSSI out of reset */
> +       writel(ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N,
> +              ALWAYSON_SC_PERIPH_RST4_DIS);
> +       do {
> +               data = readl(ALWAYSON_SC_PERIPH_RST4_STAT);
> +       } while (data & ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N);
> +
> +       /* set PMU SSI clock latency for read operation */
> +       data = readl(ALWAYSON_SC_MCU_SUBSYS_CTRL3);
> +       data &= ~ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
> +       data |= ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_3;
> +       writel(data, ALWAYSON_SC_MCU_SUBSYS_CTRL3);
> +
> +       /* enable PMUSSI clock */
> +       data = ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_CCPU |
> +              ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_MCU;
> +       writel(data, ALWAYSON_SC_PERIPH_CLK5_EN);
> +       data = ALWAYSON_SC_PERIPH_CLK4_EN_PCLK_PMUSSI;
> +       writel(data, ALWAYSON_SC_PERIPH_CLK4_EN);
> +
> +       /* Output high to PMIC on PWR_HOLD_GPIO0_0 */
> +       gpio_request(0, "PWR_HOLD_GPIO0_0");
> +       gpio_direction_output(0, 1);
> +}
> +
> +uint8_t hi6553_readb(unsigned int offset)
> +{
> +       return readb((u8 *)(unsigned long)HI6220_PMUSSI_BASE + (offset <<
2));
> +}
> +
> +void hi6553_writeb(unsigned int offset, uint8_t value)
> +{
> +       writeb(value, (u8 *)(unsigned long)HI6220_PMUSSI_BASE + (offset
<< 2));
> +}
> +
> +static void hikey_hi6553_init(void)
> +{
> +       int data;
> +
> +       hi6553_writeb(HI6553_PERI_EN_MARK, 0x1e);
> +       hi6553_writeb(HI6553_NP_REG_ADJ1, 0);
> +       data = HI6553_DISABLE6_XO_CLK_CONN | HI6553_DISABLE6_XO_CLK_NFC |
> +               HI6553_DISABLE6_XO_CLK_RF1 | HI6553_DISABLE6_XO_CLK_RF2;
> +       hi6553_writeb(HI6553_DISABLE6_XO_CLK, data);
> +
> +       /* configure BUCK0 & BUCK1 */
> +       hi6553_writeb(HI6553_BUCK01_CTRL2, 0x5e);
> +       hi6553_writeb(HI6553_BUCK0_CTRL7, 0x10);
> +       hi6553_writeb(HI6553_BUCK1_CTRL7, 0x10);
> +       hi6553_writeb(HI6553_BUCK0_CTRL5, 0x1e);
> +       hi6553_writeb(HI6553_BUCK1_CTRL5, 0x1e);
> +       hi6553_writeb(HI6553_BUCK0_CTRL1, 0xfc);
> +       hi6553_writeb(HI6553_BUCK1_CTRL1, 0xfc);
> +
> +       /* configure BUCK2 */
> +       hi6553_writeb(HI6553_BUCK2_REG1, 0x4f);
> +       hi6553_writeb(HI6553_BUCK2_REG5, 0x99);
> +       hi6553_writeb(HI6553_BUCK2_REG6, 0x45);
> +       mdelay(1);
> +       hi6553_writeb(HI6553_VSET_BUCK2_ADJ, 0x22);
> +       mdelay(1);
> +
> +       /* configure BUCK3 */
> +       hi6553_writeb(HI6553_BUCK3_REG3, 0x02);
> +       hi6553_writeb(HI6553_BUCK3_REG5, 0x99);
> +       hi6553_writeb(HI6553_BUCK3_REG6, 0x41);
> +       hi6553_writeb(HI6553_VSET_BUCK3_ADJ, 0x02);
> +       mdelay(1);
> +
> +       /* configure BUCK4 */
> +       hi6553_writeb(HI6553_BUCK4_REG2, 0x9a);
> +       hi6553_writeb(HI6553_BUCK4_REG5, 0x99);
> +       hi6553_writeb(HI6553_BUCK4_REG6, 0x45);
> +
> +       /* configure LDO20 */
> +       hi6553_writeb(HI6553_LDO20_REG_ADJ, 0x50);
> +
> +       hi6553_writeb(HI6553_NP_REG_CHG, 0x0f);
> +       hi6553_writeb(HI6553_CLK_TOP0, 0x06);
> +       hi6553_writeb(HI6553_CLK_TOP3, 0xc0);
> +       hi6553_writeb(HI6553_CLK_TOP4, 0x00);
> +
> +       /* configure LDO7 & LDO10 for SD slot */
> +       data = hi6553_readb(HI6553_LDO7_REG_ADJ);
> +       data = (data & 0xf8) | 0x2;
> +       hi6553_writeb(HI6553_LDO7_REG_ADJ, data);
> +       mdelay(5);
> +       /* enable LDO7 */
> +       hi6553_writeb(HI6553_ENABLE2_LDO1_8, 1 << 6);
> +       mdelay(5);
> +       data = hi6553_readb(HI6553_LDO10_REG_ADJ);
> +       data = (data & 0xf8) | 0x5;
> +       hi6553_writeb(HI6553_LDO10_REG_ADJ, data);
> +       mdelay(5);
> +       /* enable LDO10 */
> +       hi6553_writeb(HI6553_ENABLE3_LDO9_16, 1 << 1);
> +       mdelay(5);
> +
> +       /* select 32.764KHz */
> +       hi6553_writeb(HI6553_CLK19M2_600_586_EN, 0x01);
> +}
> +
> +/*
> + * Routine: misc_init_r
> + * Description: A basic misc_init_r

Pretty worthless comments.
>

OK, removed in v2


>
> > + */
> > +int __weak misc_init_r(void)
>
> Why weak?
>

It shouldn't have been weak, __weak removed in v2

>
> > +{
> > +       init_usb_and_picophy();
> > +
> > +       return 0;
> > +}
> > +
> > +int board_init(void)
> > +{
> > +       gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
> > +       gd->flags = 0;
> > +
> > +       icache_enable();
> > +
> > +       return 0;
> > +}
> > +
> > +#ifdef CONFIG_GENERIC_MMC
> > +
> > +static int init_dwmmc(void)
> > +{
> > +       int ret;
> > +
> > +#ifdef CONFIG_DWMMC
> > +
> > +
>
> Extra blank lines.
>

Removed in v2


>
> > +       /* mmc0 pinmux and clocks are already configured by ATF */
> > +       ret = hi6220_dwmci_add_port(0, HI6220_MMC0_BASE, 8);
> > +
> > +       if (ret)
> > +               printf("%s: Error adding eMMC port\n", __func__);
> > +
> > +       /* take mmc1 (sd slot) out of reset, configure clocks and
> pinmuxing */
> > +
> > +       mmc1_init_pll();
> > +       mmc1_reset_clk();
> > +       mmc1_setup_pinmux();
> > +
> > +       ret |= hi6220_dwmci_add_port(1, HI6220_MMC1_BASE, 4);
> > +
> > +       if (ret)
> > +               printf("%s: Error adding SD port\n", __func__);
> > +#endif
> > +       return ret;
> > +}
> > +
> > +int board_mmc_init(bd_t *bis)
> > +{
> > +       int ret;
> > +
> > +       /* init the pmussi ip */
> > +       hi6220_pmussi_init();
> > +
> > +       /* init the hi6553 pmic */
> > +       hikey_hi6553_init();
> > +
> > +       /* add the eMMC and sd ports */
> > +       ret = init_dwmmc();
> > +
> > +       if (ret)
> > +               debug("init_dwmmc failed\n");
> > +
> > +       return ret;
> > +}
> > +#endif
> > +
> > +int dram_init(void)
> > +{
> > +       gd->ram_size =
> > +               get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
> PHYS_SDRAM_1_SIZE);
> > +       return 0;
> > +}
> > +
> > +void dram_init_banksize(void)
> > +{
> > +       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
> > +       gd->bd->bi_dram[0].size =
> > +                       get_ram_size((long *)PHYS_SDRAM_1,
> PHYS_SDRAM_1_SIZE);
> > +}
> > +
> > +/* Use the Watchdog to cause reset */
> > +void reset_cpu(ulong addr)
> > +{
> > +       /* TODO program the watchdog */
> > +}
> > diff --git a/configs/hikey_aemv8a_defconfig
> b/configs/hikey_aemv8a_defconfig
> > new file mode 100644
> > index 0000000..3bbb2c5
> > --- /dev/null
> > +++ b/configs/hikey_aemv8a_defconfig
> > @@ -0,0 +1,5 @@
> > +# 96boards HiKey
> > +CONFIG_ARM=y
> > +CONFIG_TARGET_96BOARDS_HIKEY=y
> > +CONFIG_DEFAULT_DEVICE_TREE="hikey"
> > +CONFIG_SHOW_BOOT_PROGRESS=y
> > diff --git a/include/configs/hikey_aemv8a.h
> b/include/configs/hikey_aemv8a.h
> > new file mode 100644
> > index 0000000..7c0012f
> > --- /dev/null
> > +++ b/include/configs/hikey_aemv8a.h
> > @@ -0,0 +1,187 @@
> > +/*
> > + * (C) Copyright 2015 Linaro
> > + *
> > + * Peter Griffin <peter.griffin@linaro.org>
> > + *
> > + * Configuration for HiKey 96boards CE. Parts were derived from other
> ARM
> > + * configurations.
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#ifndef __HIKEY_AEMV8A_H
> > +#define __HIKEY_AEMV8A_H
> > +
> > +/* We use generic board for hikey */
> > +#define CONFIG_SYS_GENERIC_BOARD
> > +
> > +#define CONFIG_REMAKE_ELF
> > +
> > +#define CONFIG_SUPPORT_RAW_INITRD
> > +
> > +/* Cache Definitions */
> > +#define CONFIG_SYS_DCACHE_OFF
> > +#define CONFIG_SYS_ICACHE_OFF
>
> I-cache at least should be simple to enable.
>

Good spot. I will try enabling both dcache and icache, and if it works
will have it enabled in v2.


>
> > +
> > +#define CONFIG_IDENT_STRING            " hikey_aemv8a"
> > +#define CONFIG_BOOTP_VCI_STRING
> "U-boot.armv8.hikey_aemv8a"
> > +
> > +/* Flat Device Tree Definitions */
> > +#define CONFIG_OF_LIBFDT
> > +
> > +/* Physical Memory Map */
> > +
> > +#define CONFIG_SYS_TEXT_BASE           0x37000000
> > +/* RAM debug builds */
> > +/*#define CONFIG_SYS_TEXT_BASE         0x27000000*/
> > +
> > +#define CONFIG_NR_DRAM_BANKS           1
> > +#define PHYS_SDRAM_1                   0x00000000
> > +#define PHYS_SDRAM_1_SIZE              0x40000000      /* 1024 MB */
> > +#define CONFIG_SYS_SDRAM_BASE          PHYS_SDRAM_1
> > +
> > +#define CONFIG_SYS_INIT_RAM_SIZE       0x1000
> > +
> > +#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE +
> 0x7fff0)
> > +
> > +#define CONFIG_SYS_LOAD_ADDR           (CONFIG_SYS_SDRAM_BASE + 0x8000)
>
> This is the kernel address? This is ideally 0x80000 for Image files.
>

Yes it is the default kernel load address. I can update to 0x80000 in v2.
Just for my own curiosity what is special about 0x80000?


> > +#define LINUX_BOOT_PARAM_ADDR          (CONFIG_SYS_SDRAM_BASE + 0x2000)
>
> What is this for?
>

This is assigned to bi_boot_params, which is used by the bootm function
for armv7. However on armv8 it appears not to be used so I think it can be
removed.

>
> > +
> > +/* Generic Timer Definitions */
> > +#define COUNTER_FREQUENCY              (0x1300000)     /* 19MHz */
>
> Write as decimal and then you don't need the comment.
>

OK, will fix in v2


>
> > +
> > +/* Generic Interrupt Controller Definitions */
> > +#define GICD_BASE                      (0xf6801000)
> > +#define GICC_BASE                      (0xf6802000)
> > +
> > +#define CONFIG_SYS_MEMTEST_START       V2M_BASE
> > +#define CONFIG_SYS_MEMTEST_END         (V2M_BASE + 0x40000000)
>
> V2M is a VExpress thing.
>

Yes your right, I will remove in v2

>
> > +
> > +/* Size of malloc() pool */
> > +#define CONFIG_SYS_MALLOC_LEN          (CONFIG_ENV_SIZE + (8 << 20))
>
> Why is this related to CONFIG_ENV_SIZE?
>

I will confess this is left over from vexpress. However judging by the
number
of other boards which declare CONFIG_SYS_MALLOC_LEN to be CONFIG_ENV_SIZE
plus some additional memory. I can only assume that there must be a command
or build
configuration which requires the enviroment to be malloc'ed.

git grep CONFIG_SYS_MALLOC_LEN | grep CONFIG_ENV_SIZE | wc -l
78

Either that or there has been a lot of copy and paste, and your the first
to notice ;-)

>
> > +
> > +/* PL011 Serial Configuration */
> > +#define CONFIG_PL011_SERIAL
> > +
> > +#define CONFIG_PL011_CLOCK             19200000
> > +#define CONFIG_PL01x_PORTS             {(void *)CONFIG_SYS_SERIAL0}
> > +#define CONFIG_CONS_INDEX              0
> > +
> > +#define CONFIG_BAUDRATE                        115200
> > +#define CONFIG_SYS_SERIAL0             0xF8015000
> > +
> > +#define CONFIG_CMD_USB
> > +#ifdef CONFIG_CMD_USB
> > +#define CONFIG_USB_DWC2
> > +#define CONFIG_USB_DWC2_REG_ADDR 0xF72C0000
> > +/*#define CONFIG_DWC2_DFLT_SPEED_FULL*/
> > +#define CONFIG_DWC2_ENABLE_DYNAMIC_FIFO
> > +
> > +#define CONFIG_USB_STORAGE
> > +#define CONFIG_USB_HOST_ETHER
> > +#define CONFIG_USB_ETHER_SMSC95XX
> > +#define CONFIG_USB_ETHER_ASIX
> > +#define CONFIG_MISC_INIT_R
> > +#endif
> > +
> > +#define CONFIG_HIKEY_GPIO
> > +#define CONFIG_DM_GPIO
> > +#define CONFIG_CMD_GPIO
> > +#define CONFIG_DM
> > +
> > +/* SD/MMC configuration */
> > +#define CONFIG_GENERIC_MMC
> > +#define CONFIG_MMC
> > +#define CONFIG_DWMMC
> > +#define CONFIG_HIKEY_DWMMC
> > +#define CONFIG_BOUNCE_BUFFER
> > +#define CONFIG_CMD_MMC
> > +
> > +#define CONFIG_FS_EXT4
> > +#define CONFIG_FS_FAT
> > +
> > +/* Command line configuration */
> > +#define CONFIG_MENU
> > +/*#define CONFIG_MENU_SHOW*/
> > +#define CONFIG_CMD_CACHE
>
> But you've disabled caches...
>

As mentioned above I will try enabling caches for V2

>
> > +#define CONFIG_CMD_BDI
> > +#define CONFIG_CMD_BOOTI
> > +#define CONFIG_CMD_UNZIP
> > +#define CONFIG_CMD_DHCP
> > +#define CONFIG_CMD_PXE
> > +#define CONFIG_CMD_ENV
> > +#define CONFIG_CMD_IMI
> > +#define CONFIG_CMD_LOADB
> > +#define CONFIG_CMD_MEMORY
> > +#define CONFIG_CMD_MII
> > +#define CONFIG_CMD_NET
> > +#define CONFIG_CMD_PING
> > +#define CONFIG_CMD_SAVEENV
> > +#define CONFIG_CMD_RUN
> > +#define CONFIG_CMD_BOOTD
> > +#define CONFIG_CMD_ECHO
> > +#define CONFIG_CMD_SOURCE
> > +#define CONFIG_CMD_FAT
> > +#define CONFIG_CMD_EXT2
> > +#define CONFIG_CMD_EXT4
> > +#define CONFIG_CMD_FS_GENERIC
> > +
> > +#define CONFIG_DOS_PARTITION
> > +#define CONFIG_EFI_PARTITION
> > +#define CONFIG_MAC_PARTITION
> > +#define CONFIG_MTD_PARTITIONS
>
> Use config_distro_defaults.h and you can drop lots of these.
>

OK thanks, I wasn't aware of that I will look at
using config_distro_defaults.h for V2.


> > +
> > +/* BOOTP options */
> > +#define CONFIG_BOOTP_BOOTFILESIZE
> > +#define CONFIG_BOOTP_BOOTPATH
> > +#define CONFIG_BOOTP_GATEWAY
> > +#define CONFIG_BOOTP_HOSTNAME
> > +#define CONFIG_BOOTP_PXE
> > +#define CONFIG_BOOTP_PXE_CLIENTARCH    0x100
> > +
> > +/* Initial environment variables */
> > +
> > +/*
> > + * Defines where the kernel and FDT exist in NOR flash and where it will
> > + * be copied into DRAM
> > + */
> > +#define CONFIG_EXTRA_ENV_SETTINGS      \
> > +                               "kernel_name=Image\0"   \
> > +                               "kernel_addr=0x0000000\0" \
> > +                               "fdt_name=hi6220-hikey.dtb\0" \
> > +                               "fdt_addr=0x0300000\0" \
> > +                               "max_fdt=0x100000\0" \
> > +                               "fdt_high=0xffffffffffffffff\0" \
> > +                               "initrd_high=0xffffffffffffffff\0" \
> > +
> > +/* Assume we boot with root on the first partition of a USB stick */
> > +#define CONFIG_BOOTARGS                "console=ttyAMA0,115200n8
> /dev/mmcblk0p7 rw "
> > +
> > +/* Copy the kernel and FDT to DRAM memory and boot */
> > +#define CONFIG_BOOTCOMMAND     "booti $kernel_addr_r - $fdt_addr_r"
> > +
> > +#define CONFIG_BOOTDELAY               2
> > +
> > +/* Preserve enviroment onto sd card */
> > +#define CONFIG_ENV_IS_IN_MMC
> > +#define CONFIG_SYS_MMC_ENV_DEV         1
> > +#define CONFIG_SYS_MMC_ENV_PART                0
> > +#define CONFIG_ENV_OFFSET               0x0
> > +#define CONFIG_ENV_SIZE                        0x1000
> > +#define CONFIG_ENV_OFFSET_REDUND        (CONFIG_ENV_OFFSET +
> CONFIG_ENV_SIZE)
> > +#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
>
> Looks like a typo here.
>

Surprisingly not, that is just what it is called.

>
> > +
> > +/* Monitor Command Prompt */
> > +#define CONFIG_SYS_CBSIZE              512     /* Console I/O Buffer
> Size */
> > +#define CONFIG_SYS_PROMPT              "HiKey64# "
>
> Do we really need a custom prompt?
>

No I guess not. It did bring a smile to my face the first time u-boot
booted on HiKey though :-) I will remove it in V2.

regards,

Peter.
Peter Griffin July 6, 2015, 11:50 a.m. UTC | #2
Hi Simon,

>
> > It has been tested with Arm Trusted Firmware running u-boot as the BL33
> executable.
>
> Are there instructions somewhere on how to do this? Perhaps add a
> README with details or a few links?
>

There are some slightly old instructions here
http://people.linaro.org/~peter.griffin/hikey/hikey-u-boot-release_r1/u-boot-readme.txt


>
> Are there instructions somewhere on how to do this? Perhaps add a
> README with details or a few links?
>

Yes good idea, I will include a README with the v2 patchset which includes
some of this info.


>
> >
> > Notes:
> >
> > eMMC has been tested with basic reading of eMMC partition intto DDR. I
> have not
> > tested writing / erasing. I suspect due to lack of clock control it
> won't be
> > running in the most performant high speed mode.
> >
> > SD card slot has been tested for reading and booting kernels into DDR.
> > It is also currently used for saving the u-boot enviroment.
> >
> > USB has been tested with ASIX networking adapter to tftpboot kernels
> > into DDR. USB mass storage device enumeration doesn't currently work for
> > an unkown reason.
> >
> > GPIO has been tested using gpio toggle GPIO4_1-3 to flash LEDs.
> >
> > Basic SoC datasheet can be found here: -
> > https://github.com/96boards/documentation/blob/master/hikey/
> > Hi6220V100_Multi-Mode_Application_Processor_Function_Description.pdf
> >
> > Board schematic can be found here: -
> > https://github.com/96boards/documentation/blob/master/hikey/
> > 96Boards-Hikey-Rev-A1.pdf
> >
> > Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
> > ---
> >  arch/arm/Kconfig                |   5 +
> >  board/96boards/hikey64/Kconfig  |  12 ++
> >  board/96boards/hikey64/Makefile |   8 +
> >  board/96boards/hikey64/hikey.c  | 439
> ++++++++++++++++++++++++++++++++++++++++
> >  configs/hikey_aemv8a_defconfig  |   5 +
> >  include/configs/hikey_aemv8a.h  | 187 +++++++++++++++++
> >  6 files changed, 656 insertions(+)
> >  create mode 100644 board/96boards/hikey64/Kconfig
> >  create mode 100644 board/96boards/hikey64/Makefile
> >  create mode 100644 board/96boards/hikey64/hikey.c
> >  create mode 100644 configs/hikey_aemv8a_defconfig
> >  create mode 100644 include/configs/hikey_aemv8a.h
> >
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 7ed0e20..0b6de5d 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -656,6 +656,10 @@ config TARGET_LS2085A_SIMU
> >         select ARM64
> >         select ARMV8_MULTIENTRY
> >
> > +config TARGET_96BOARDS_HIKEY
> > +       bool "Support HiKey 96boards Consumer Edition Platform"
> > +       select ARM64
> > +
> >  config TARGET_LS1021AQDS
> >         bool "Support ls1021aqds"
> >         select CPU_V7
> > @@ -787,6 +791,7 @@ source "board/armadeus/apf27/Kconfig"
> >  source "board/armltd/integrator/Kconfig"
> >  source "board/armltd/vexpress/Kconfig"
> >  source "board/armltd/vexpress64/Kconfig"
> > +source "board/96boards/hikey64/Kconfig"
> >  source "board/bachmann/ot1200/Kconfig"
> >  source "board/balloon3/Kconfig"
> >  source "board/barco/platinum/Kconfig"
> > diff --git a/board/96boards/hikey64/Kconfig
> b/board/96boards/hikey64/Kconfig
> > new file mode 100644
> > index 0000000..eb1709b
> > --- /dev/null
> > +++ b/board/96boards/hikey64/Kconfig
> > @@ -0,0 +1,12 @@
> > +if TARGET_96BOARDS_HIKEY
> > +
> > +config SYS_BOARD
> > +       default "hikey64"
> > +
> > +config SYS_VENDOR
> > +       default "96boards"
> > +
> > +config SYS_CONFIG_NAME
> > +       default "hikey_aemv8a"
> > +
> > +endif
> > diff --git a/board/96boards/hikey64/Makefile
> b/board/96boards/hikey64/Makefile
> > new file mode 100644
> > index 0000000..d4ec8c7
> > --- /dev/null
> > +++ b/board/96boards/hikey64/Makefile
> > @@ -0,0 +1,8 @@
> > +#
> > +# (C) Copyright 2000-2004
> > +# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
> > +#
> > +# SPDX-License-Identifier:     GPL-2.0+
> > +#
> > +
> > +obj-y  := hikey.o
> > diff --git a/board/96boards/hikey64/hikey.c
> b/board/96boards/hikey64/hikey.c
> > new file mode 100644
> > index 0000000..91e8e6b
> > --- /dev/null
> > +++ b/board/96boards/hikey64/hikey.c
> > @@ -0,0 +1,439 @@
> > +/*
> > + * (C) Copyright 2015 Linaro
> > + * Peter Griffin <peter.griffin@linaro.org>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <malloc.h>
> > +#include <errno.h>
> > +#include <netdev.h>
> > +#include <asm/io.h>
> > +#include <asm-generic/gpio.h>
> > +#include <asm/arch/gpio.h>
> > +#include <asm/arch/dwmmc.h>
> > +#include <asm/arch/hi6220.h>
> > +#include <asm/arch/hi6553.h>
> > +
> > +#ifdef CONFIG_DM_GPIO
> > +static const struct hikey_gpio_platdata hi6220_gpio[] = {
> > +       { 0, HI6220_GPIO0_BASE},
> > +       { 1, HI6220_GPIO1_BASE},
> > +       { 2, HI6220_GPIO2_BASE},
> > +       { 3, HI6220_GPIO3_BASE},
> > +       { 4, HI6220_GPIO4_BASE},
> > +       { 5, HI6220_GPIO5_BASE},
> > +       { 6, HI6220_GPIO6_BASE},
> > +       { 7, HI6220_GPIO7_BASE},
> > +       { 8, HI6220_GPIO8_BASE},
> > +       { 9, HI6220_GPIO9_BASE},
> > +       { 10, HI6220_GPIO10_BASE},
> > +       { 11, HI6220_GPIO11_BASE},
> > +       { 12, HI6220_GPIO12_BASE},
> > +       { 13, HI6220_GPIO13_BASE},
> > +       { 14, HI6220_GPIO14_BASE},
> > +       { 15, HI6220_GPIO15_BASE},
> > +       { 16, HI6220_GPIO16_BASE},
> > +       { 17, HI6220_GPIO17_BASE},
> > +       { 18, HI6220_GPIO18_BASE},
> > +       { 19, HI6220_GPIO19_BASE},
> > +
> > +};
> > +
> > +U_BOOT_DEVICES(hi6220_gpios) = {
> > +       { "gpio_hi6220", &hi6220_gpio[0] },
> > +       { "gpio_hi6220", &hi6220_gpio[1] },
> > +       { "gpio_hi6220", &hi6220_gpio[2] },
> > +       { "gpio_hi6220", &hi6220_gpio[3] },
> > +       { "gpio_hi6220", &hi6220_gpio[4] },
> > +       { "gpio_hi6220", &hi6220_gpio[5] },
> > +       { "gpio_hi6220", &hi6220_gpio[6] },
> > +       { "gpio_hi6220", &hi6220_gpio[7] },
> > +       { "gpio_hi6220", &hi6220_gpio[8] },
> > +       { "gpio_hi6220", &hi6220_gpio[9] },
> > +       { "gpio_hi6220", &hi6220_gpio[10] },
> > +       { "gpio_hi6220", &hi6220_gpio[11] },
> > +       { "gpio_hi6220", &hi6220_gpio[12] },
> > +       { "gpio_hi6220", &hi6220_gpio[13] },
> > +       { "gpio_hi6220", &hi6220_gpio[14] },
> > +       { "gpio_hi6220", &hi6220_gpio[15] },
> > +       { "gpio_hi6220", &hi6220_gpio[16] },
> > +       { "gpio_hi6220", &hi6220_gpio[17] },
> > +       { "gpio_hi6220", &hi6220_gpio[18] },
> > +       { "gpio_hi6220", &hi6220_gpio[19] },
> > +};
> > +#endif
>
> Can we use device tree for this board? I have just received one so if
> you don't have the time for this I could give it a try (once I figure
> out how to get U-Boot onto the board).
>

Do you mean using device tree for configuring u-boot? If so that would be a
useful addition. If you want to do it then please do :-)


>
> Also, do you know anything about the SDRAM controller? I don't see
> mention of it in the docs and we would need it to create an SPL for
> this board.
>

No I'm afraid not. The datasheet released so far is sadly rather sparse on
details.

There is some code in ATF for configuring ddr clocks which could be used
as a reference though see arm-trusted-firmware/plat/hikey/pll.c.

regards,

Peter.
diff mbox

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7ed0e20..0b6de5d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -656,6 +656,10 @@  config TARGET_LS2085A_SIMU
 	select ARM64
 	select ARMV8_MULTIENTRY
 
+config TARGET_96BOARDS_HIKEY
+	bool "Support HiKey 96boards Consumer Edition Platform"
+	select ARM64
+
 config TARGET_LS1021AQDS
 	bool "Support ls1021aqds"
 	select CPU_V7
@@ -787,6 +791,7 @@  source "board/armadeus/apf27/Kconfig"
 source "board/armltd/integrator/Kconfig"
 source "board/armltd/vexpress/Kconfig"
 source "board/armltd/vexpress64/Kconfig"
+source "board/96boards/hikey64/Kconfig"
 source "board/bachmann/ot1200/Kconfig"
 source "board/balloon3/Kconfig"
 source "board/barco/platinum/Kconfig"
diff --git a/board/96boards/hikey64/Kconfig b/board/96boards/hikey64/Kconfig
new file mode 100644
index 0000000..eb1709b
--- /dev/null
+++ b/board/96boards/hikey64/Kconfig
@@ -0,0 +1,12 @@ 
+if TARGET_96BOARDS_HIKEY
+
+config SYS_BOARD
+	default "hikey64"
+
+config SYS_VENDOR
+	default "96boards"
+
+config SYS_CONFIG_NAME
+	default "hikey_aemv8a"
+
+endif
diff --git a/board/96boards/hikey64/Makefile b/board/96boards/hikey64/Makefile
new file mode 100644
index 0000000..d4ec8c7
--- /dev/null
+++ b/board/96boards/hikey64/Makefile
@@ -0,0 +1,8 @@ 
+#
+# (C) Copyright 2000-2004
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= hikey.o
diff --git a/board/96boards/hikey64/hikey.c b/board/96boards/hikey64/hikey.c
new file mode 100644
index 0000000..91e8e6b
--- /dev/null
+++ b/board/96boards/hikey64/hikey.c
@@ -0,0 +1,439 @@ 
+/*
+ * (C) Copyright 2015 Linaro
+ * Peter Griffin <peter.griffin@linaro.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <errno.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm-generic/gpio.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/dwmmc.h>
+#include <asm/arch/hi6220.h>
+#include <asm/arch/hi6553.h>
+
+#ifdef CONFIG_DM_GPIO
+static const struct hikey_gpio_platdata hi6220_gpio[] = {
+	{ 0, HI6220_GPIO0_BASE},
+	{ 1, HI6220_GPIO1_BASE},
+	{ 2, HI6220_GPIO2_BASE},
+	{ 3, HI6220_GPIO3_BASE},
+	{ 4, HI6220_GPIO4_BASE},
+	{ 5, HI6220_GPIO5_BASE},
+	{ 6, HI6220_GPIO6_BASE},
+	{ 7, HI6220_GPIO7_BASE},
+	{ 8, HI6220_GPIO8_BASE},
+	{ 9, HI6220_GPIO9_BASE},
+	{ 10, HI6220_GPIO10_BASE},
+	{ 11, HI6220_GPIO11_BASE},
+	{ 12, HI6220_GPIO12_BASE},
+	{ 13, HI6220_GPIO13_BASE},
+	{ 14, HI6220_GPIO14_BASE},
+	{ 15, HI6220_GPIO15_BASE},
+	{ 16, HI6220_GPIO16_BASE},
+	{ 17, HI6220_GPIO17_BASE},
+	{ 18, HI6220_GPIO18_BASE},
+	{ 19, HI6220_GPIO19_BASE},
+
+};
+
+U_BOOT_DEVICES(hi6220_gpios) = {
+	{ "gpio_hi6220", &hi6220_gpio[0] },
+	{ "gpio_hi6220", &hi6220_gpio[1] },
+	{ "gpio_hi6220", &hi6220_gpio[2] },
+	{ "gpio_hi6220", &hi6220_gpio[3] },
+	{ "gpio_hi6220", &hi6220_gpio[4] },
+	{ "gpio_hi6220", &hi6220_gpio[5] },
+	{ "gpio_hi6220", &hi6220_gpio[6] },
+	{ "gpio_hi6220", &hi6220_gpio[7] },
+	{ "gpio_hi6220", &hi6220_gpio[8] },
+	{ "gpio_hi6220", &hi6220_gpio[9] },
+	{ "gpio_hi6220", &hi6220_gpio[10] },
+	{ "gpio_hi6220", &hi6220_gpio[11] },
+	{ "gpio_hi6220", &hi6220_gpio[12] },
+	{ "gpio_hi6220", &hi6220_gpio[13] },
+	{ "gpio_hi6220", &hi6220_gpio[14] },
+	{ "gpio_hi6220", &hi6220_gpio[15] },
+	{ "gpio_hi6220", &hi6220_gpio[16] },
+	{ "gpio_hi6220", &hi6220_gpio[17] },
+	{ "gpio_hi6220", &hi6220_gpio[18] },
+	{ "gpio_hi6220", &hi6220_gpio[19] },
+};
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_SHOW_BOOT_PROGRESS)
+void show_boot_progress(int progress)
+{
+	printf("Boot reached stage %d\n", progress);
+}
+#endif
+
+static inline void delay(ulong loops)
+{
+	__asm__ volatile ("1:\n"
+		"subs %0, %1, #1\n"
+		"bne 1b" : "=r" (loops) : "0" (loops));
+}
+
+
+#define EYE_PATTERN	0x70533483
+
+static void init_usb_and_picophy(void)
+{
+	unsigned int data;
+
+	/* enable USB clock */
+	writel(PERI_CLK0_USBOTG, PERI_SC_PERIPH_CLK0_EN);
+	do {
+		data = readl(PERI_SC_PERIPH_CLK0_STAT);
+	} while ((data & PERI_CLK0_USBOTG) == 0);
+
+	/* take usb IPs out of reset */
+	writel(PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
+		PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K,
+		PERI_SC_PERIPH_RST0_DIS);
+	do {
+		data = readl(PERI_SC_PERIPH_RST0_STAT);
+		data &= PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
+			PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K;
+	} while (data);
+
+	/*CTRL 5*/
+	data = readl(PERI_SC_PERIPH_CTRL5);
+	data &= ~PERI_CTRL5_PICOPHY_BC_MODE;
+	data |= PERI_CTRL5_USBOTG_RES_SEL | PERI_CTRL5_PICOPHY_ACAENB;
+	data |= 0x300;
+	writel(data, PERI_SC_PERIPH_CTRL5);
+
+	/*CTRL 4*/
+
+	/* configure USB PHY */
+	data = readl(PERI_SC_PERIPH_CTRL4);
+
+	/* make PHY out of low power mode */
+	data &= ~PERI_CTRL4_PICO_SIDDQ;
+	data &= ~PERI_CTRL4_PICO_OGDISABLE;
+	data |= PERI_CTRL4_PICO_VBUSVLDEXTSEL | PERI_CTRL4_PICO_VBUSVLDEXT;
+	writel(data, PERI_SC_PERIPH_CTRL4);
+
+	writel(EYE_PATTERN, PERI_SC_PERIPH_CTRL8);
+
+	delay(20000);
+}
+
+static int sd_card_detect(void)
+{
+	int ret;
+
+	/* configure GPIO8 as nopull */
+	writel(0, 0xf8001830);
+
+	gpio_request(8, "SD CD");
+
+	gpio_direction_input(8);
+	ret = gpio_get_value(8);
+
+	if (!ret) {
+		printf("%s: SD card present\n", __func__);
+		return 1;
+	}
+
+	printf("%s: SD card not present\n", __func__);
+	return 0;
+}
+
+static void mmc1_setup_pinmux(void)
+{
+	/* switch pinmux to SD */
+	writel(0, 0xf701000c);
+	writel(0, 0xf7010010);
+	writel(0, 0xf7010014);
+	writel(0, 0xf7010018);
+	writel(0, 0xf701001c);
+	writel(0, 0xf7010020);
+
+	/* input, 16mA or 12mA */
+	writel(0x64, 0xf701080c);
+	writel(0x54, 0xf7010810);
+	writel(0x54, 0xf7010814);
+	writel(0x54, 0xf7010818);
+	writel(0x54, 0xf701081c);
+	writel(0x54, 0xf7010820);
+
+	sd_card_detect();
+}
+
+static void mmc1_init_pll(void)
+{
+	uint32_t data;
+
+	/* select SYSPLL as the source of MMC1 */
+	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
+	writel(1 << 11 | 1 << 27, PERI_SC_CLK0_SEL);
+	do {
+		data = readl(PERI_SC_CLK0_SEL);
+	} while (!(data & (1 << 11)));
+
+	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
+	writel(1 << 30, PERI_SC_CLK0_SEL);
+	do {
+		data = readl(PERI_SC_CLK0_SEL);
+	} while (data & (1 << 14));
+
+	writel((1 << 1), PERI_SC_PERIPH_CLK0_EN);
+	do {
+		data = readl(PERI_SC_PERIPH_CLK0_STAT);
+	} while (!(data & (1 << 1)));
+
+	data = readl(PERI_SC_PERIPH_CLK12_EN);
+	data |= 1 << 2;
+	writel(data, PERI_SC_PERIPH_CLK12_EN);
+
+	do {
+		/* 1.2GHz / 50 = 24MHz */
+		writel(0x31 | (1 << 7), PERI_SC_CLKCFG8BIT2);
+		data = readl(PERI_SC_CLKCFG8BIT2);
+	} while ((data & 0x31) != 0x31);
+}
+
+static void mmc1_reset_clk(void)
+{
+	unsigned int data;
+
+	/* disable mmc1 bus clock */
+	writel(PERI_CLK0_MMC1, PERI_SC_PERIPH_CLK0_DIS);
+	do {
+		data = readl(PERI_SC_PERIPH_CLK0_STAT);
+	} while (data & PERI_CLK0_MMC1);
+
+	/* enable mmc1 bus clock */
+	writel(PERI_CLK0_MMC1, PERI_SC_PERIPH_CLK0_EN);
+	do {
+		data = readl(PERI_SC_PERIPH_CLK0_STAT);
+	} while (!(data & PERI_CLK0_MMC1));
+
+	/* reset mmc1 clock domain */
+	writel(PERI_RST0_MMC1, PERI_SC_PERIPH_RST0_EN);
+
+	/* bypass mmc1 clock phase */
+	data = readl(PERI_SC_PERIPH_CTRL2);
+	data |= 3 << 2;
+	writel(data, PERI_SC_PERIPH_CTRL2);
+
+	/* disable low power */
+	data = readl(PERI_SC_PERIPH_CTRL13);
+	data |= 1 << 4;
+	writel(data, PERI_SC_PERIPH_CTRL13);
+	do {
+		data = readl(PERI_SC_PERIPH_RST0_STAT);
+	} while (!(data & PERI_RST0_MMC1));
+
+	/* unreset mmc0 clock domain */
+	writel(PERI_RST0_MMC1, PERI_SC_PERIPH_RST0_DIS);
+	do {
+		data = readl(PERI_SC_PERIPH_RST0_STAT);
+	} while (data & PERI_RST0_MMC1);
+}
+
+/* PMU SSI is the IP that maps the external PMU hi6553 registers as IO */
+static void hi6220_pmussi_init(void)
+{
+	uint32_t data;
+
+	/* Take PMUSSI out of reset */
+	writel(ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N,
+	       ALWAYSON_SC_PERIPH_RST4_DIS);
+	do {
+		data = readl(ALWAYSON_SC_PERIPH_RST4_STAT);
+	} while (data & ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N);
+
+	/* set PMU SSI clock latency for read operation */
+	data = readl(ALWAYSON_SC_MCU_SUBSYS_CTRL3);
+	data &= ~ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
+	data |= ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_3;
+	writel(data, ALWAYSON_SC_MCU_SUBSYS_CTRL3);
+
+	/* enable PMUSSI clock */
+	data = ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_CCPU |
+	       ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_MCU;
+	writel(data, ALWAYSON_SC_PERIPH_CLK5_EN);
+	data = ALWAYSON_SC_PERIPH_CLK4_EN_PCLK_PMUSSI;
+	writel(data, ALWAYSON_SC_PERIPH_CLK4_EN);
+
+	/* Output high to PMIC on PWR_HOLD_GPIO0_0 */
+	gpio_request(0, "PWR_HOLD_GPIO0_0");
+	gpio_direction_output(0, 1);
+}
+
+uint8_t hi6553_readb(unsigned int offset)
+{
+	return readb((u8 *)(unsigned long)HI6220_PMUSSI_BASE + (offset << 2));
+}
+
+void hi6553_writeb(unsigned int offset, uint8_t value)
+{
+	writeb(value, (u8 *)(unsigned long)HI6220_PMUSSI_BASE + (offset << 2));
+}
+
+static void hikey_hi6553_init(void)
+{
+	int data;
+
+	hi6553_writeb(HI6553_PERI_EN_MARK, 0x1e);
+	hi6553_writeb(HI6553_NP_REG_ADJ1, 0);
+	data = HI6553_DISABLE6_XO_CLK_CONN | HI6553_DISABLE6_XO_CLK_NFC |
+		HI6553_DISABLE6_XO_CLK_RF1 | HI6553_DISABLE6_XO_CLK_RF2;
+	hi6553_writeb(HI6553_DISABLE6_XO_CLK, data);
+
+	/* configure BUCK0 & BUCK1 */
+	hi6553_writeb(HI6553_BUCK01_CTRL2, 0x5e);
+	hi6553_writeb(HI6553_BUCK0_CTRL7, 0x10);
+	hi6553_writeb(HI6553_BUCK1_CTRL7, 0x10);
+	hi6553_writeb(HI6553_BUCK0_CTRL5, 0x1e);
+	hi6553_writeb(HI6553_BUCK1_CTRL5, 0x1e);
+	hi6553_writeb(HI6553_BUCK0_CTRL1, 0xfc);
+	hi6553_writeb(HI6553_BUCK1_CTRL1, 0xfc);
+
+	/* configure BUCK2 */
+	hi6553_writeb(HI6553_BUCK2_REG1, 0x4f);
+	hi6553_writeb(HI6553_BUCK2_REG5, 0x99);
+	hi6553_writeb(HI6553_BUCK2_REG6, 0x45);
+	mdelay(1);
+	hi6553_writeb(HI6553_VSET_BUCK2_ADJ, 0x22);
+	mdelay(1);
+
+	/* configure BUCK3 */
+	hi6553_writeb(HI6553_BUCK3_REG3, 0x02);
+	hi6553_writeb(HI6553_BUCK3_REG5, 0x99);
+	hi6553_writeb(HI6553_BUCK3_REG6, 0x41);
+	hi6553_writeb(HI6553_VSET_BUCK3_ADJ, 0x02);
+	mdelay(1);
+
+	/* configure BUCK4 */
+	hi6553_writeb(HI6553_BUCK4_REG2, 0x9a);
+	hi6553_writeb(HI6553_BUCK4_REG5, 0x99);
+	hi6553_writeb(HI6553_BUCK4_REG6, 0x45);
+
+	/* configure LDO20 */
+	hi6553_writeb(HI6553_LDO20_REG_ADJ, 0x50);
+
+	hi6553_writeb(HI6553_NP_REG_CHG, 0x0f);
+	hi6553_writeb(HI6553_CLK_TOP0, 0x06);
+	hi6553_writeb(HI6553_CLK_TOP3, 0xc0);
+	hi6553_writeb(HI6553_CLK_TOP4, 0x00);
+
+	/* configure LDO7 & LDO10 for SD slot */
+	data = hi6553_readb(HI6553_LDO7_REG_ADJ);
+	data = (data & 0xf8) | 0x2;
+	hi6553_writeb(HI6553_LDO7_REG_ADJ, data);
+	mdelay(5);
+	/* enable LDO7 */
+	hi6553_writeb(HI6553_ENABLE2_LDO1_8, 1 << 6);
+	mdelay(5);
+	data = hi6553_readb(HI6553_LDO10_REG_ADJ);
+	data = (data & 0xf8) | 0x5;
+	hi6553_writeb(HI6553_LDO10_REG_ADJ, data);
+	mdelay(5);
+	/* enable LDO10 */
+	hi6553_writeb(HI6553_ENABLE3_LDO9_16, 1 << 1);
+	mdelay(5);
+
+	/* select 32.764KHz */
+	hi6553_writeb(HI6553_CLK19M2_600_586_EN, 0x01);
+}
+
+/*
+ * Routine: misc_init_r
+ * Description: A basic misc_init_r
+ */
+int __weak misc_init_r(void)
+{
+	init_usb_and_picophy();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
+	gd->flags = 0;
+
+	icache_enable();
+
+	return 0;
+}
+
+#ifdef CONFIG_GENERIC_MMC
+
+static int init_dwmmc(void)
+{
+	int ret;
+
+#ifdef CONFIG_DWMMC
+
+
+	/* mmc0 pinmux and clocks are already configured by ATF */
+	ret = hi6220_dwmci_add_port(0, HI6220_MMC0_BASE, 8);
+
+	if (ret)
+		printf("%s: Error adding eMMC port\n", __func__);
+
+	/* take mmc1 (sd slot) out of reset, configure clocks and pinmuxing */
+
+	mmc1_init_pll();
+	mmc1_reset_clk();
+	mmc1_setup_pinmux();
+
+	ret |= hi6220_dwmci_add_port(1, HI6220_MMC1_BASE, 4);
+
+	if (ret)
+		printf("%s: Error adding SD port\n", __func__);
+#endif
+	return ret;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	int ret;
+
+	/* init the pmussi ip */
+	hi6220_pmussi_init();
+
+	/* init the hi6553 pmic */
+	hikey_hi6553_init();
+
+	/* add the eMMC and sd ports */
+	ret = init_dwmmc();
+
+	if (ret)
+		debug("init_dwmmc failed\n");
+
+	return ret;
+}
+#endif
+
+int dram_init(void)
+{
+	gd->ram_size =
+		get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, PHYS_SDRAM_1_SIZE);
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
+	gd->bd->bi_dram[0].size =
+			get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
+}
+
+/* Use the Watchdog to cause reset */
+void reset_cpu(ulong addr)
+{
+	/* TODO program the watchdog */
+}
diff --git a/configs/hikey_aemv8a_defconfig b/configs/hikey_aemv8a_defconfig
new file mode 100644
index 0000000..3bbb2c5
--- /dev/null
+++ b/configs/hikey_aemv8a_defconfig
@@ -0,0 +1,5 @@ 
+# 96boards HiKey
+CONFIG_ARM=y
+CONFIG_TARGET_96BOARDS_HIKEY=y
+CONFIG_DEFAULT_DEVICE_TREE="hikey"
+CONFIG_SHOW_BOOT_PROGRESS=y
diff --git a/include/configs/hikey_aemv8a.h b/include/configs/hikey_aemv8a.h
new file mode 100644
index 0000000..7c0012f
--- /dev/null
+++ b/include/configs/hikey_aemv8a.h
@@ -0,0 +1,187 @@ 
+/*
+ * (C) Copyright 2015 Linaro
+ *
+ * Peter Griffin <peter.griffin@linaro.org>
+ *
+ * Configuration for HiKey 96boards CE. Parts were derived from other ARM
+ * configurations.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __HIKEY_AEMV8A_H
+#define __HIKEY_AEMV8A_H
+
+/* We use generic board for hikey */
+#define CONFIG_SYS_GENERIC_BOARD
+
+#define CONFIG_REMAKE_ELF
+
+#define CONFIG_SUPPORT_RAW_INITRD
+
+/* Cache Definitions */
+#define CONFIG_SYS_DCACHE_OFF
+#define CONFIG_SYS_ICACHE_OFF
+
+#define CONFIG_IDENT_STRING		" hikey_aemv8a"
+#define CONFIG_BOOTP_VCI_STRING		"U-boot.armv8.hikey_aemv8a"
+
+/* Flat Device Tree Definitions */
+#define CONFIG_OF_LIBFDT
+
+/* Physical Memory Map */
+
+#define CONFIG_SYS_TEXT_BASE		0x37000000
+/* RAM debug builds */
+/*#define CONFIG_SYS_TEXT_BASE		0x27000000*/
+
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM_1			0x00000000
+#define PHYS_SDRAM_1_SIZE		0x40000000	/* 1024 MB */
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM_1
+
+#define CONFIG_SYS_INIT_RAM_SIZE	0x1000
+
+#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_SDRAM_BASE + 0x7fff0)
+
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x8000)
+#define LINUX_BOOT_PARAM_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x2000)
+
+/* Generic Timer Definitions */
+#define COUNTER_FREQUENCY              (0x1300000)     /* 19MHz */
+
+/* Generic Interrupt Controller Definitions */
+#define GICD_BASE			(0xf6801000)
+#define GICC_BASE			(0xf6802000)
+
+#define CONFIG_SYS_MEMTEST_START	V2M_BASE
+#define CONFIG_SYS_MEMTEST_END		(V2M_BASE + 0x40000000)
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (8 << 20))
+
+/* PL011 Serial Configuration */
+#define CONFIG_PL011_SERIAL
+
+#define CONFIG_PL011_CLOCK		19200000
+#define CONFIG_PL01x_PORTS		{(void *)CONFIG_SYS_SERIAL0}
+#define CONFIG_CONS_INDEX		0
+
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_SERIAL0		0xF8015000
+
+#define CONFIG_CMD_USB
+#ifdef CONFIG_CMD_USB
+#define CONFIG_USB_DWC2
+#define CONFIG_USB_DWC2_REG_ADDR 0xF72C0000
+/*#define CONFIG_DWC2_DFLT_SPEED_FULL*/
+#define CONFIG_DWC2_ENABLE_DYNAMIC_FIFO
+
+#define CONFIG_USB_STORAGE
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_SMSC95XX
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_MISC_INIT_R
+#endif
+
+#define CONFIG_HIKEY_GPIO
+#define CONFIG_DM_GPIO
+#define CONFIG_CMD_GPIO
+#define CONFIG_DM
+
+/* SD/MMC configuration */
+#define CONFIG_GENERIC_MMC
+#define CONFIG_MMC
+#define CONFIG_DWMMC
+#define CONFIG_HIKEY_DWMMC
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_CMD_MMC
+
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
+
+/* Command line configuration */
+#define CONFIG_MENU
+/*#define CONFIG_MENU_SHOW*/
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_BOOTI
+#define CONFIG_CMD_UNZIP
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_PXE
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_IMI
+#define CONFIG_CMD_LOADB
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SAVEENV
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_ECHO
+#define CONFIG_CMD_SOURCE
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_FS_GENERIC
+
+#define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_MTD_PARTITIONS
+
+/* BOOTP options */
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+#define CONFIG_BOOTP_PXE
+#define CONFIG_BOOTP_PXE_CLIENTARCH	0x100
+
+/* Initial environment variables */
+
+/*
+ * Defines where the kernel and FDT exist in NOR flash and where it will
+ * be copied into DRAM
+ */
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+				"kernel_name=Image\0"	\
+				"kernel_addr=0x0000000\0" \
+				"fdt_name=hi6220-hikey.dtb\0" \
+				"fdt_addr=0x0300000\0" \
+				"max_fdt=0x100000\0" \
+				"fdt_high=0xffffffffffffffff\0" \
+				"initrd_high=0xffffffffffffffff\0" \
+
+/* Assume we boot with root on the first partition of a USB stick */
+#define CONFIG_BOOTARGS		"console=ttyAMA0,115200n8 /dev/mmcblk0p7 rw "
+
+/* Copy the kernel and FDT to DRAM memory and boot */
+#define CONFIG_BOOTCOMMAND	"booti $kernel_addr_r - $fdt_addr_r"
+
+#define CONFIG_BOOTDELAY		2
+
+/* Preserve enviroment onto sd card */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV		1
+#define CONFIG_SYS_MMC_ENV_PART		0
+#define CONFIG_ENV_OFFSET               0x0
+#define CONFIG_ENV_SIZE			0x1000
+#define CONFIG_ENV_OFFSET_REDUND        (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+
+/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE		512	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PROMPT		"HiKey64# "
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_HUSH_PARSER
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_MAXARGS		64	/* max command args */
+
+#define CONFIG_SYS_NO_FLASH
+
+#endif /* __HIKEY_AEMV8A_H */