Merge git://www.denx.de/git/u-boot-marvell

master
Tom Rini 8 years ago
commit b591730c35
  1. 64
      arch/arm/dts/armada-7040-db.dts
  2. 114
      arch/arm/dts/armada-8040-db.dts
  3. 18
      arch/arm/dts/armada-ap806.dtsi
  4. 32
      arch/arm/dts/armada-cp110-master.dtsi
  5. 19
      arch/arm/dts/armada-cp110-slave.dtsi
  6. 21
      arch/arm/include/asm/arch-armada8k/cache_llc.h
  7. 17
      arch/arm/include/asm/arch-armada8k/soc-info.h
  8. 1
      arch/arm/mach-mvebu/armada8k/Makefile
  9. 39
      arch/arm/mach-mvebu/armada8k/cache_llc.S
  10. 3
      cmd/Kconfig
  11. 2
      cmd/Makefile
  12. 52
      cmd/mvebu/Kconfig
  13. 8
      cmd/mvebu/Makefile
  14. 767
      cmd/mvebu/bubt.c
  15. 6
      configs/mvebu_db-88f7040_defconfig
  16. 3
      configs/mvebu_db-88f8040_defconfig
  17. 25
      doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt
  18. 270
      doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt
  19. 113
      doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt
  20. 64
      doc/mvebu/cmd/bubt.txt
  21. 1
      drivers/pinctrl/Kconfig
  22. 1
      drivers/pinctrl/Makefile
  23. 7
      drivers/pinctrl/mvebu/Kconfig
  24. 7
      drivers/pinctrl/mvebu/Makefile
  25. 179
      drivers/pinctrl/mvebu/pinctrl-mvebu.c
  26. 31
      drivers/pinctrl/mvebu/pinctrl-mvebu.h

@ -66,36 +66,14 @@
};
};
&i2c0 {
status = "okay";
clock-frequency = <100000>;
};
&spi0 {
status = "okay";
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <10000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "U-Boot";
reg = <0 0x200000>;
};
partition@400000 {
label = "Filesystem";
reg = <0x200000 0xce0000>;
};
};
};
&ap_pinctl {
/* MPP Bus:
* SDIO [0-5]
* UART0 [11,19]
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 1 1 1 1 1 1 0 0 0 0
0 3 0 0 0 0 0 0 0 3 >;
};
&uart0 {
@ -108,11 +86,37 @@
};
&cpm_i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&cpm_i2c0_pins>;
status = "okay";
clock-frequency = <100000>;
};
&cpm_pinctl {
/* MPP Bus:
* TDM [0-11]
* SPI [13-16]
* SATA1 [28]
* UART0 [29-30]
* SMI [32,34]
* XSMI [35-36]
* I2C [37-38]
* RGMII1[44-55]
* SD [56-62]
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 4 4 4 4 4 4 4 4 4 4
4 4 0 3 3 3 3 0 0 0
0 0 0 0 0 0 0 0 9 0xA
0xA 0 7 0 7 7 7 2 2 0
0 0 0 0 1 1 1 1 1 1
1 1 1 1 1 1 0xE 0xE 0xE 0xE
0xE 0xE 0xE >;
};
&cpm_spi1 {
pinctrl-names = "default";
pinctrl-0 = <&cpm_spi0_pins>;
status = "okay";
spi-flash@0 {

@ -57,7 +57,7 @@
aliases {
i2c0 = &cpm_i2c0;
spi0 = &spi0;
spi0 = &cps_spi1;
};
memory@00000000 {
@ -66,50 +66,55 @@
};
};
&i2c0 {
/* Accessible over the mini-USB CON9 connector on the main board */
&uart0 {
status = "okay";
clock-frequency = <100000>;
};
&spi0 {
status = "okay";
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <10000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "U-Boot";
reg = <0 0x200000>;
};
partition@400000 {
label = "Filesystem";
reg = <0x200000 0xce0000>;
};
};
};
&ap_pinctl {
/* MPP Bus:
* SDIO [0-10]
* UART0 [11,19]
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 1 1 1 1 1 1 1 1 1 1
1 3 0 0 0 0 0 0 0 3 >;
};
/* Accessible over the mini-USB CON9 connector on the main board */
&uart0 {
status = "okay";
&cpm_pinctl {
/* MPP Bus:
* [0-31] = 0xff: Keep default CP0_shared_pins:
* [11] CLKOUT_MPP_11 (out)
* [23] LINK_RD_IN_CP2CP (in)
* [25] CLKOUT_MPP_25 (out)
* [29] AVS_FB_IN_CP2CP (in)
* [32,34] SMI
* [31] GPIO: push button/Wake
* [35-36] GPIO
* [37-38] I2C
* [40-41] SATA[0/1]_PRESENT_ACTIVEn
* [42-43] XSMI
* [44-55] RGMII1
* [56-62] SD
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0 7 0 7 0 0 2 2 0
0 0 8 8 1 1 1 1 1 1
1 1 1 1 1 1 0xe 0xe 0xe 0xe
0xe 0xe 0xe >;
};
/* CON5 on CP0 expansion */
&cpm_pcie2 {
status = "okay";
};
&cpm_i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&cpm_i2c0_pins>;
status = "okay";
clock-frequency = <100000>;
};
@ -129,14 +134,55 @@
status = "okay";
};
&cps_pinctl {
/* MPP Bus:
* [0-11] RGMII0
* [13-16] SPI1
* [27,31] GE_MDIO/MDC
* [32-62] = 0xff: Keep default CP1_shared_pins:
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3
0x3 0x3 0xff 0x3 0x3 0x3 0x3 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x8 0xff 0xff
0xff 0x8 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff >;
};
/* CON5 on CP1 expansion */
&cps_pcie2 {
status = "okay";
};
&cps_i2c0 {
&cps_spi1 {
pinctrl-names = "default";
pinctrl-0 = <&cps_spi1_pins>;
status = "okay";
clock-frequency = <100000>;
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <10000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "U-Boot";
reg = <0 0x200000>;
};
partition@400000 {
label = "Filesystem";
reg = <0x200000 0xce0000>;
};
};
};
};
/* CON4 on CP1 expansion */

