diff mbox

[U-Boot,v2,5/6] ARM64: hikey: hi6220: Add u-boot support for the 96boards CE HiKey board.

Message ID 1436371040-26620-6-git-send-email-peter.griffin@linaro.org
State Superseded
Delegated to: Tom Rini
Headers show

Commit Message

Peter Griffin July 8, 2015, 3:57 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. 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. On v2015.07-rc2 dhcp now works, and also usb mass storage
is enumerated correctly.

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               |   8 +
 board/hisilicon/hikey/Kconfig  |  15 ++
 board/hisilicon/hikey/Makefile |   8 +
 board/hisilicon/hikey/hikey.c  | 415 +++++++++++++++++++++++++++++++++++++++++
 configs/hikey_defconfig        |   5 +
 include/configs/hikey.h        | 168 +++++++++++++++++
 6 files changed, 619 insertions(+)
 create mode 100644 board/hisilicon/hikey/Kconfig
 create mode 100644 board/hisilicon/hikey/Makefile
 create mode 100644 board/hisilicon/hikey/hikey.c
 create mode 100644 configs/hikey_defconfig
 create mode 100644 include/configs/hikey.h

Comments

Rob Herring July 10, 2015, 6:36 p.m. UTC | #1
On Wed, Jul 8, 2015 at 10:57 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.
>
> This initial port adds support for: -
> 1) Serial
> 2) eMMC / sd card

s/sd/SD/

> 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

s/intto/into/

> tested writing / erasing. 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.

s/enviroment/environment/

> USB has been tested with ASIX networking adapter to tftpboot kernels
> into DDR. On v2015.07-rc2 dhcp now works, and also usb mass storage

s/usb/USB/

> is enumerated correctly.
>
> 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               |   8 +
>  board/hisilicon/hikey/Kconfig  |  15 ++
>  board/hisilicon/hikey/Makefile |   8 +
>  board/hisilicon/hikey/hikey.c  | 415 +++++++++++++++++++++++++++++++++++++++++
>  configs/hikey_defconfig        |   5 +
>  include/configs/hikey.h        | 168 +++++++++++++++++
>  6 files changed, 619 insertions(+)
>  create mode 100644 board/hisilicon/hikey/Kconfig
>  create mode 100644 board/hisilicon/hikey/Makefile
>  create mode 100644 board/hisilicon/hikey/hikey.c
>  create mode 100644 configs/hikey_defconfig
>  create mode 100644 include/configs/hikey.h

[...]

> +
> +int misc_init_r(void)
> +{
> +       init_usb_and_picophy();

Can board_usb_init or usb_lowlevel_init be used here?

> +
> +       return 0;
> +}
> +
> +int board_init(void)
> +{
> +       gd->flags = 0;
> +
> +       icache_enable();

The enable_caches call in board_r.c should do this for you.

> +
> +       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 = 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 = PHYS_SDRAM_1_SIZE;
> +}
> +
> +/* Use the Watchdog to cause reset */
> +void reset_cpu(ulong addr)
> +{
> +       /* TODO program the watchdog */
> +}
> diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
> new file mode 100644
> index 0000000..50baf22
> --- /dev/null
> +++ b/configs/hikey_defconfig
> @@ -0,0 +1,5 @@
> +# 96boards HiKey
> +CONFIG_ARM=y
> +CONFIG_TARGET_HIKEY=y
> +CONFIG_SHOW_BOOT_PROGRESS=y
> +CONFIG_NET=y
> diff --git a/include/configs/hikey.h b/include/configs/hikey.h
> new file mode 100644
> index 0000000..303b857
> --- /dev/null
> +++ b/include/configs/hikey.h
> @@ -0,0 +1,168 @@
> +/*
> + * (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

Drop the AEMV8A.

> +
> +/* 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_IDENT_STRING            "hikey"
> +
> +/* Flat Device Tree Definitions */
> +#define CONFIG_OF_LIBFDT
> +
> +/* Physical Memory Map */
> +
> +/* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */
> +#define CONFIG_SYS_TEXT_BASE           0x35000000
> +
> +#define CONFIG_NR_DRAM_BANKS           1
> +#define PHYS_SDRAM_1                   0x00000000
> +
> +/* 1008 MB (the last 16Mb are secured for TrustZone by ATF*/
> +#define PHYS_SDRAM_1_SIZE              0x3f000000
> +#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 + 0x80000)
> +
> +/* Generic Timer Definitions */
> +#define COUNTER_FREQUENCY              (19000000)
> +
> +/* Generic Interrupt Controller Definitions */
> +#define GICD_BASE                      (0xf6801000)
> +#define GICC_BASE                      (0xf6802000)
> +
> +/* 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

Just do:

#define CONFIG_PL01x_PORTS             {(void *)0xf8015000}

You are probably going to want to setup multiple serial consoles
(debug + LS header). That can come later, but I've figured out how to
enable that if you are interested.

> +
> +#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

distro config should set this.

> +
> +/* Command line configuration */
> +#define CONFIG_MENU
> +#define CONFIG_CMD_CACHE
> +#define CONFIG_CMD_BDI
> +#define CONFIG_CMD_UNZIP
> +#define CONFIG_CMD_PXE

and this.

> +#define CONFIG_CMD_ENV
> +#define CONFIG_CMD_IMI
> +#define CONFIG_CMD_LOADB
> +#define CONFIG_CMD_MEMORY
> +#define CONFIG_CMD_SAVEENV
> +#define CONFIG_CMD_RUN
> +#define CONFIG_CMD_BOOTD
> +#define CONFIG_CMD_ECHO
> +#define CONFIG_CMD_SOURCE
> +
> +#define CONFIG_MAC_PARTITION

Supporting Mac partitions, really?

> +#define CONFIG_MTD_PARTITIONS

On what MTD device?

> +
> +/* BOOTP options */
> +#define CONFIG_BOOTP_BOOTFILESIZE
> +
> +#define CONFIG_CMD_NET
> +
> +#include <config_distro_defaults.h>
> +
> +/* 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" \

Shouldn't this be 0x80000 to avoid copying from 0x0 to 0x80000.

> +                               "fdt_name=hi6220-hikey.dtb\0" \
> +                               "fdt_addr=0x0300000\0" \
> +                               "max_fdt=0x100000\0" \

I don't think this is needed.

> +                               "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 "

/dev/mmcblk0p7 doesn't look right. You mean "root=/dev/..."?

> +
> +/* Copy the kernel and FDT to DRAM memory and boot */
> +#define CONFIG_BOOTCOMMAND     "booti $kernel_addr_r - $fdt_addr_r"

Don't you need to set these variables?

Also, don't you need to load the kernel and dtb first?

> +
> +#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

Don't you have these reversed? The first MMC device is 0 and I think
partition numbering starts at 1.

> +#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

Is redundant env necessary? It seems like this was more for raw NAND
and shouldn't really be needed for MMC.

Rob
Peter Griffin July 16, 2015, 12:41 a.m. UTC | #2
Hi Rob,

On Fri, 10 Jul 2015, Rob Herring wrote:

> On Wed, Jul 8, 2015 at 10:57 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.
> >
> > This initial port adds support for: -
> > 1) Serial
> > 2) eMMC / sd card
> 
> s/sd/SD/

Will fix in v3

> 
> > 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
> 
> s/intto/into/

Will fix in v3

> 
> > tested writing / erasing. 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.
> 
> s/enviroment/environment/

Will fix in v3.

> 
> > USB has been tested with ASIX networking adapter to tftpboot kernels
> > into DDR. On v2015.07-rc2 dhcp now works, and also usb mass storage
> 
> s/usb/USB/

Will fix in v3
> 
> > is enumerated correctly.
> >
> > 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               |   8 +
> >  board/hisilicon/hikey/Kconfig  |  15 ++
> >  board/hisilicon/hikey/Makefile |   8 +
> >  board/hisilicon/hikey/hikey.c  | 415 +++++++++++++++++++++++++++++++++++++++++
> >  configs/hikey_defconfig        |   5 +
> >  include/configs/hikey.h        | 168 +++++++++++++++++
> >  6 files changed, 619 insertions(+)
> >  create mode 100644 board/hisilicon/hikey/Kconfig
> >  create mode 100644 board/hisilicon/hikey/Makefile
> >  create mode 100644 board/hisilicon/hikey/hikey.c
> >  create mode 100644 configs/hikey_defconfig
> >  create mode 100644 include/configs/hikey.h
> 
> [...]
> 
> > +
> > +int misc_init_r(void)
> > +{
> > +       init_usb_and_picophy();
> 
> Can board_usb_init or usb_lowlevel_init be used here?

Umm I wasn't aware of those functions. It looks like usb_lowlevel_init() is used 
by the host controller driver. Other host controllers like ohci / ehci and xhci call
board_usb_init() from their usb_lowlevel_init function, but not dwc2.

So I can make use of board_usb_init() if I update dwc2.c generic code to call it
from usb_lowlevel_init(). I'll do this in V3 and hopefully nobody has any objections.

> 
> > +
> > +       return 0;
> > +}
> > +
> > +int board_init(void)
> > +{
> > +       gd->flags = 0;
> > +
> > +       icache_enable();
> 
> The enable_caches call in board_r.c should do this for you.

Ok, will remove in v3.

> 
> > +
> > +       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 = 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 = PHYS_SDRAM_1_SIZE;
> > +}
> > +
> > +/* Use the Watchdog to cause reset */
> > +void reset_cpu(ulong addr)
> > +{
> > +       /* TODO program the watchdog */
> > +}
> > diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
> > new file mode 100644
> > index 0000000..50baf22
> > --- /dev/null
> > +++ b/configs/hikey_defconfig
> > @@ -0,0 +1,5 @@
> > +# 96boards HiKey
> > +CONFIG_ARM=y
> > +CONFIG_TARGET_HIKEY=y
> > +CONFIG_SHOW_BOOT_PROGRESS=y
> > +CONFIG_NET=y
> > diff --git a/include/configs/hikey.h b/include/configs/hikey.h
> > new file mode 100644
> > index 0000000..303b857
> > --- /dev/null
> > +++ b/include/configs/hikey.h
> > @@ -0,0 +1,168 @@
> > +/*
> > + * (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
> 
> Drop the AEMV8A.

Ah, I thought I'd got rid of all that, but cleary missed this one.
Will remove in V3

> 
> > +
> > +/* 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_IDENT_STRING            "hikey"
> > +
> > +/* Flat Device Tree Definitions */
> > +#define CONFIG_OF_LIBFDT
> > +
> > +/* Physical Memory Map */
> > +
> > +/* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */
> > +#define CONFIG_SYS_TEXT_BASE           0x35000000
> > +
> > +#define CONFIG_NR_DRAM_BANKS           1
> > +#define PHYS_SDRAM_1                   0x00000000
> > +
> > +/* 1008 MB (the last 16Mb are secured for TrustZone by ATF*/
> > +#define PHYS_SDRAM_1_SIZE              0x3f000000
> > +#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 + 0x80000)
> > +
> > +/* Generic Timer Definitions */
> > +#define COUNTER_FREQUENCY              (19000000)
> > +
> > +/* Generic Interrupt Controller Definitions */
> > +#define GICD_BASE                      (0xf6801000)
> > +#define GICC_BASE                      (0xf6802000)
> > +
> > +/* 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
> 
> Just do:
> 
> #define CONFIG_PL01x_PORTS             {(void *)0xf8015000}

Ok, fixed in V3

> 
> You are probably going to want to setup multiple serial consoles
> (debug + LS header). That can come later, but I've figured out how to
> enable that if you are interested.

Yes I'm interested, please do let me know :)

> 
> > +
> > +#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
> 
> distro config should set this.

Ah ok, indirectly yes, as distro_config sets CONFIG_CMD_FAT, and if that is set
config_fallbacks.h will enable CONFIG_FS_FAT.

I've removed both CONFIG_FS_FAT and CONFIG_FS_EXT4 in v3

> 
> > +
> > +/* Command line configuration */
> > +#define CONFIG_MENU
> > +#define CONFIG_CMD_CACHE
> > +#define CONFIG_CMD_BDI
> > +#define CONFIG_CMD_UNZIP
> > +#define CONFIG_CMD_PXE
> 
> and this.

Whoops, missed this one. I've removed in V3

> 
> > +#define CONFIG_CMD_ENV
> > +#define CONFIG_CMD_IMI
> > +#define CONFIG_CMD_LOADB
> > +#define CONFIG_CMD_MEMORY
> > +#define CONFIG_CMD_SAVEENV
> > +#define CONFIG_CMD_RUN
> > +#define CONFIG_CMD_BOOTD
> > +#define CONFIG_CMD_ECHO
> > +#define CONFIG_CMD_SOURCE
> > +
> > +#define CONFIG_MAC_PARTITION
> 
> Supporting Mac partitions, really?

Will remove in V3. It doesn't look like I can blame that on
vexpress either, so I must have thought it was a good idea ;)

 
> > +#define CONFIG_MTD_PARTITIONS
> 
> On what MTD device?

Good point, Will remove in v3.