@ -140,6 +140,24 @@
marvell,spi-base = <128>, <136>, <144>, <152>;
};
ap_pinctl: ap-pinctl@6F4000 {
compatible = "marvell,armada-ap806-pinctrl";
bank-name ="apn-806";
reg = <0x6F4000 0x10>;
pin-count = <20>;
max-func = <3>;
ap_i2c0_pins: i2c-pins-0 {
marvell,pins = < 4 5 >;
marvell,function = <3>;
};
ap_emmc_pins: emmc-pins-0 {
marvell,pins = < 0 1 2 3 4 5 6 7
8 9 10 >;
marvell,function = <1>;
};
};
xor@400000 {
compatible = "marvell,mv-xor-v2";
reg = <0x400000 0x1000>,

@ -81,6 +81,38 @@
"cpm-usb3dev", "cpm-eip150", "cpm-eip197";
};
cpm_pinctl: cpm-pinctl@440000 {
compatible = "marvell,mvebu-pinctrl",
"marvell,a70x0-pinctrl",
"marvell,a80x0-cp0-pinctrl";
bank-name ="cp0-110";
reg = <0x440000 0x20>;
pin-count = <63>;
max-func = <0xf>;
cpm_i2c0_pins: cpm-i2c-pins-0 {
marvell,pins = < 37 38 >;
marvell,function = <2>;
};
cpm_ge2_rgmii_pins: cpm-ge-rgmii-pins-0 {
marvell,pins = < 44 45 46 47 48 49 50 51
52 53 54 55 >;
marvell,function = <1>;
};
pca0_pins: cpm-pca0_pins {
marvell,pins = <62>;
marvell,function = <0>;
};
cpm_sdhci_pins: cpm-sdhi-pins-0 {
marvell,pins = < 56 57 58 59 60 61 >;
marvell,function = <14>;
};
cpm_spi0_pins: cpm-spi-pins-0 {
marvell,pins = < 13 14 15 16 >;
marvell,function = <3>;
};
};
cpm_sata0: sata@540000 {
compatible = "marvell,armada-8k-ahci";
reg = <0x540000 0x30000>;

@ -81,6 +81,25 @@
"cps-usb3dev", "cps-eip150", "cps-eip197";
};
cps_pinctl: cps-pinctl@440000 {
compatible = "marvell,mvebu-pinctrl",
"marvell,a80x0-cp1-pinctrl";
bank-name ="cp1-110";
reg = <0x440000 0x20>;
pin-count = <63>;
max-func = <0xf>;
cps_ge1_rgmii_pins: cps-ge-rgmii-pins-0 {
marvell,pins = < 0 1 2 3 4 5 6 7
8 9 10 11 >;
marvell,function = <3>;
};
cps_spi1_pins: cps-spi-pins-1 {
marvell,pins = < 13 14 15 16 >;
marvell,function = <3>;
};
};
cps_sata0: sata@540000 {
compatible = "marvell,armada-8k-ahci";
reg = <0x540000 0x30000>;

@ -0,0 +1,21 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#ifndef _CACHE_LLC_H_
#define _CACHE_LLC_H_
/* Armada-7K/8K last level cache */
#define MVEBU_A8K_REGS_BASE_MSB 0xf000
#define LLC_BASE_ADDR 0x8000
#define LLC_CACHE_SYNC 0x700
#define LLC_CACHE_SYNC_COMPLETE 0x730
#define LLC_FLUSH_BY_WAY 0x7fc
#define LLC_WAY_MASK 0xffffffff
#define LLC_CACHE_SYNC_MASK 0x1
#endif /* _CACHE_LLC_H_ */

@ -0,0 +1,17 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#ifndef _SOC_INFO_H_
#define _SOC_INFO_H_
/* Pin Ctrl driver definitions */
#define BITS_PER_PIN 4
#define PIN_FUNC_MASK ((1 << BITS_PER_PIN) - 1)
#define PIN_REG_SHIFT 3
#define PIN_FIELD_MASK ((1 << PIN_REG_SHIFT) - 1)
#endif /* _SOC_INFO_H_ */

@ -5,3 +5,4 @@
#
obj-y = cpu.o
obj-y += cache_llc.o

@ -0,0 +1,39 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#include <asm/arch-armada8k/cache_llc.h>
#include <linux/linkage.h>
/*
* int __asm_flush_l3_dcache
*
* flush Armada-8K last level cache.
*
*/
ENTRY(__asm_flush_l3_dcache)
/* flush cache */
mov x0, #LLC_BASE_ADDR
add x0, x0, #LLC_FLUSH_BY_WAY
movk x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
mov w1, #LLC_WAY_MASK
str w1, [x0]
/* sync cache */
mov x0, #LLC_BASE_ADDR
add x0, x0, #LLC_CACHE_SYNC
movk x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
str wzr, [x0]
/* check that cache sync completed */
mov x0, #LLC_BASE_ADDR
add x0, x0, #LLC_CACHE_SYNC_COMPLETE
movk x0, #MVEBU_A8K_REGS_BASE_MSB, lsl #16
1: ldr w1, [x0]
and w1, w1, #LLC_CACHE_SYNC_MASK
cbnz w1, 1b
/* return success */
mov x0, #0
ret
ENDPROC(__asm_flush_l3_dcache)

@ -653,6 +653,9 @@ config CMD_QFW
This provides access to the QEMU firmware interface. The main
feature is to allow easy loading of files passed to qemu-system
via -kernel / -initrd
source "cmd/mvebu/Kconfig"
endmenu
config CMD_BOOTSTAGE

@ -163,3 +163,5 @@ obj-$(CONFIG_CMD_BLOB) += blob.o
# core command
obj-y += nvedit.o
obj-$(CONFIG_ARCH_MVEBU) += mvebu/

@ -0,0 +1,52 @@
menu "MVEBU commands"
depends on ARCH_MVEBU
config CMD_MVEBU_BUBT
bool "bubt"
default n
help
bubt - Burn a u-boot image to flash
For details about bubt command please see the documentation
in doc/mvebu/cmd/bubt.txt
choice
prompt "Flash for image"
default MVEBU_SPI_BOOT
config MVEBU_NAND_BOOT
bool "NAND flash boot"
depends on NAND_PXA3XX
help
Enable boot from NAND flash.
Allow usage of NAND flash as a target for "bubt" command
For details about bubt command please see the documentation
in doc/mvebu/cmd/bubt.txt
config MVEBU_SPI_BOOT
bool "SPI flash boot"
depends on SPI_FLASH
help
Enable boot from SPI flash.
Allow usage of SPI flash as a target for "bubt" command
For details about bubt command please see the documentation
in doc/mvebu/cmd/bubt.txt
config MVEBU_MMC_BOOT
bool "eMMC flash boot"
depends on MVEBU_MMC
help
Enable boot from eMMC boot partition
Allow usage of eMMC/SD device as a target for "bubt" command
For details about bubt command please see the documentation
in doc/mvebu/cmd/bubt.txt
endchoice
config MVEBU_UBOOT_DFLT_NAME
string "Default image name for bubt command"
default "flash-image.bin"
help
This option should contain a default file name to be used with
MVEBU "bubt" command if the source file name is omitted
endmenu

@ -0,0 +1,8 @@
#
# Copyright (C) 2016 Marvell International Ltd.
#
# SPDX-License-Identifier: GPL-2.0
# https://spdx.org/licenses
obj-$(CONFIG_CMD_MVEBU_BUBT) += bubt.o

@ -0,0 +1,767 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#include <config.h>
#include <common.h>
#include <command.h>
#include <vsprintf.h>
#include <errno.h>
#include <dm.h>
#include <spi_flash.h>
#include <spi.h>
#include <nand.h>
#include <usb.h>
#include <fs.h>
#include <mmc.h>
#include <u-boot/sha1.h>
#include <u-boot/sha256.h>
#ifndef CONFIG_SYS_MMC_ENV_DEV
#define CONFIG_SYS_MMC_ENV_DEV 0
#endif
#if defined(CONFIG_ARMADA_8K)
#define MAIN_HDR_MAGIC 0xB105B002
struct mvebu_image_header {
u32 magic; /* 0-3 */
u32 prolog_size; /* 4-7 */
u32 prolog_checksum; /* 8-11 */
u32 boot_image_size; /* 12-15 */
u32 boot_image_checksum; /* 16-19 */
u32 rsrvd0; /* 20-23 */
u32 load_addr; /* 24-27 */
u32 exec_addr; /* 28-31 */
u8 uart_cfg; /* 32 */
u8 baudrate; /* 33 */
u8 ext_count; /* 34 */
u8 aux_flags; /* 35 */
u32 io_arg_0; /* 36-39 */
u32 io_arg_1; /* 40-43 */
u32 io_arg_2; /* 43-47 */
u32 io_arg_3; /* 48-51 */
u32 rsrvd1; /* 52-55 */
u32 rsrvd2; /* 56-59 */
u32 rsrvd3; /* 60-63 */
};
#elif defined(CONFIG_ARMADA_3700) /* A3700 */
#define HASH_SUM_LEN 16
#define IMAGE_VERSION_3_6_0 0x030600
#define IMAGE_VERSION_3_5_0 0x030500
struct common_tim_data {
u32 version;
u32 identifier;
u32 trusted;
u32 issue_date;
u32 oem_unique_id;
u32 reserved[5]; /* Reserve 20 bytes */
u32 boot_flash_sign;
u32 num_images;
u32 num_keys;
u32 size_of_reserved;
};
struct mvebu_image_info {
u32 image_id;
u32 next_image_id;
u32 flash_entry_addr;
u32 load_addr;
u32 image_size;
u32 image_size_to_hash;
u32 hash_algorithm_id;
u32 hash[HASH_SUM_LEN]; /* Reserve 512 bits for the hash */
u32 partition_number;
u32 enc_algorithm_id;
u32 encrypt_start_offset;
u32 encrypt_size;
};
#endif /* CONFIG_ARMADA_XXX */
struct bubt_dev {
char name[8];
size_t (*read)(const char *file_name);
int (*write)(size_t image_size);
int (*active)(void);
};
static ulong get_load_addr(void)
{
const char *addr_str;
unsigned long addr;
addr_str = getenv("loadaddr");
if (addr_str)
addr = simple_strtoul(addr_str, NULL, 16);
else
addr = CONFIG_SYS_LOAD_ADDR;
return addr;
}
/********************************************************************
* eMMC services
********************************************************************/
#ifdef CONFIG_DM_MMC
static int mmc_burn_image(size_t image_size)
{
struct mmc *mmc;
lbaint_t start_lba;
lbaint_t blk_count;
ulong blk_written;
int err;
const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
mmc = find_mmc_device(mmc_dev_num);
if (!mmc) {
printf("No SD/MMC/eMMC card found\n");
return -ENOMEDIUM;
}
err = mmc_init(mmc);
if (err) {
printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
mmc_dev_num);
return err;
}
#ifdef CONFIG_SYS_MMC_ENV_PART
if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART) {
err = mmc_switch_part(mmc_dev_num, CONFIG_SYS_MMC_ENV_PART);
if (err) {
printf("MMC partition switch failed\n");
return err;
}
}
#endif
/* SD reserves LBA-0 for MBR and boots from LBA-1,
* MMC/eMMC boots from LBA-0
*/
start_lba = IS_SD(mmc) ? 1 : 0;
blk_count = image_size / mmc->block_dev.blksz;
if (image_size % mmc->block_dev.blksz)
blk_count += 1;
blk_written = mmc->block_dev.block_write(mmc_dev_num,
start_lba, blk_count,
(void *)get_load_addr());
if (blk_written != blk_count) {
printf("Error - written %#lx blocks\n", blk_written);
return -ENOSPC;
}
printf("Done!\n");
#ifdef CONFIG_SYS_MMC_ENV_PART
if (mmc->part_num != CONFIG_SYS_MMC_ENV_PART)
mmc_switch_part(mmc_dev_num, mmc->part_num);
#endif
return 0;
}
static size_t mmc_read_file(const char *file_name)
{
loff_t act_read = 0;
int rc;
struct mmc *mmc;
const u8 mmc_dev_num = CONFIG_SYS_MMC_ENV_DEV;
mmc = find_mmc_device(mmc_dev_num);
if (!mmc) {
printf("No SD/MMC/eMMC card found\n");
return 0;
}
if (mmc_init(mmc)) {
printf("%s(%d) init failed\n", IS_SD(mmc) ? "SD" : "MMC",
mmc_dev_num);
return 0;
}
/* Load from data partition (0) */
if (fs_set_blk_dev("mmc", "0", FS_TYPE_ANY)) {
printf("Error: MMC 0 not found\n");
return 0;
}
/* Perfrom file read */
rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
if (rc)
return 0;
return act_read;
}
static int is_mmc_active(void)
{
return 1;
}
#else /* CONFIG_DM_MMC */
static int mmc_burn_image(size_t image_size)
{
return -ENODEV;
}
static size_t mmc_read_file(const char *file_name)
{
return 0;
}
static int is_mmc_active(void)
{
return 0;
}
#endif /* CONFIG_DM_MMC */
/********************************************************************
* SPI services
********************************************************************/
#ifdef CONFIG_SPI_FLASH
static int spi_burn_image(size_t image_size)
{
int ret;
struct spi_flash *flash;
u32 erase_bytes;
/* Probe the SPI bus to get the flash device */
flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
CONFIG_ENV_SPI_CS,
CONFIG_SF_DEFAULT_SPEED,
CONFIG_SF_DEFAULT_MODE);
if (!flash) {
printf("Failed to probe SPI Flash\n");
return -ENOMEDIUM;
}
#ifdef CONFIG_SPI_FLASH_PROTECTION
spi_flash_protect(flash, 0);
#endif
erase_bytes = image_size +
(flash->erase_size - image_size % flash->erase_size);
printf("Erasing %d bytes (%d blocks) at offset 0 ...",
erase_bytes, erase_bytes / flash->erase_size);
ret = spi_flash_erase(flash, 0, erase_bytes);
if (ret)
printf("Error!\n");
else
printf("Done!\n");
printf("Writing %d bytes from 0x%lx to offset 0 ...",
(int)image_size, get_load_addr());
ret = spi_flash_write(flash, 0, image_size, (void *)get_load_addr());
if (ret)
printf("Error!\n");
else
printf("Done!\n");
#ifdef CONFIG_SPI_FLASH_PROTECTION
spi_flash_protect(flash, 1);
#endif
return ret;
}
static int is_spi_active(void)
{
return 1;
}
#else /* CONFIG_SPI_FLASH */
static int spi_burn_image(size_t image_size)
{
return -ENODEV;
}
static int is_spi_active(void)
{
return 0;
}
#endif /* CONFIG_SPI_FLASH */
/********************************************************************
* NAND services
********************************************************************/
#ifdef CONFIG_CMD_NAND
static int nand_burn_image(size_t image_size)
{
int ret, block_size;
nand_info_t *nand;
int dev = nand_curr_device;
if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
(!nand_info[dev].name)) {
puts("\nno devices available\n");
return -ENOMEDIUM;
}
nand = &nand_info[dev];
block_size = nand->erasesize;
/* Align U-Boot size to currently used blocksize */
image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
/* Erase the U-BOOT image space */
printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
ret = nand_erase(nand, 0, image_size);
if (ret) {
printf("Error!\n");
goto error;
}
printf("Done!\n");
/* Write the image to flash */
printf("Writing image:...");
printf("&image_size = 0x%p\n", (void *)&image_size);
ret = nand_write(nand, 0, &image_size, (void *)get_load_addr());
if (ret)
printf("Error!\n");
else
printf("Done!\n");
error:
return ret;
}
static int is_nand_active(void)
{
return 1;
}
#else /* CONFIG_CMD_NAND */
static int nand_burn_image(size_t image_size)
{
return -ENODEV;
}
static int is_nand_active(void)
{
return 0;
}
#endif /* CONFIG_CMD_NAND */
/********************************************************************
* USB services
********************************************************************/
#if defined(CONFIG_USB_STORAGE) && defined(CONFIG_BLK)
static size_t usb_read_file(const char *file_name)
{
loff_t act_read = 0;
struct udevice *dev;
int rc;
usb_stop();
if (usb_init() < 0) {
printf("Error: usb_init failed\n");
return 0;
}
/* Try to recognize storage devices immediately */
blk_first_device(IF_TYPE_USB, &dev);
if (!dev) {
printf("Error: USB storage device not found\n");
return 0;
}
/* Always load from usb 0 */
if (fs_set_blk_dev("usb", "0", FS_TYPE_ANY)) {
printf("Error: USB 0 not found\n");
return 0;
}
/* Perfrom file read */
rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read);
if (rc)
return 0;
return act_read;
}
static int is_usb_active(void)
{
return 1;
}
#else /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
static size_t usb_read_file(const char *file_name)
{
return 0;
}
static int is_usb_active(void)
{
return 0;
}
#endif /* defined(CONFIG_USB_STORAGE) && defined (CONFIG_BLK) */
/********************************************************************
* Network services
********************************************************************/
#ifdef CONFIG_CMD_NET
static size_t tftp_read_file(const char *file_name)
{
/* update global variable load_addr before tftp file from network */
load_addr = get_load_addr();
return net_loop(TFTPGET);
}
static int is_tftp_active(void)
{
return 1;
}
#else
static size_t tftp_read_file(const char *file_name)
{
return 0;
}
static int is_tftp_active(void)
{
return 0;
}
#endif /* CONFIG_CMD_NET */
enum bubt_devices {
BUBT_DEV_NET = 0,
BUBT_DEV_USB,
BUBT_DEV_MMC,
BUBT_DEV_SPI,
BUBT_DEV_NAND,
BUBT_MAX_DEV
};
struct bubt_dev bubt_devs[BUBT_MAX_DEV] = {
{"tftp", tftp_read_file, NULL, is_tftp_active},
{"usb", usb_read_file, NULL, is_usb_active},
{"mmc", mmc_read_file, mmc_burn_image, is_mmc_active},
{"spi", NULL, spi_burn_image, is_spi_active},
{"nand", NULL, nand_burn_image, is_nand_active},
};
static int bubt_write_file(struct bubt_dev *dst, size_t image_size)
{
if (!dst->write) {
printf("Error: Write not supported on device %s\n", dst->name);
return -ENOTSUPP;
}
return dst->write(image_size);
}
#if defined(CONFIG_ARMADA_8K)
u32 do_checksum32(u32 *start, int32_t len)
{
u32 sum = 0;
u32 *startp = start;
do {
sum += *startp;
startp++;
len -= 4;
} while (len > 0);
return sum;
}
static int check_image_header(void)
{
struct mvebu_image_header *hdr =
(struct mvebu_image_header *)get_load_addr();
u32 header_len = hdr->prolog_size;
u32 checksum;
u32 checksum_ref = hdr->prolog_checksum;
/*
* For now compare checksum, and magic. Later we can
* verify more stuff on the header like interface type, etc
*/
if (hdr->magic != MAIN_HDR_MAGIC) {
printf("ERROR: Bad MAGIC 0x%08x != 0x%08x\n",
hdr->magic, MAIN_HDR_MAGIC);
return -ENOEXEC;
}
/* The checksum value is discarded from checksum calculation */
hdr->prolog_checksum = 0;
checksum = do_checksum32((u32 *)hdr, header_len);
if (checksum != checksum_ref) {
printf("Error: Bad Image checksum. 0x%x != 0x%x\n",
checksum, checksum_ref);
return -ENOEXEC;
}
/* Restore the checksum before writing */
hdr->prolog_checksum = checksum_ref;
printf("Image checksum...OK!\n");
return 0;
}
#elif defined(CONFIG_ARMADA_3700) /* Armada 3700 */
static int check_image_header(void)
{
struct common_tim_data *hdr = (struct common_tim_data *)get_load_addr();
int image_num;
u8 hash_160_output[SHA1_SUM_LEN];
u8 hash_256_output[SHA256_SUM_LEN];
sha1_context hash1_text;
sha256_context hash256_text;
u8 *hash_output;
u32 hash_algorithm_id;
u32 image_size_to_hash;
u32 flash_entry_addr;
u32 *hash_value;
u32 internal_hash[HASH_SUM_LEN];
const u8 *buff;
u32 num_of_image = hdr->num_images;
u32 version = hdr->version;
u32 trusted = hdr->trusted;
/* bubt checksum validation only supports nontrusted images */
if (trusted == 1) {
printf("bypass image validation, ");
printf("only untrusted image is supported now\n");
return 0;
}
/* only supports image version 3.5 and 3.6 */
if (version != IMAGE_VERSION_3_5_0 && version != IMAGE_VERSION_3_6_0) {
printf("Error: Unsupported Image version = 0x%08x\n", version);
return -ENOEXEC;
}
/* validate images hash value */
for (image_num = 0; image_num < num_of_image; image_num++) {
struct mvebu_image_info *info =
(struct mvebu_image_info *)(get_load_addr() +
sizeof(struct common_tim_data) +
image_num * sizeof(struct mvebu_image_info));
hash_algorithm_id = info->hash_algorithm_id;
image_size_to_hash = info->image_size_to_hash;
flash_entry_addr = info->flash_entry_addr;
hash_value = info->hash;
buff = (const u8 *)(get_load_addr() + flash_entry_addr);
if (image_num == 0) {
/*
* The first image includes hash values in its content.
* For hash calculation, we need to save the original
* hash values to a local variable that will be
* copied back for comparsion and set all zeros to
* the orignal hash values for calculating new value.
* First image original format :
* x...x (datum1) x...x(orig. hash values) x...x(datum2)
* Replaced first image format :
* x...x (datum1) 0...0(hash values) x...x(datum2)
*/
memcpy(internal_hash, hash_value,
sizeof(internal_hash));
memset(hash_value, 0, sizeof(internal_hash));
}
if (image_size_to_hash == 0) {
printf("Warning: Image_%d hash checksum is disabled, ",
image_num);
printf("skip the image validation.\n");
continue;
}
switch (hash_algorithm_id) {
case SHA1_SUM_LEN:
sha1_starts(&hash1_text);
sha1_update(&hash1_text, buff, image_size_to_hash);
sha1_finish(&hash1_text, hash_160_output);
hash_output = hash_160_output;
break;
case SHA256_SUM_LEN:
sha256_starts(&hash256_text);
sha256_update(&hash256_text, buff, image_size_to_hash);
sha256_finish(&hash256_text, hash_256_output);
hash_output = hash_256_output;
break;
default:
printf("Error: Unsupported hash_algorithm_id = %d\n",
hash_algorithm_id);
return -ENOEXEC;
}
if (image_num == 0)
memcpy(hash_value, internal_hash,
sizeof(internal_hash));
if (memcmp(hash_value, hash_output, hash_algorithm_id) != 0) {
printf("Error: Image_%d checksum is not correct\n",
image_num);
return -ENOEXEC;
}
}
printf("Image checksum...OK!\n");
return 0;
}
#else /* Not ARMADA? */
static int check_image_header(void)
{
printf("bubt cmd does not support this SoC device or family!\n");
return -ENOEXEC;
}
#endif
static int bubt_verify(size_t image_size)
{
int err;
/* Check a correct image header exists */
err = check_image_header();
if (err) {
printf("Error: Image header verification failed\n");
return err;
}
return 0;
}
static int bubt_read_file(struct bubt_dev *src)
{
size_t image_size;
if (!src->read) {
printf("Error: Read not supported on device \"%s\"\n",
src->name);
return 0;
}
image_size = src->read(net_boot_file_name);
if (image_size <= 0) {
printf("Error: Failed to read file %s from %s\n",
net_boot_file_name, src->name);
return 0;
}
return image_size;
}
static int bubt_is_dev_active(struct bubt_dev *dev)
{
if (!dev->active) {
printf("Device \"%s\" not supported by U-BOOT image\n",
dev->name);
return 0;
}
if (!dev->active()) {
printf("Device \"%s\" is inactive\n", dev->name);
return 0;
}
return 1;
}
struct bubt_dev *find_bubt_dev(char *dev_name)
{
int dev;
for (dev = 0; dev < BUBT_MAX_DEV; dev++) {
if (strcmp(bubt_devs[dev].name, dev_name) == 0)
return &bubt_devs[dev];
}
return 0;
}
#define DEFAULT_BUBT_SRC "tftp"
#ifndef DEFAULT_BUBT_DST
#ifdef CONFIG_MVEBU_SPI_BOOT
#define DEFAULT_BUBT_DST "spi"
#elif defined(CONFIG_MVEBU_NAND_BOOT)
#define DEFAULT_BUBT_DST "nand"
#elif defined(CONFIG_MVEBU_MMC_BOOT)
#define DEFAULT_BUBT_DST "mmc"
else
#define DEFAULT_BUBT_DST "error"
#endif
#endif /* DEFAULT_BUBT_DST */
int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct bubt_dev *src, *dst;
size_t image_size;
char src_dev_name[8];
char dst_dev_name[8];
char *name;
int err;
if (argc < 2)
copy_filename(net_boot_file_name,
CONFIG_MVEBU_UBOOT_DFLT_NAME,
sizeof(net_boot_file_name));
else
copy_filename(net_boot_file_name, argv[1],
sizeof(net_boot_file_name));
if (argc >= 3) {
strncpy(dst_dev_name, argv[2], 8);
} else {
name = DEFAULT_BUBT_DST;
strncpy(dst_dev_name, name, 8);
}
if (argc >= 4)
strncpy(src_dev_name, argv[3], 8);
else
strncpy(src_dev_name, DEFAULT_BUBT_SRC, 8);
/* Figure out the destination device */
dst = find_bubt_dev(dst_dev_name);
if (!dst) {
printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
return -EINVAL;
}
if (!bubt_is_dev_active(dst))
return -ENODEV;
/* Figure out the source device */
src = find_bubt_dev(src_dev_name);
if (!src) {
printf("Error: Unknown source \"%s\"\n", src_dev_name);
return 1;
}
if (!bubt_is_dev_active(src))
return -ENODEV;
printf("Burning U-BOOT image \"%s\" from \"%s\" to \"%s\"\n",
net_boot_file_name, src->name, dst->name);
image_size = bubt_read_file(src);
if (!image_size)
return -EIO;
err = bubt_verify(image_size);
if (err)
return err;
err = bubt_write_file(dst, image_size);
if (err)
return err;
return 0;
}
U_BOOT_CMD(
bubt, 4, 0, do_bubt_cmd,
"Burn a u-boot image to flash",
"[file-name] [destination [source]]\n"
"\t-file-name The image file name to burn. Default = flash-image.bin\n"
"\t-destination Flash to burn to [spi, nand, mmc]. Default = active boot device\n"
"\t-source The source to load image from [tftp, usb, mmc]. Default = tftp\n"
"Examples:\n"
"\tbubt - Burn flash-image.bin from tftp to active boot device\n"
"\tbubt flash-image-new.bin nand - Burn flash-image-new.bin from tftp to NAND flash\n"
"\tbubt backup-flash-image.bin mmc usb - Burn backup-flash-image.bin from usb to MMC\n"
);