> 
> > +
> > +/* BOOTP options */
> > +#define CONFIG_BOOTP_BOOTFILESIZE
> > +
> > +#define CONFIG_CMD_NET
> > +
> > +#include <config_distro_defaults.h>
> > +
> > +/* 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" \
> 
> Shouldn't this be 0x80000 to avoid copying from 0x0 to 0x80000.

I've updated this. Kernel boot time is much reduced with this and also the
icache being enabled.

> 
> > +                               "fdt_name=hi6220-hikey.dtb\0" \
> > +                               "fdt_addr=0x0300000\0" \
> > +                               "max_fdt=0x100000\0" \
> 
> I don't think this is needed.

Removed in V3
> 
> > +                               "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 "
> 
> /dev/mmcblk0p7 doesn't look right. You mean "root=/dev/..."?

Good spot, yes your right. Plus now you highlight it the comment above also needs updating.

Will fix in V3.

> 
> > +
> > +/* Copy the kernel and FDT to DRAM memory and boot */
> > +#define CONFIG_BOOTCOMMAND     "booti $kernel_addr_r - $fdt_addr_r"
> 
> Don't you need to set these variables?
> 
> Also, don't you need to load the kernel and dtb first?

Yes, but I'm not sure quite what to make the default here. My personal
workflow is: -

 "usb start; dhcp; tftp $kernel_addr $kernel_name; tftp $fdt_addr $fdt_name;
   booti $kernel_addr - $fdt_addr"

So I could use that unless you have a better idea?

> 
> > +
> > +#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
> 
> Don't you have these reversed? The first MMC device is 0 and I think
> partition numbering starts at 1.

Having CONFIG_SYS_MMC_ENV_DEV 1 was deliberate, as the first device is eMMC, and 
I don't have a "official" partition to save the u-boot enviroment in.
So as not to corrupt anything folks may have flashed into eMMC from the official
builds I opted to save the u-boot env to SD card which is device 1.

However that seems to have been working by luck with ENC_PART being 0, and it was
actually corrupting the partition table of the SD card. Looking more closely I think
what I should of used is 

#define CONFIG_ENV_IS_IN_FAT
#define FAT_ENV_INTERFACE               "mmc"
#define FAT_ENV_DEVICE_AND_PART         "1:1"
#define FAT_ENV_FILE                    "uboot.env"

This then saves the enviroment on a fat formatted SD card with the filename
u-boot.env. This is what I plan on using for v3.

Maybe I should additionally request some space in the official eMMC parition 
table and then we could switch over to using that.

> 
> > +#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
> 
> Is redundant env necessary? It seems like this was more for raw NAND
> and shouldn't really be needed for MMC.

README file documents it as being valid for CONFIG_ENV_IS_IN_MMC, and a bunch of boards
declare it with their CONFIG_ENV_IS_IN_MMC such as omap5_uevm.h, dra7xx_evm.h,
am335x_evm.h. Whilst using managed NAND should be more reliable, I think it
is still used in case there is a power failure whilst issuing 'saveenv'.

Anyways with moving to CONFIG_ENV_IS_IN_FAT I won't need it anymore so it will be
removed in V3.

Many thanks for your thorough reviews, you've spotted some really good stuff
that has meant boot time is now a lot quicker, and I will no longer be crapping
over peoples SD card partition table :)

kind regards,

Peter.
Rob Herring July 16, 2015, 1:28 p.m. UTC | #3
On Wed, Jul 15, 2015 at 7:41 PM, Peter Griffin <peter.griffin@linaro.org> wrote:
> Hi Rob,
>
> On Fri, 10 Jul 2015, Rob Herring wrote:
>
>> On Wed, Jul 8, 2015 at 10:57 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.
>> >

[...]

>> > +#define CONFIG_BAUDRATE                        115200
>> > +#define CONFIG_SYS_SERIAL0             0xF8015000
>>
>> Just do:
>>
>> #define CONFIG_PL01x_PORTS             {(void *)0xf8015000}
>
> Ok, fixed in V3
>
>>
>> You are probably going to want to setup multiple serial consoles
>> (debug + LS header). That can come later, but I've figured out how to
>> enable that if you are interested.
>
> Yes I'm interested, please do let me know :)

See this commit:

https://git.linaro.org/people/rob.herring/u-boot.git/commitdiff/f1d0aef06ae7fe09793d46589bd94fa36c45bbc0

This may be 8250 specific and require more work for pl011 driver. The
mixture of 0 and 1 based indexing makes it fun too.


>> > +#define CONFIG_EXTRA_ENV_SETTINGS      \
>> > +                               "kernel_name=Image\0"   \
>> > +                               "kernel_addr=0x0000000\0" \
>>
>> Shouldn't this be 0x80000 to avoid copying from 0x0 to 0x80000.
>
> I've updated this. Kernel boot time is much reduced with this and also the
> icache being enabled.

Also, this should be kernel_addr_r

>
>>
>> > +                               "fdt_name=hi6220-hikey.dtb\0" \
>> > +                               "fdt_addr=0x0300000\0" \

and fdt_addr_r

>> > +                               "max_fdt=0x100000\0" \
>>
>> I don't think this is needed.
>
> Removed in V3
>>
>> > +                               "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 "
>>
>> /dev/mmcblk0p7 doesn't look right. You mean "root=/dev/..."?
>
> Good spot, yes your right. Plus now you highlight it the comment above also needs updating.
>
> Will fix in V3.
>
>>
>> > +
>> > +/* Copy the kernel and FDT to DRAM memory and boot */
>> > +#define CONFIG_BOOTCOMMAND     "booti $kernel_addr_r - $fdt_addr_r"
>>
>> Don't you need to set these variables?
>>
>> Also, don't you need to load the kernel and dtb first?
>
> Yes, but I'm not sure quite what to make the default here. My personal
> workflow is: -
>
>  "usb start; dhcp; tftp $kernel_addr $kernel_name; tftp $fdt_addr $fdt_name;
>    booti $kernel_addr - $fdt_addr"
>
> So I could use that unless you have a better idea?

Not really as everyone has their own preferences. I have some thing like this:

#define CONFIG_BOOTCOMMAND \
"while true; do " \
"mmc read ${fdt_addr_r} 0x10000 0x1000; " \
"fastboot; " \
"mmc read ${fdt_addr_r} 0x10000 0x1000; " \
"mmc read ${kernel_addr_r} 0x8000 0x8000 && " \
"bootm ${kernel_addr_r} ${kernel_addr_r} ${fdt_addr_r};" \
"done"

This relies on fastboot doing USB cable detection and it exits if no
USB connection.

USB ethernet is as good a default as any. Otherwise reading Image and
dtb from the 1st or bootable partition (the default) would be
reasonable.


>> > +/* 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
>>
>> Don't you have these reversed? The first MMC device is 0 and I think
>> partition numbering starts at 1.
>
> Having CONFIG_SYS_MMC_ENV_DEV 1 was deliberate, as the first device is eMMC, and
> I don't have a "official" partition to save the u-boot enviroment in.
> So as not to corrupt anything folks may have flashed into eMMC from the official
> builds I opted to save the u-boot env to SD card which is device 1.

Okay, but don't you have spare space in the partition with u-boot? I
have a single bootloader partition 1MB in size and the last 8? KB is
the env.

> However that seems to have been working by luck with ENC_PART being 0, and it was
> actually corrupting the partition table of the SD card. Looking more closely I think
> what I should of used is
>
> #define CONFIG_ENV_IS_IN_FAT
> #define FAT_ENV_INTERFACE               "mmc"
> #define FAT_ENV_DEVICE_AND_PART         "1:1"
> #define FAT_ENV_FILE                    "uboot.env"
>
> This then saves the enviroment on a fat formatted SD card with the filename
> u-boot.env. This is what I plan on using for v3.
>
> Maybe I should additionally request some space in the official eMMC parition
> table and then we could switch over to using that.
>
>>
>> > +#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
>>
>> Is redundant env necessary? It seems like this was more for raw NAND
>> and shouldn't really be needed for MMC.
>
> README file documents it as being valid for CONFIG_ENV_IS_IN_MMC, and a bunch of boards
> declare it with their CONFIG_ENV_IS_IN_MMC such as omap5_uevm.h, dra7xx_evm.h,
> am335x_evm.h. Whilst using managed NAND should be more reliable, I think it
> is still used in case there is a power failure whilst issuing 'saveenv'.

Perhaps a bunch of cut and paste. I'd guess there are many more
platforms that use MMC and don't enable redundant.

> Anyways with moving to CONFIG_ENV_IS_IN_FAT I won't need it anymore so it will be
> removed in V3.

Storing in FAT probably only increases your chance of failure from
power failure. :)

Rob
Tom Rini July 16, 2015, 1:39 p.m. UTC | #4
On Thu, Jul 16, 2015 at 08:28:03AM -0500, Rob Herring wrote:
> On Wed, Jul 15, 2015 at 7:41 PM, Peter Griffin <peter.griffin@linaro.org> wrote:
[snip]
> >> > +#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
> >>
> >> Is redundant env necessary? It seems like this was more for raw NAND
> >> and shouldn't really be needed for MMC.
> >
> > README file documents it as being valid for CONFIG_ENV_IS_IN_MMC, and a bunch of boards
> > declare it with their CONFIG_ENV_IS_IN_MMC such as omap5_uevm.h, dra7xx_evm.h,
> > am335x_evm.h. Whilst using managed NAND should be more reliable, I think it
> > is still used in case there is a power failure whilst issuing 'saveenv'.
> 
> Perhaps a bunch of cut and paste. I'd guess there are many more
> platforms that use MMC and don't enable redundant.

No, we turn it on, on purpose, out of a certain level of paranoia (and
for ref boards like those, showing everything one could do, let $company
and their experts argue of which failure possibilities are the important
ones).

> > Anyways with moving to CONFIG_ENV_IS_IN_FAT I won't need it anymore so it will be
> > removed in V3.
> 
> Storing in FAT probably only increases your chance of failure from
> power failure. :)

True but IMHO env in FAT is the most friendly option for a community
board. "Broke your ENV?  Stick the SD card in your PC, delete .." "Here,
take a look at my env, copy this file ..." and all that.
Simon Glass July 18, 2015, 2:38 p.m. UTC | #5
Hi Peter,

On 8 July 2015 at 09:57, 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.
>
> 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. 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. On v2015.07-rc2 dhcp now works, and also usb mass storage
> is enumerated correctly.
>
> 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               |   8 +
>  board/hisilicon/hikey/Kconfig  |  15 ++
>  board/hisilicon/hikey/Makefile |   8 +
>  board/hisilicon/hikey/hikey.c  | 415 +++++++++++++++++++++++++++++++++++++++++
>  configs/hikey_defconfig        |   5 +
>  include/configs/hikey.h        | 168 +++++++++++++++++
>  6 files changed, 619 insertions(+)
>  create mode 100644 board/hisilicon/hikey/Kconfig
>  create mode 100644 board/hisilicon/hikey/Makefile
>  create mode 100644 board/hisilicon/hikey/hikey.c
>  create mode 100644 configs/hikey_defconfig
>  create mode 100644 include/configs/hikey.h
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 2985e6e..d0b7939 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -721,6 +721,13 @@ config TARGET_LS2085ARDB
>           development platform that supports the QorIQ LS2085A
>           Layerscape Architecture processor.
>
> +config TARGET_HIKEY
> +       bool "Support HiKey 96boards Consumer Edition Platform"
> +       select ARM64
> +         help
> +         Support for HiKey 96boards platform. It features a HI6220
> +         SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM.
> +
>  config TARGET_LS1021AQDS
>         bool "Support ls1021aqds"
>         select CPU_V7
> @@ -865,6 +872,7 @@ source "board/Marvell/gplugd/Kconfig"
>  source "board/armadeus/apf27/Kconfig"
>  source "board/armltd/vexpress/Kconfig"
>  source "board/armltd/vexpress64/Kconfig"
> +source "board/hisilicon/hikey/Kconfig"
>  source "board/bachmann/ot1200/Kconfig"
>  source "board/balloon3/Kconfig"
>  source "board/barco/platinum/Kconfig"
> diff --git a/board/hisilicon/hikey/Kconfig b/board/hisilicon/hikey/Kconfig
> new file mode 100644
> index 0000000..f7f1055
> --- /dev/null
> +++ b/board/hisilicon/hikey/Kconfig
> @@ -0,0 +1,15 @@
> +if TARGET_HIKEY
> +
> +config SYS_BOARD
> +       default "hikey"
> +
> +config SYS_VENDOR
> +       default "hisilicon"
> +
> +config SYS_SOC
> +       default "hi6220"
> +
> +config SYS_CONFIG_NAME
> +       default "hikey"
> +
> +endif
> diff --git a/board/hisilicon/hikey/Makefile b/board/hisilicon/hikey/Makefile
> new file mode 100644
> index 0000000..d4ec8c7
> --- /dev/null
> +++ b/board/hisilicon/hikey/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/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
> new file mode 100644
> index 0000000..bd5c409
> --- /dev/null
> +++ b/board/hisilicon/hikey/hikey.c
> @@ -0,0 +1,415 @@
> +/*
> + * (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>

nit: errno.h should go above malloc.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

Isn't that always defined? Probably don't need this #ifdef. Also can
you add a TODO to drop this table in favour of device tree?

> +static const struct hikey_gpio_platdata hi6220_gpio[] = {
> +       { 0, HI6220_GPIO_BASE(0)},
> +       { 1, HI6220_GPIO_BASE(1)},
> +       { 2, HI6220_GPIO_BASE(2)},
> +       { 3, HI6220_GPIO_BASE(3)},
> +       { 4, HI6220_GPIO_BASE(4)},
> +       { 5, HI6220_GPIO_BASE(5)},
> +       { 6, HI6220_GPIO_BASE(6)},
> +       { 7, HI6220_GPIO_BASE(7)},
> +       { 8, HI6220_GPIO_BASE(8)},
> +       { 9, HI6220_GPIO_BASE(9)},
> +       { 10, HI6220_GPIO_BASE(10)},
> +       { 11, HI6220_GPIO_BASE(11)},
> +       { 12, HI6220_GPIO_BASE(12)},
> +       { 13, HI6220_GPIO_BASE(13)},
> +       { 14, HI6220_GPIO_BASE(14)},
> +       { 15, HI6220_GPIO_BASE(15)},
> +       { 16, HI6220_GPIO_BASE(16)},
> +       { 17, HI6220_GPIO_BASE(17)},
> +       { 18, HI6220_GPIO_BASE(18)},
> +       { 19, HI6220_GPIO_BASE(19)},
> +
> +};
> +
> +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;
> +
> +#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);
> +
> +       mdelay(5);
> +}
> +
> +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);

Should define a struct for this peripheral.

> +
> +       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);

What are 11 and 27? Should they have an enum?

> +       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));

Repeating code here and below - how about a function to enable a given clock?

> +
> +       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);

This should go in a PMIC driver. Ideally most of this would happen
automatically if the voltages are in the device tree, but since you
don't have one, I suggest just moving this code into the driver.

> +}
> +
> +int misc_init_r(void)
> +{
> +       init_usb_and_picophy();
> +
> +       return 0;
> +}
> +
> +int board_init(void)
> +{
> +       gd->flags = 0;

Drop that.

> +
> +       icache_enable();

Should happen in generic ARM code at start-up?

> +
> +       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 = 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 = PHYS_SDRAM_1_SIZE;
> +}
> +
> +/* Use the Watchdog to cause reset */
> +void reset_cpu(ulong addr)
> +{
> +       /* TODO program the watchdog */
> +}
> diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
> new file mode 100644
> index 0000000..50baf22
> --- /dev/null
> +++ b/configs/hikey_defconfig
> @@ -0,0 +1,5 @@
> +# 96boards HiKey
> +CONFIG_ARM=y
> +CONFIG_TARGET_HIKEY=y
> +CONFIG_SHOW_BOOT_PROGRESS=y