@ -27,6 +27,7 @@ CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_CMD_MVEBU_BUBT=y
CONFIG_BLOCK_CACHE=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
@ -36,6 +37,9 @@ CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_PHYLIB=y
CONFIG_PCI=y
CONFIG_DM_PCI=y
CONFIG_PCIE_DW_MVEBU=y
CONFIG_MVEBU_COMPHY_SUPPORT=y
# CONFIG_SPL_SERIAL_PRESENT is not set
CONFIG_DEBUG_UART=y
@ -50,3 +54,5 @@ CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_SMBIOS_MANUFACTURER=""
CONFIG_PINCTRL=y
CONFIG_HUSH_PARSER=y

@ -27,6 +27,7 @@ CONFIG_CMD_EXT4=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_CMD_MVEBU_BUBT=y
CONFIG_BLOCK_CACHE=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_MVTWSI=y
@ -53,3 +54,5 @@ CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_SMBIOS_MANUFACTURER=""
CONFIG_PINCTRL=y
CONFIG_HUSH_PARSER=y

@ -0,0 +1,25 @@
Functions of Armada APN806 pin controller
Function 0x0 for any MPP ID activates GPIO pin mode
----------------------------------------------------------------------
MPP# 0x1 0x2 0x3 0x4
----------------------------------------------------------------------
0 SDIO_CLK - SPI0_CLK -
1 SDIO_CMD - SPI0_MISO -
2 SDIO_D[0] - SPI0_MOSI -
3 SDIO_D[1] - SPI0_CS0n -
4 SDIO_D[2] - I2C0_SDA SPI0_CS1n
5 SDIO_D[3] - I2C0_SCK -
6 SDIO_DS - - -
7 SDIO_D[4] - UART1_RXD -
8 SDIO_D[5] - UART1_TXD -
9 SDIO_D[6] - SPI0_CS1n -
10 SDIO_D[7] - - -
11 - - UART0_TXD -
12 SDIO_CARD_PW_OFF SDIO_HW_RST - -
13 - - - -
14 - - - -
15 - - - -
16 - - - -
17 - - - -
18 - - - -
19 - - UART0_RXD -