I don't think this works yet - there is no Kconfig for it. You can put
it in your hikey.h file.

> +CONFIG_NET=y
> diff --git a/include/configs/hikey.h b/include/configs/hikey.h
> new file mode 100644
> index 0000000..303b857
> --- /dev/null
> +++ b/include/configs/hikey.h
> @@ -0,0 +1,168 @@
> +/*
> + * (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_IDENT_STRING            "hikey"
> +
> +/* Flat Device Tree Definitions */
> +#define CONFIG_OF_LIBFDT
> +
> +/* Physical Memory Map */
> +
> +/* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */
> +#define CONFIG_SYS_TEXT_BASE           0x35000000
> +
> +#define CONFIG_NR_DRAM_BANKS           1
> +#define PHYS_SDRAM_1                   0x00000000
> +
> +/* 1008 MB (the last 16Mb are secured for TrustZone by ATF*/
> +#define PHYS_SDRAM_1_SIZE              0x3f000000
> +#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 + 0x80000)
> +
> +/* Generic Timer Definitions */
> +#define COUNTER_FREQUENCY              (19000000)
> +
> +/* Generic Interrupt Controller Definitions */
> +#define GICD_BASE                      (0xf6801000)

Don't need () around simple constants

> +#define GICC_BASE                      (0xf6802000)
> +
> +/* 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

Again this need to be device tree soon.

> +
> +#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_CMD_CACHE
> +#define CONFIG_CMD_BDI
> +#define CONFIG_CMD_UNZIP
> +#define CONFIG_CMD_PXE
> +#define CONFIG_CMD_ENV
> +#define CONFIG_CMD_IMI
> +#define CONFIG_CMD_LOADB
> +#define CONFIG_CMD_MEMORY
> +#define CONFIG_CMD_SAVEENV
> +#define CONFIG_CMD_RUN
> +#define CONFIG_CMD_BOOTD
> +#define CONFIG_CMD_ECHO
> +#define CONFIG_CMD_SOURCE
> +
> +#define CONFIG_MAC_PARTITION
> +#define CONFIG_MTD_PARTITIONS
> +
> +/* BOOTP options */
> +#define CONFIG_BOOTP_BOOTFILESIZE
> +
> +#define CONFIG_CMD_NET
> +
> +#include <config_distro_defaults.h>
> +
> +/* 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_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 */
> --
> 1.9.1
>

Regards,
Simon
Peter Griffin July 28, 2015, 5:37 p.m. UTC | #6
Hi Simon,

Thanks for reviewing.

On 18 July 2015 at 15:38, Simon Glass <sjg@chromium.org> wrote:

> Hi Peter,
>
> On 8 July 2015 at 09:57, 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.
> >
> > 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. 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. On v2015.07-rc2 dhcp now works, and also usb mass storage
> > is enumerated correctly.
> >
> > 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               |   8 +
> >  board/hisilicon/hikey/Kconfig  |  15 ++
> >  board/hisilicon/hikey/Makefile |   8 +
> >  board/hisilicon/hikey/hikey.c  | 415
> +++++++++++++++++++++++++++++++++++++++++
> >  configs/hikey_defconfig        |   5 +
> >  include/configs/hikey.h        | 168 +++++++++++++++++
> >  6 files changed, 619 insertions(+)
> >  create mode 100644 board/hisilicon/hikey/Kconfig
> >  create mode 100644 board/hisilicon/hikey/Makefile
> >  create mode 100644 board/hisilicon/hikey/hikey.c
> >  create mode 100644 configs/hikey_defconfig
> >  create mode 100644 include/configs/hikey.h
> >
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index 2985e6e..d0b7939 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -721,6 +721,13 @@ config TARGET_LS2085ARDB
> >           development platform that supports the QorIQ LS2085A
> >           Layerscape Architecture processor.
> >
> > +config TARGET_HIKEY
> > +       bool "Support HiKey 96boards Consumer Edition Platform"
> > +       select ARM64
> > +         help
> > +         Support for HiKey 96boards platform. It features a HI6220
> > +         SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM.
> > +
> >  config TARGET_LS1021AQDS
> >         bool "Support ls1021aqds"
> >         select CPU_V7
> > @@ -865,6 +872,7 @@ source "board/Marvell/gplugd/Kconfig"
> >  source "board/armadeus/apf27/Kconfig"
> >  source "board/armltd/vexpress/Kconfig"
> >  source "board/armltd/vexpress64/Kconfig"
> > +source "board/hisilicon/hikey/Kconfig"
> >  source "board/bachmann/ot1200/Kconfig"
> >  source "board/balloon3/Kconfig"
> >  source "board/barco/platinum/Kconfig"
> > diff --git a/board/hisilicon/hikey/Kconfig
> b/board/hisilicon/hikey/Kconfig
> > new file mode 100644
> > index 0000000..f7f1055
> > --- /dev/null
> > +++ b/board/hisilicon/hikey/Kconfig
> > @@ -0,0 +1,15 @@
> > +if TARGET_HIKEY
> > +
> > +config SYS_BOARD
> > +       default "hikey"
> > +
> > +config SYS_VENDOR
> > +       default "hisilicon"
> > +
> > +config SYS_SOC
> > +       default "hi6220"
> > +
> > +config SYS_CONFIG_NAME
> > +       default "hikey"
> > +
> > +endif
> > diff --git a/board/hisilicon/hikey/Makefile
> b/board/hisilicon/hikey/Makefile
> > new file mode 100644
> > index 0000000..d4ec8c7
> > --- /dev/null
> > +++ b/board/hisilicon/hikey/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/hisilicon/hikey/hikey.c
> b/board/hisilicon/hikey/hikey.c
> > new file mode 100644
> > index 0000000..bd5c409
> > --- /dev/null
> > +++ b/board/hisilicon/hikey/hikey.c
> > @@ -0,0 +1,415 @@
> > +/*
> > + * (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>
>
> nit: errno.h should go above malloc.h
>

Fixed in v3


>
> > +#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
>
> Isn't that always defined? Probably don't need this #ifdef. Also can
> you add a TODO to drop this table in favour of device tree?
>

#ifdef removed and TODO added in v3


>
> > +static const struct hikey_gpio_platdata hi6220_gpio[] = {
> > +       { 0, HI6220_GPIO_BASE(0)},
> > +       { 1, HI6220_GPIO_BASE(1)},
> > +       { 2, HI6220_GPIO_BASE(2)},
> > +       { 3, HI6220_GPIO_BASE(3)},
> > +       { 4, HI6220_GPIO_BASE(4)},
> > +       { 5, HI6220_GPIO_BASE(5)},
> > +       { 6, HI6220_GPIO_BASE(6)},
> > +       { 7, HI6220_GPIO_BASE(7)},
> > +       { 8, HI6220_GPIO_BASE(8)},
> > +       { 9, HI6220_GPIO_BASE(9)},
> > +       { 10, HI6220_GPIO_BASE(10)},
> > +       { 11, HI6220_GPIO_BASE(11)},
> > +       { 12, HI6220_GPIO_BASE(12)},
> > +       { 13, HI6220_GPIO_BASE(13)},
> > +       { 14, HI6220_GPIO_BASE(14)},
> > +       { 15, HI6220_GPIO_BASE(15)},
> > +       { 16, HI6220_GPIO_BASE(16)},
> > +       { 17, HI6220_GPIO_BASE(17)},
> > +       { 18, HI6220_GPIO_BASE(18)},
> > +       { 19, HI6220_GPIO_BASE(19)},
> > +
> > +};
> > +
> > +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;
> > +
> > +#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);
> > +
> > +       mdelay(5);
> > +}
> > +
> > +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);
>
> Should define a struct for this peripheral.
>

In v3 I've added a minimal pinmux driver  which I've reverse engineered
by looking at the Linux code.

Sadly the Linux pinctrl settings don't actually work for the sd card slot
and
it hangs the board. I've debugged this to not setting BIT(2) on the pull
down/up/drive registers.

I don't have any documentation on the register bit fields only the
the existing code which makes things difficult :(


>
> > +
> > +       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);
>
> What are 11 and 27? Should they have an enum?
>

Ideally yes, but unfortunately I don't have any documentation for the
register.
All I know for sure is it doesn't work without it!


>
> > +       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));
>
> Repeating code here and below - how about a function to enable a given
> clock?
>

I've added a clock_enable and clock_disable function in V3 and removed this
code
duplication.


> > +
> > +       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);
>
> This should go in a PMIC driver. Ideally most of this would happen
> automatically if the voltages are in the device tree, but since you
> don't have one, I suggest just moving this code into the driver.
>

Ok I've done as you suggested and added a simple simple pmic driver
in v3. From a practical PoV this means you can now dump the pmic
regs using the pmic * commands, which might be helpful to somebody.


> > +}
> > +
> > +int misc_init_r(void)
> > +{
> > +       init_usb_and_picophy();
> > +
> > +       return 0;
> > +}
> > +
> > +int board_init(void)
> > +{
> > +       gd->flags = 0;
>
> Drop that.
>

Fixed in v3

>
> > +
> > +       icache_enable();
>
> Should happen in generic ARM code at start-up?
>

Yes Rob also pointed this out, I've removed it in V3.

>
> > +
> > +       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 = 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 = PHYS_SDRAM_1_SIZE;
> > +}
> > +
> > +/* Use the Watchdog to cause reset */
> > +void reset_cpu(ulong addr)
> > +{
> > +       /* TODO program the watchdog */
> > +}
> > diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
> > new file mode 100644
> > index 0000000..50baf22
> > --- /dev/null
> > +++ b/configs/hikey_defconfig
> > @@ -0,0 +1,5 @@
> > +# 96boards HiKey
> > +CONFIG_ARM=y
> > +CONFIG_TARGET_HIKEY=y
> > +CONFIG_SHOW_BOOT_PROGRESS=y
>
> I don't think this works yet - there is no Kconfig for it. You can put
> it in your hikey.h file.
>

Ok, I've removed in V3, as not much use if it doesn't work.


>
> > +CONFIG_NET=y
> > diff --git a/include/configs/hikey.h b/include/configs/hikey.h
> > new file mode 100644
> > index 0000000..303b857
> > --- /dev/null
> > +++ b/include/configs/hikey.h
> > @@ -0,0 +1,168 @@
> > +/*
> > + * (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_IDENT_STRING            "hikey"
> > +
> > +/* Flat Device Tree Definitions */
> > +#define CONFIG_OF_LIBFDT
> > +
> > +/* Physical Memory Map */
> > +
> > +/* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */
> > +#define CONFIG_SYS_TEXT_BASE           0x35000000
> > +
> > +#define CONFIG_NR_DRAM_BANKS           1
> > +#define PHYS_SDRAM_1                   0x00000000
> > +
> > +/* 1008 MB (the last 16Mb are secured for TrustZone by ATF*/
> > +#define PHYS_SDRAM_1_SIZE              0x3f000000
> > +#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 + 0x80000)
> > +
> > +/* Generic Timer Definitions */
> > +#define COUNTER_FREQUENCY              (19000000)
> > +
> > +/* Generic Interrupt Controller Definitions */
> > +#define GICD_BASE                      (0xf6801000)
>
> Don't need () around simple constants
>

Fixed in V3


>
> > +#define GICC_BASE                      (0xf6802000)
> > +
> > +/* 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
>
> Again this need to be device tree soon.
>

Yes ok. Also we wish to enable additional UARTS on the low speed connector.
In v3 in the pinmux driver I've added code for the additional UARTs.

I'm also being sent an expansion board which brings out the UARTs on the
lowspeed
connector, so I can test this :)


>
> > +
> > +#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_CMD_CACHE
> > +#define CONFIG_CMD_BDI
> > +#define CONFIG_CMD_UNZIP
> > +#define CONFIG_CMD_PXE
> > +#define CONFIG_CMD_ENV
> > +#define CONFIG_CMD_IMI
> > +#define CONFIG_CMD_LOADB
> > +#define CONFIG_CMD_MEMORY
> > +#define CONFIG_CMD_SAVEENV
> > +#define CONFIG_CMD_RUN
> > +#define CONFIG_CMD_BOOTD
> > +#define CONFIG_CMD_ECHO
> > +#define CONFIG_CMD_SOURCE
> > +
> > +#define CONFIG_MAC_PARTITION
> > +#define CONFIG_MTD_PARTITIONS
> > +
> > +/* BOOTP options */
> > +#define CONFIG_BOOTP_BOOTFILESIZE
> > +
> > +#define CONFIG_CMD_NET
> > +
> > +#include <config_distro_defaults.h>
> > +
> > +/* 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_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 */
> > --
> > 1.9.1
> >
>
> Regards,
> Simon
>

regards,

Peter.
Peter Griffin July 29, 2015, 8:59 p.m. UTC | #7
Hi Rob,

On 16 July 2015 at 14:28, Rob Herring <robherring2@gmail.com> wrote:

> On Wed, Jul 15, 2015 at 7:41 PM, Peter Griffin <peter.griffin@linaro.org>
> wrote:
> > Hi Rob,
> >
> > On Fri, 10 Jul 2015, Rob Herring wrote:
> >
> >> On Wed, Jul 8, 2015 at 10:57 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.
> >> >
>
> [...]
>

<snip>


> >> You are probably going to want to setup multiple serial consoles
> >> (debug + LS header). That can come later, but I've figured out how to
> >> enable that if you are interested.
> >
> > Yes I'm interested, please do let me know :)
>
> See this commit:
>
>
> https://git.linaro.org/people/rob.herring/u-boot.git/commitdiff/f1d0aef06ae7fe09793d46589bd94fa36c45bbc0
>
> This may be 8250 specific and require more work for pl011 driver. The
> mixture of 0 and 1 based indexing makes it fun too.
>

OK thanks for the pointer :) I'm waiting for one of Grants expansion boards
to be sent to me, so will try it out when it arrives.


> >> > +#define CONFIG_EXTRA_ENV_SETTINGS      \
> >> > +                               "kernel_name=Image\0"   \
> >> > +                               "kernel_addr=0x0000000\0" \
> >>
> >> Shouldn't this be 0x80000 to avoid copying from 0x0 to 0x80000.
> >
> > I've updated this. Kernel boot time is much reduced with this and also
> the
> > icache being enabled.
>
> Also, this should be kernel_addr_r
>

Fixed in v3


>
> >
> >>
> >> > +                               "fdt_name=hi6220-hikey.dtb\0" \
> >> > +                               "fdt_addr=0x0300000\0" \
>
> and fdt_addr_r
>

Fixed in v3


>
> >> > +                               "max_fdt=0x100000\0" \
> >>
> >> I don't think this is needed.
> >
> > Removed in V3
> >>
> >> > +                               "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 "
> >>
> >> /dev/mmcblk0p7 doesn't look right. You mean "root=/dev/..."?
> >
> > Good spot, yes your right. Plus now you highlight it the comment above
> also needs updating.
> >
> > Will fix in V3.
> >
> >>
> >> > +
> >> > +/* Copy the kernel and FDT to DRAM memory and boot */
> >> > +#define CONFIG_BOOTCOMMAND     "booti $kernel_addr_r - $fdt_addr_r"
> >>
> >> Don't you need to set these variables?
> >>
> >> Also, don't you need to load the kernel and dtb first?
> >
> > Yes, but I'm not sure quite what to make the default here. My personal
> > workflow is: -
> >
> >  "usb start; dhcp; tftp $kernel_addr $kernel_name; tftp $fdt_addr
> $fdt_name;
> >    booti $kernel_addr - $fdt_addr"
> >
> > So I could use that unless you have a better idea?
>
> Not really as everyone has their own preferences. I have some thing like
> this:
>
> #define CONFIG_BOOTCOMMAND \
> "while true; do " \
> "mmc read ${fdt_addr_r} 0x10000 0x1000; " \
> "fastboot; " \
> "mmc read ${fdt_addr_r} 0x10000 0x1000; " \
> "mmc read ${kernel_addr_r} 0x8000 0x8000 && " \
> "bootm ${kernel_addr_r} ${kernel_addr_r} ${fdt_addr_r};" \
> "done"
>
> This relies on fastboot doing USB cable detection and it exits if no
> USB connection.
>
> USB ethernet is as good a default as any. Otherwise reading Image and
> dtb from the 1st or bootable partition (the default) would be
> reasonable.
>

Thanks for sharing your setup, I've updated the bootcmd to be the USB
ethernet by default in the V3 patches.