@ -0,0 +1,270 @@
Functions of Armada CP110 pin controller
Function 0x0 for any MPP ID activates GPIO pin mode
Function 0xc for any MPP ID activates DEBUG_BUS pin mode
-------------------------------------------------------------------------------
MPP# 0x1 0x2 0x3 0x4
-------------------------------------------------------------------------------
0 DEV_ALE[1] AU_I2SMCLK GE0_RXD[3] TDM_PCLK
1 DEV_ALE[0] AU_I2SDO_SPDIFO GE0_RXD[2] TDM_DRX
2 DEV_AD[15] AU_I2SEXTCLK GE0_RXD[1] TDM_DTX
3 DEV_AD[14] AU_I2SLRCLK GE0_RXD[0] TDM_FSYNC
4 DEV_AD[13] AU_I2SBCLK GE0_RXCTL TDM_RSTn
5 DEV_AD[12] AU_I2SDI GE0_RXCLK TDM_INTn
6 DEV_AD[11] - GE0_TXD[3] SPI0_CSn[2]
7 DEV_AD[10] - GE0_TXD[2] SPI0_CSn[1]
8 DEV_AD[9] - GE0_TXD[1] SPI0_CSn[0]
9 DEV_AD[8] - GE0_TXD[0] SPI0_MOSI
10 DEV_READYn - GE0_TXCTL SPI0_MISO
11 DEV_WEn[1] - GE0_TXCLKOUT SPI0_CLK
12 DEV_CLK_OUT NF_RBn[1] SPI1_CSn[1] GE0_RXCLK
13 DEV_BURSTn NF_RBn[0] SPI1_MISO GE0_RXCTL
14 DEV_BOOTCSn DEV_CSn[0] SPI1_CSn[0] SPI0_CSn[3]
15 DEV_AD[7] - SPI1_MOSI -
16 DEV_AD[6] - SPI1_CLK -
17 DEV_AD[5] - - GE0_TXD[3]
18 DEV_AD[4] - - GE0_TXD[2]
19 DEV_AD[3] - - GE0_TXD[1]
20 DEV_AD[2] - - GE0_TXD[0]
21 DEV_AD[1] - - GE0_TXCTL
22 DEV_AD[0] - - GE0_TXCLKOUT
23 DEV_A[1] - - -
24 DEV_A[0] - - -
25 DEV_OEn - - - -
26 DEV_WEn[0] - - -
27 DEV_CSn[0] SPI1_MISO MSS_GPIO[4] GE0_RXD[3]
28 DEV_CSn[1] SPI1_CSn[0] MSS_GPIO[5] GE0_RXD[2]
29 DEV_CSn[2] SPI1_MOSI MSS_GPIO[6] GE0_RXD[1]
30 DEV_CSn[3] SPI1_CLK MSS_GPIO[7] GE0_RXD[0]
31 DEV_A[2] - MSS_GPIO[4] -
32 MII_COL MII_TXERR MSS_SPI_MISO TDM_DRX
33 MII_TXCLK SDIO_PWR1[0] MSS_SPI_CSn TDM_FSYNC
34 MII_RXERR SDIO_PWR1[1] MSS_SPI_MOSI TDM_DTX
35 SATA1_PRESENT_ACTIVEn TWSI1_SDA MSS_SPI_CLK TDM_PCLK
36 SYNCE2_CLK TWSI1_SCK PTP_CLK SYNCE1_CLK
37 UART2_RXD TWSI0_SCK PTP_PCLK_OUT TDM_INTn
38 UART2_TXD TWSI0_SDA PTP_PULSE TDM_RSTn
39 SDIO_WR_PROTECT - - AU_I2SBCLK PTP_CLK
40 SDIO_PWR1[1] SYNCE1_CLK MSS_TWSI_SDA AU_I2SDO_SPDIFO
41 SDIO_PWR1[0] SDIO_BUS_PWR MSS_TWSI_SCK AU_I2SLRCLK
42 SDIO_V18_EN SDIO_WR_PROTECT SYNCE2_CLK AU_I2SMCLK
43 SDIO_CARD_DETECT - SYNCE1_CLK AU_I2SEXTCLK
44 GE1_TXD[2] - - -
45 GE1_TXD[3] - - -
46 GE1_TXD[1] - - -
47 GE1_TXD[0] - - -
48 GE1_TXCTL_MII_TXEN - - -
49 GE1_TXCLKOUT MII_CRS - -
50 GE1_RXCLK MSS_TWSI_SDA - -
51 GE1_RXD[0] MSS_TWSI_SCK - -
52 GE1_RXD[1] SYNCE1_CLK - SYNCE2_CLK
53 GE1_RXD[2] - PTP_CLK -
54 GE1_RXD[3] SYNCE2_CLK PTP_PCLK_OUT SYNCE1_CLK
55 GE1_RXCTL_MII_RXDV - PTP_PULSE -
56 - - - TDM_DRX
57 - MSS_TWSI_SDA PTP_PCLK_OUT TDM_INTn
58 - MSS_TWSI_SCK PTP_CLK TDM_RSTn
59 MSS_GPIO[7] SYNCE2_CLK - TDM_FSYNC
60 MSS_GPIO[6] - PTP_PULSE TDM_DTX
61 MSS_GPIO[5] - PTP_CLK TDM_PCLK
62 MSS_GPIO[4] SYNCE1_CLK PTP_PCLK_OUT -
-------------------------------------------------------------------------------
MPP# 0x5 0x6 0x7
-------------------------------------------------------------------------------
0 - PTP_PULSE MSS_TWSI_SDA
1 - PTP_CLK MSS_TWSI_SCK
2 MSS_UART_RXD PTP_PCLK_OUT TWSI1_SCK
3 MSS_UART_TXD PCIe_RSTOUTn TWSI1_SDA
4 MSS_UART_RXD UART1_CTS PCIe0_CLKREQ
5 MSS_UART_TXD UART1_RTS PCIe1_CLKREQ
6 AU_I2SEXTCLK SATA1_PRESENT_ACTIVEn PCIe2_CLKREQ
7 SPI1_CSn[1] SATA0_PRESENT_ACTIVEn LED_DATA
8 SPI1_CSn[0] UART0_CTS LED_STB
9 SPI1_MOSI - PCIe_RSTOUTn
10 SPI1_MISO UART0_CTS SATA1_PRESENT_ACTIVEn
11 SPI1_CLK UART0_RTS LED_CLK
12 - - -
13 - - -
14 AU_I2SEXTCLK SPI0_MISO SATA0_PRESENT_ACTIVEn
15 - SPI0_MOSI -
16 - - -
17 - - -
18 - - -
19 - - -
20 - - -
21 - - -
22 - - -
23 AU_I2SMCLK - -
24 AU_I2SLRCLK - -
25 AU_I2SDO_SPDIFO - -
26 AU_I2SBCLK - -
27 SPI0_CSn[4] - -
28 SPI0_CSn[5] PCIe2_CLKREQ PTP_PULSE
29 SPI0_CSn[6] PCIe1_CLKREQ PTP_CLK
30 SPI0_CSn[7] PCIe0_CLKREQ PTP_PCLK_OUT
31 - PCIe_RSTOUTn -
32 AU_I2SEXTCLK AU_I2SDI GE_MDIO
33 AU_I2SMCLK SDIO_BUS_PWR -
34 AU_I2SLRCLK SDIO_WR_PROTECT GE_MDC
35 AU_I2SDO_SPDIFO SDIO_CARD_DETECT XG_MDIO
36 AU_I2SBCLK SATA0_PRESENT_ACTIVEn XG_MDC
37 MSS_TWSI_SCK SATA1_PRESENT_ACTIVEn GE_MDC
38 MSS_TWSI_SDA SATA0_PRESENT_ACTIVEn GE_MDIO
39 SPI0_CSn[1] - -
40 PTP_PCLK_OUT SPI0_CLK UART1_TXD
41 PTP_PULSE SPI0_MOSI UART1_RXD
42 MSS_UART_TXD SPI0_MISO UART1_CTS
43 MSS_UART_RXD SPI0_CSn[0] UART1_RTS
44 - - UART0_RTS
45 - - UART0_TXD
46 - - UART1_RTS
47 SPI1_CLK - UART1_TXD
48 SPI1_MOSI - -
49 SPI1_MISO - UART1_RXD
50 SPI1_CSn[0] UART2_TXD UART0_RXD
51 SPI1_CSn[1] UART2_RXD UART0_CTS
52 SPI1_CSn[2] - UART1_CTS
53 SPI1_CSn[3] - UART1_RXD
54 - - -
55 - - -
56 AU_I2SDO_SPDIFO SPI0_CLK UART1_RXD
57 AU_I2SBCLK SPI0_MOSI UART1_TXD
58 AU_I2SDI SPI0_MISO UART1_CTS
59 AU_I2SLRCLK SPI0_CSn[0] UART0_CTS
60 AU_I2SMCLK SPI0_CSn[1] UART0_RTS
61 AU_I2SEXTCLK SPI0_CSn[2] UART0_TXD
62 SATA1_PRESENT_ACTIVEn SPI0_CSn[3] UART0_RXD
-------------------------------------------------------------------------------
MPP# 0x8 0x9 0xA
-------------------------------------------------------------------------------
0 UART0_RXD SATA0_PRESENT_ACTIVEn GE_MDIO
1 UART0_TXD SATA1_PRESENT_ACTIVEn GE_MDC
2 UART1_RXD SATA0_PRESENT_ACTIVEn XG_MDC
3 UART1_TXD SATA1_PRESENT_ACTIVEn XG_MDIO
4 UART3_RXD - GE_MDC
5 UART3_TXD - GE_MDIO
6 UART0_RXD PTP_PULSE -
7 UART0_TXD PTP_CLK -
8 UART2_RXD PTP_PCLK_OUT SYNCE1_CLK
9 - - SYNCE2_CLK
10 - - -
11 UART2_TXD SATA0_PRESENT_ACTIVEn -
12 - - -
13 MSS_SPI_MISO - -
14 MSS_SPI_CSn - -
15 MSS_SPI_MOSI - -
16 MSS_SPI_CLK - -
17 - - -
18 - - -
19 - - -
20 - - -
21 - - -
22 - - -
23 - - -
24 - - -
25 - - -
26 - - -
27 GE_MDIO SATA0_PRESENT_ACTIVEn UART0_RTS
28 GE_MDC SATA1_PRESENT_ACTIVEn UART0_CTS
29 MSS_TWSI_SDA SATA0_PRESENT_ACTIVEn UART0_RXD
30 MSS_TWSI_SCK SATA1_PRESENT_ACTIVEn UART0_TXD
31 GE_MDC - -
32 SDIO_V18_EN PCIe1_CLKREQ MSS_GPIO[0]
33 XG_MDIO PCIe2_CLKREQ MSS_GPIO[1]
34 - PCIe0_CLKREQ MSS_GPIO[2]
35 GE_MDIO PCIe_RSTOUTn MSS_GPIO[3]
36 GE_MDC PCIe2_CLKREQ MSS_GPIO[5]
37 XG_MDC PCIe1_CLKREQ MSS_GPIO[6]
38 XG_MDIO AU_I2SEXTCLK MSS_GPIO[7]
39 SATA1_PRESENT_ACTIVEn MSS_GPIO[0]
40 GE_MDIO SATA0_PRESENT_ACTIVEn MSS_GPIO[1]
41 GE_MDC SATA1_PRESENT_ACTIVEn MSS_GPIO[2]
42 XG_MDC SATA0_PRESENT_ACTIVEn MSS_GPIO[4]
43 XG_MDIO SATA1_PRESENT_ACTIVEn MSS_GPIO[5]
44 - - -
45 - PCIe_RSTOUTn -
46 - - -
47 GE_MDC CLKOUT -
48 XG_MDC - -
49 GE_MDIO PCIe0_CLKREQ SDIO_V18_EN
50 XG_MDIO - SDIO_PWR1[1]
51 - - SDIO_PWR1[0]
52 LED_CLK PCIe_RSTOUTn PCIe0_CLKREQ
53 LED_STB - -
54 LED_DATA - SDIO_HW_RST
55 - - SDIO_LED
56 - SATA1_PRESENT_ACTIVEn -
57 - SATA0_PRESENT_ACTIVEn -
58 LED_CLK - -
59 LED_STB UART1_TXD -
60 LED_DATA UART1_RXD -
61 UART2_TXD SATA1_PRESENT_ACTIVEn GE_MDIO
62 UART2_RXD SATA0_PRESENT_ACTIVEn GE_MDC
-------------------------------------------------------------------------------
MPP# 0xB 0xD 0xE
-------------------------------------------------------------------------------
0 - - -
1 - - -
2 - - -
3 - - -
4 - - -
5 - - -
6 - - -
7 - - -
8 - - -
9 - - -
10 - - -
11 - CLKOUT_MPP_11 -
12 - - -
13 - - -
14 - - -
15 PTP_PULSE_CP2CP SAR_IN[5] -
16 - SAR_IN[3] -
17 - SAR_IN[6] -
18 PTP_CLK_CP2CP SAR_IN[11] -
19 WAKEUP_OUT_CP2CP SAR_IN[7] -
20 - SAR_IN[9] -
21 SEI_IN_CP2CP SAR_IN[8] -
22 WAKEUP_IN_CP2CP SAR_IN[10] -
23 LINK_RD_IN_CP2CP SAR_IN[4] -
24 - - -
25 - CLKOUT_MPP_25 -
26 - SAR_IN[0] -
27 REI_IN_CP2CP SAR_IN[1] -
28 LED_DATA SAR_IN[2] -
29 LED_STB AVS_FB_IN_CP2CP -
30 LED_CLK SAR_IN[13] -
31 - - -
32 - SAR_CP2CP_OUT[0] -
33 - SAR_CP2CP_OUT[1] -
34 - SAR_CP2CP_OUT[2] -
35 - SAR_CP2CP_OUT[3] -
36 - CLKIN -
37 LINK_RD_OUT_CP2CP SAR_CP2CP_OUT[4] -
38 PTP_PULSE_CP2CP SAR_CP2CP_OUT[5] -
39 - AVS_FB_OUT_CP2CP -
40 - - -
41 REI_OUT_CP2CP - -
42 - SAR_CP2CP_OUT[9] -
43 WAKEUP_OUT_CP2CP SAR_CP2CP_OUT[10] -
44 PTP_CLK_CP2CP SAR_CP2CP_OUT[11] -
45 - SAR_CP2CP_OUT[6] -
46 - SAR_CP2CP_OUT[13] -
47 - - -
48 WAKEUP_IN_CP2CP SAR_CP2CP_OUT[7] -
49 SEI_OUT_CP2CP SAR_CP2CP_OUT[8] -
50 - - -
51 - - -
52 - - -
53 SDIO_LED - -
54 SDIO_WR_PROTECT - -
55 SDIO_CARD_DETECT - -
56 - - SDIO0_CLK
57 - - SDIO0_CMD
58 - - SDIO0_D[0]
59 - - SDIO0_D[1]
60 - - SDIO0_D[2]
61 - - SDIO0_D[3]
62 - - -

@ -0,0 +1,113 @@
The pinctrl driver enables Marvell Armada 8K SoCs to configure the multi-purpose
pins (mpp) to a specific function.
A Marvell SoC pin configuration node is a node of a group of pins which can
be used for a specific device or function. Each node requires one or more
mpp pins or group of pins and a mpp function common to all pins.
Required properties for the pinctrl driver:
- compatible: "marvell,mvebu-pinctrl",
"marvell,armada-ap806-pinctrl",
"marvell,a70x0-pinctrl",
"marvell,a80x0-cp0-pinctrl",
"marvell,a80x0-cp1-pinctrl"
- bank-name: A string defining the pinc controller bank name
- reg: A pair of values defining the pin controller base address
and the address space
- pin-count: Numeric value defining the amount of multi purpose pins
included in this bank
- max-func: Numeric value defining the maximum function value for
pins in this bank
- pin-func: Array of pin function values for every pin in the bank.
When the function value for a specific pin equal 0xFF,
the pin configuration is skipped and a default function
value is used for this pin.
The A8K is a hybrid SoC that contains several silicon dies interconnected in
a single package. Each such die may have a separate pin controller.
Example:
/ {
ap806 {
config-space {
pinctl: pinctl@6F4000 {
compatible = "marvell,mvebu-pinctrl",
"marvell,armada-ap806-pinctrl";
bank-name ="apn-806";
reg = <0x6F4000 0x10>;
pin-count = <20>;
max-func = <3>;
/* MPP Bus:
* SPI0 [0-3]
* I2C0 [4-5]
* UART0 [11,19]
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 3 3 3 3 3 3 0 0 0 0
0 3 0 0 0 0 0 0 0 3>;
};
};
};
cp110-master {
config-space {
cpm_pinctl: pinctl@44000 {
compatible = "marvell,mvebu-pinctrl",
"marvell,a70x0-pinctrl",
"marvell,a80x0-cp0-pinctrl";
bank-name ="cp0-110";
reg = <0x440000 0x20>;
pin-count = <63>;
max-func = <0xf>;
/* MPP Bus:
* [0-31] = 0xff: Keep default CP0_shared_pins:
* [11] CLKOUT_MPP_11 (out)
* [23] LINK_RD_IN_CP2CP (in)
* [25] CLKOUT_MPP_25 (out)
* [29] AVS_FB_IN_CP2CP (in)
* [32,34] SMI
* [31] GPIO: push button/Wake
* [35-36] GPIO
* [37-38] I2C
* [40-41] SATA[0/1]_PRESENT_ACTIVEn
* [42-43] XSMI
* [44-55] RGMII1
* [56-62] SD
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0 7 0 7 0 0 2 2 0
0 0 8 8 1 1 1 1 1 1
1 1 1 1 1 1 0xE 0xE 0xE 0xE
0xE 0xE 0xE>;
};
};
};
cp110-slave {
config-space {
cps_pinctl: pinctl@44000 {
compatible = "marvell,mvebu-pinctrl",
"marvell,a80x0-cp1-pinctrl";
bank-name ="cp1-110";
reg = <0x440000 0x20>;
pin-count = <63>;
max-func = <0xf>;
/* MPP Bus:
* [0-11] RGMII0
* [27,31] GE_MDIO/MDC
* [32-62] = 0xff: Keep default CP1_shared_pins:
*/
/* 0 1 2 3 4 5 6 7 8 9 */
pin-func = < 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3 0x3
0x3 0x3 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x8 0xff 0xff
0xff 0x8 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
0xff 0xff 0xff>;
};
};
};
}