>> > +/* 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
> >>
> >> Don't you have these reversed? The first MMC device is 0 and I think
> >> partition numbering starts at 1.
> >
> > Having CONFIG_SYS_MMC_ENV_DEV 1 was deliberate, as the first device is
> eMMC, and
> > I don't have a "official" partition to save the u-boot enviroment in.
> > So as not to corrupt anything folks may have flashed into eMMC from the
> official
> > builds I opted to save the u-boot env to SD card which is device 1.
>
> Okay, but don't you have spare space in the partition with u-boot? I
> have a single bootloader partition 1MB in size and the last 8? KB is
> the env.
>

Good idea, I'd not thought of that and we could most likely do that if we
wanted. However I plan on sticking with u-boot env on the sd card for the
moment
as Tom pointed out it can be a bit more user friendly for a community board.


>
> > However that seems to have been working by luck with ENC_PART being 0,
> and it was
> > actually corrupting the partition table of the SD card. Looking more
> closely I think
> > what I should of used is
> >
> > #define CONFIG_ENV_IS_IN_FAT
> > #define FAT_ENV_INTERFACE               "mmc"
> > #define FAT_ENV_DEVICE_AND_PART         "1:1"
> > #define FAT_ENV_FILE                    "uboot.env"
> >
> > This then saves the enviroment on a fat formatted SD card with the
> filename
> > u-boot.env. This is what I plan on using for v3.
> >
> > Maybe I should additionally request some space in the official eMMC
> parition
> > table and then we could switch over to using that.
> >
> >>
> >> > +#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
> >>
> >> Is redundant env necessary? It seems like this was more for raw NAND
> >> and shouldn't really be needed for MMC.
> >
> > README file documents it as being valid for CONFIG_ENV_IS_IN_MMC, and a
> bunch of boards
> > declare it with their CONFIG_ENV_IS_IN_MMC such as omap5_uevm.h,
> dra7xx_evm.h,
> > am335x_evm.h. Whilst using managed NAND should be more reliable, I think
> it
> > is still used in case there is a power failure whilst issuing 'saveenv'.
>
> Perhaps a bunch of cut and paste. I'd guess there are many more
> platforms that use MMC and don't enable redundant.
>

Tom answered this one already.


>
> > Anyways with moving to CONFIG_ENV_IS_IN_FAT I won't need it anymore so
> it will be
> > removed in V3.
>
> Storing in FAT probably only increases your chance of failure from
> power failure. :)
>
> Ha, yes maybe :)

regards,

Peter.
diff mbox

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2985e6e..d0b7939 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -721,6 +721,13 @@  config TARGET_LS2085ARDB
 	  development platform that supports the QorIQ LS2085A
 	  Layerscape Architecture processor.
 
+config TARGET_HIKEY
+	bool "Support HiKey 96boards Consumer Edition Platform"
+	select ARM64
+	  help
+	  Support for HiKey 96boards platform. It features a HI6220
+	  SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM.
+
 config TARGET_LS1021AQDS
 	bool "Support ls1021aqds"
 	select CPU_V7
@@ -865,6 +872,7 @@  source "board/Marvell/gplugd/Kconfig"
 source "board/armadeus/apf27/Kconfig"
 source "board/armltd/vexpress/Kconfig"
 source "board/armltd/vexpress64/Kconfig"
+source "board/hisilicon/hikey/Kconfig"
 source "board/bachmann/ot1200/Kconfig"
 source "board/balloon3/Kconfig"
 source "board/barco/platinum/Kconfig"
diff --git a/board/hisilicon/hikey/Kconfig b/board/hisilicon/hikey/Kconfig
new file mode 100644
index 0000000..f7f1055
--- /dev/null
+++ b/board/hisilicon/hikey/Kconfig
@@ -0,0 +1,15 @@ 
+if TARGET_HIKEY
+
+config SYS_BOARD
+	default "hikey"
+
+config SYS_VENDOR
+	default "hisilicon"
+
+config SYS_SOC
+	default "hi6220"
+
+config SYS_CONFIG_NAME
+	default "hikey"
+
+endif
diff --git a/board/hisilicon/hikey/Makefile b/board/hisilicon/hikey/Makefile
new file mode 100644
index 0000000..d4ec8c7
--- /dev/null
+++ b/board/hisilicon/hikey/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/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c
new file mode 100644
index 0000000..bd5c409
--- /dev/null
+++ b/board/hisilicon/hikey/hikey.c
@@ -0,0 +1,415 @@ 
+/*
+ * (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_GPIO_BASE(0)},
+	{ 1, HI6220_GPIO_BASE(1)},
+	{ 2, HI6220_GPIO_BASE(2)},
+	{ 3, HI6220_GPIO_BASE(3)},
+	{ 4, HI6220_GPIO_BASE(4)},
+	{ 5, HI6220_GPIO_BASE(5)},
+	{ 6, HI6220_GPIO_BASE(6)},
+	{ 7, HI6220_GPIO_BASE(7)},
+	{ 8, HI6220_GPIO_BASE(8)},
+	{ 9, HI6220_GPIO_BASE(9)},
+	{ 10, HI6220_GPIO_BASE(10)},
+	{ 11, HI6220_GPIO_BASE(11)},
+	{ 12, HI6220_GPIO_BASE(12)},
+	{ 13, HI6220_GPIO_BASE(13)},
+	{ 14, HI6220_GPIO_BASE(14)},
+	{ 15, HI6220_GPIO_BASE(15)},
+	{ 16, HI6220_GPIO_BASE(16)},
+	{ 17, HI6220_GPIO_BASE(17)},
+	{ 18, HI6220_GPIO_BASE(18)},
+	{ 19, HI6220_GPIO_BASE(19)},
+
+};
+
+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;
+
+#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);
+
+	mdelay(5);
+}
+
+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);
+}
+
+int misc_init_r(void)
+{
+	init_usb_and_picophy();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	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 = 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 = PHYS_SDRAM_1_SIZE;
+}
+
+/* Use the Watchdog to cause reset */
+void reset_cpu(ulong addr)
+{
+	/* TODO program the watchdog */
+}
diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig
new file mode 100644
index 0000000..50baf22
--- /dev/null
+++ b/configs/hikey_defconfig
@@ -0,0 +1,5 @@ 
+# 96boards HiKey
+CONFIG_ARM=y
+CONFIG_TARGET_HIKEY=y
+CONFIG_SHOW_BOOT_PROGRESS=y
+CONFIG_NET=y
diff --git a/include/configs/hikey.h b/include/configs/hikey.h
new file mode 100644
index 0000000..303b857
--- /dev/null
+++ b/include/configs/hikey.h
@@ -0,0 +1,168 @@ 
+/*
+ * (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_IDENT_STRING		"hikey"
+
+/* Flat Device Tree Definitions */
+#define CONFIG_OF_LIBFDT
+
+/* Physical Memory Map */
+
+/* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */
+#define CONFIG_SYS_TEXT_BASE		0x35000000
+
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM_1			0x00000000
+
+/* 1008 MB (the last 16Mb are secured for TrustZone by ATF*/
+#define PHYS_SDRAM_1_SIZE		0x3f000000
+#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 + 0x80000)
+
+/* Generic Timer Definitions */
+#define COUNTER_FREQUENCY              (19000000)
+
+/* Generic Interrupt Controller Definitions */
+#define GICD_BASE			(0xf6801000)
+#define GICC_BASE			(0xf6802000)
+
+/* 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_CMD_CACHE
+#define CONFIG_CMD_BDI
+#define CONFIG_CMD_UNZIP
+#define CONFIG_CMD_PXE
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_IMI
+#define CONFIG_CMD_LOADB
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_SAVEENV
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_BOOTD
+#define CONFIG_CMD_ECHO
+#define CONFIG_CMD_SOURCE
+
+#define CONFIG_MAC_PARTITION
+#define CONFIG_MTD_PARTITIONS
+
+/* BOOTP options */
+#define CONFIG_BOOTP_BOOTFILESIZE
+
+#define CONFIG_CMD_NET
+
+#include <config_distro_defaults.h>
+
+/* 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_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 */