@ -0,0 +1,64 @@
BUBT (Burn ATF) command
--------------------------
Bubt command is used to burn a new ATF image to flash device.
The bubt command gets the following parameters: ATF file name, destination device and source device.
bubt [file-name] [destination [source]]
- file-name Image file name to burn. default = flash-image.bin
- destination Flash to burn to [spi, nand, mmc]. default = active flash
- source Source to load image from [tftp, usb]. default = tftp
Examples:
bubt - Burn flash-image.bin from tftp to active flash
bubt latest-spi.bin nand - Burn latest-spi.bin from tftp to NAND flash
Notes:
- For the TFTP interface set serverip and ipaddr.
- To burn image to SD/eMMC device, the target is defined
by parameters CONFIG_SYS_MMC_ENV_DEV and CONFIG_SYS_MMC_ENV_PART.
Bubt command details (burn image step by-step)
----------------------------------------------
This section describes bubt command flow:
1. Fetch the requested ATF image from an available interface (USB/SD/SATA/XDB, etc.)
into the DRAM, and place it at <load_address>
Example: when using the FAT file system on USB flash device:
# usb reset
# fatls usb 0 (see files in device)
# fatload usb 0 <load_address> <file_name>
2. Erase the target device:
- NAND: # nand erase 0 100000
- SPI: # sf probe 0
# sf erase 0 100000
- SD/eMMC: # mmc dev <dev_id> <boot_partition>
Notes:
- The eMMC has 2 boot partitions (BOOT0 and BOOT1) and a user data partition (DATA).
The boot partitions are numbered as partition 1 and 2 in MMC driver.
Number 0 is used for user data partition and should not be utilized for storing
boot images and U-Boot environment in RAW mode since it will break file system
structures usually located here.
The default boot partition is BOOT0. It is selected by the following parameter:
CONFIG_SYS_MMC_ENV_PART=1
Valid values for this parameter are 1 for BOOT0 and 2 for BOOT1.
Please never use partition number 0 here!
The eMMC has 2 boot partitions (BOOT0 and BOOT1) and a user data partition (DATA).
The boot partitions are numbered as partition 1 and 2 in MMC driver.
Number 0 is used for user data partition and should not be utilized for storing
boot images and U-Boot environment in RAW mode since it will break file system
structures usually located here.
The default boot partition is BOOT0. It is selected by the following parameter:
CONFIG_SYS_MMC_ENV_PART=1
Valid values for this parameter are 1 for BOOT0 and 2 for BOOT1.
Please never use partition number 0 here!
- The partition number is ignored if the target device is SD card.
- The boot image offset starts at block 0 for eMMC and block 1 for SD devices.
The block 0 on SD devices is left for MBR storage.
3. Write the ATF image:
- NAND: # nand write <load_address> 0 <ATF Size>
- SPI: # sf write <load_address> 0 <ATF Size>
- SD/eMMC: # mmc write <load_address> [0|1] <ATF Size>/<block_size>

@ -181,5 +181,6 @@ source "drivers/pinctrl/meson/Kconfig"
source "drivers/pinctrl/nxp/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/exynos/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
endmenu

@ -15,3 +15,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_PIC32_PINCTRL) += pinctrl_pic32.o
obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/
obj-$(CONFIG_PINCTRL_MESON) += meson/
obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/

@ -0,0 +1,7 @@
config PINCTRL_MVEBU
depends on ARCH_MVEBU
bool
default y
help
Support pin multiplexing and pin configuration control on
Marvell's Armada-8K SoC.

@ -0,0 +1,7 @@
#
# Copyright (C) 2016 Marvell International Ltd.
#
# SPDX-License-Identifier: GPL-2.0
# https://spdx.org/licenses
obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o

@ -0,0 +1,179 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#include <common.h>
#include <config.h>
#include <fdtdec.h>
#include <errno.h>
#include <dm.h>
#include <dm/pinctrl.h>
#include <dm/root.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/arch-armada8k/soc-info.h>
#include "pinctrl-mvebu.h"
DECLARE_GLOBAL_DATA_PTR;
/*
* mvebu_pinctrl_set_state: configure pin functions.
* @dev: the pinctrl device to be configured.
* @config: the state to be configured.
* @return: 0 in success
*/
int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config)
{
const void *blob = gd->fdt_blob;
int node = config->of_offset;
struct mvebu_pinctrl_priv *priv;
u32 pin_arr[MVEBU_MAX_PINS_PER_BANK];
u32 function;
int i, pin_count;
priv = dev_get_priv(dev);
pin_count = fdtdec_get_int_array_count(blob, node,
"marvell,pins",
pin_arr,
MVEBU_MAX_PINS_PER_BANK);
if (pin_count <= 0) {
debug("Failed reading pins array for pinconfig %s (%d)\n",
config->name, pin_count);
return -EINVAL;
}
function = fdtdec_get_int(blob, node, "marvell,function", 0xff);
for (i = 0; i < pin_count; i++) {
int reg_offset;
int field_offset;
int pin = pin_arr[i];
if (function > priv->max_func) {
debug("Illegal function %d for pinconfig %s\n",
function, config->name);
return -EINVAL;
}
/* Calculate register address and bit in register */
reg_offset = priv->reg_direction * 4 *
(pin >> (PIN_REG_SHIFT));
field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
clrsetbits_le32(priv->base_reg + reg_offset,
PIN_FUNC_MASK << field_offset,
(function & PIN_FUNC_MASK) << field_offset);
}
return 0;
}
/*
* mvebu_pinctrl_set_state_all: configure the entire bank pin functions.
* @dev: the pinctrl device to be configured.
* @config: the state to be configured.
* @return: 0 in success
*/
static int mvebu_pinctrl_set_state_all(struct udevice *dev,
struct udevice *config)
{
const void *blob = gd->fdt_blob;
int node = config->of_offset;
struct mvebu_pinctrl_priv *priv;
u32 func_arr[MVEBU_MAX_PINS_PER_BANK];
int pin, err;
priv = dev_get_priv(dev);
err = fdtdec_get_int_array(blob, node, "pin-func",
func_arr, priv->pin_cnt);
if (err) {
debug("Failed reading pin functions for bank %s\n",
priv->bank_name);
return -EINVAL;
}
for (pin = 0; pin < priv->pin_cnt; pin++) {
int reg_offset;
int field_offset;
u32 func = func_arr[pin];
/* Bypass pins with function 0xFF */
if (func == 0xff) {
debug("Warning: pin %d value is not modified ", pin);
debug("(kept as default)\n");
continue;
} else if (func > priv->max_func) {
debug("Illegal function %d for pin %d\n", func, pin);
return -EINVAL;
}
/* Calculate register address and bit in register */
reg_offset = priv->reg_direction * 4 *
(pin >> (PIN_REG_SHIFT));
field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
clrsetbits_le32(priv->base_reg + reg_offset,
PIN_FUNC_MASK << field_offset,
(func & PIN_FUNC_MASK) << field_offset);
}
return 0;
}
int mvebu_pinctl_probe(struct udevice *dev)
{
const void *blob = gd->fdt_blob;
int node = dev->of_offset;
struct mvebu_pinctrl_priv *priv;
priv = dev_get_priv(dev);
if (!priv) {
debug("%s: Failed to get private\n", __func__);
return -EINVAL;
}
priv->base_reg = dev_get_addr_ptr(dev);
if (priv->base_reg == (void *)FDT_ADDR_T_NONE) {
debug("%s: Failed to get base address\n", __func__);
return -EINVAL;
}
priv->pin_cnt = fdtdec_get_int(blob, node, "pin-count",
MVEBU_MAX_PINS_PER_BANK);
priv->max_func = fdtdec_get_int(blob, node, "max-func",
MVEBU_MAX_FUNC);
priv->bank_name = fdt_getprop(blob, node, "bank-name", NULL);
priv->reg_direction = 1;
if (fdtdec_get_bool(blob, node, "reverse-reg"))
priv->reg_direction = -1;
return mvebu_pinctrl_set_state_all(dev, dev);
}
static struct pinctrl_ops mvebu_pinctrl_ops = {
.set_state = mvebu_pinctrl_set_state
};
static const struct udevice_id mvebu_pinctrl_ids[] = {
{ .compatible = "marvell,mvebu-pinctrl" },
{ .compatible = "marvell,armada-ap806-pinctrl" },
{ .compatible = "marvell,a70x0-pinctrl" },
{ .compatible = "marvell,a80x0-cp0-pinctrl" },
{ .compatible = "marvell,a80x0-cp1-pinctrl" },
{ }
};
U_BOOT_DRIVER(pinctrl_mvebu) = {
.name = "mvebu_pinctrl",
.id = UCLASS_PINCTRL,
.of_match = mvebu_pinctrl_ids,
.priv_auto_alloc_size = sizeof(struct mvebu_pinctrl_priv),
.ops = &mvebu_pinctrl_ops,
.probe = mvebu_pinctl_probe
};

@ -0,0 +1,31 @@
/*
* Copyright (C) 2016 Marvell International Ltd.
*
* SPDX-License-Identifier: GPL-2.0
* https://spdx.org/licenses
*/
#ifndef __PINCTRL_MVEBU_H_
#define __PINCTRL_MVEBU_H_
#define MVEBU_MAX_PINCTL_BANKS 4
#define MVEBU_MAX_PINS_PER_BANK 100
#define MVEBU_MAX_FUNC 0xF
/*
* struct mvebu_pin_bank_data: mvebu-pinctrl bank data
* @base_reg: controller base address for this bank
* @pin_cnt: number of pins included in this bank
* @max_func: maximum configurable function value for pins in this bank
* @reg_direction:
* @bank_name: the pin's bank name
*/
struct mvebu_pinctrl_priv {
void *base_reg;
uint pin_cnt;
uint max_func;
int reg_direction;
const char *bank_name;
};
#endif /* __PINCTRL_MVEBU_H_ */
Loading…
Cancel
Save