diff options
26 files changed, 1800 insertions, 64 deletions
diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts index b8fe5a9cb9..466c6dcc3f 100644 --- a/arch/arm/dts/armada-7040-db.dts +++ b/arch/arm/dts/armada-7040-db.dts @@ -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 { diff --git a/arch/arm/dts/armada-8040-db.dts b/arch/arm/dts/armada-8040-db.dts index 7fb674b8b7..40def9d6cd 100644 --- a/arch/arm/dts/armada-8040-db.dts +++ b/arch/arm/dts/armada-8040-db.dts @@ -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 */ diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi index d315b29cd0..efb383b9f3 100644 --- a/arch/arm/dts/armada-ap806.dtsi +++ b/arch/arm/dts/armada-ap806.dtsi @@ -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>, diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index 422d754401..d637867615 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -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>; diff --git a/arch/arm/dts/armada-cp110-slave.dtsi b/arch/arm/dts/armada-cp110-slave.dtsi index a7f77b9515..92ef55cf26 100644 --- a/arch/arm/dts/armada-cp110-slave.dtsi +++ b/arch/arm/dts/armada-cp110-slave.dtsi @@ -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>; diff --git a/arch/arm/include/asm/arch-armada8k/cache_llc.h b/arch/arm/include/asm/arch-armada8k/cache_llc.h new file mode 100644 index 0000000000..8f97e6d776 --- /dev/null +++ b/arch/arm/include/asm/arch-armada8k/cache_llc.h @@ -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_ */ diff --git a/arch/arm/include/asm/arch-armada8k/soc-info.h b/arch/arm/include/asm/arch-armada8k/soc-info.h new file mode 100644 index 0000000000..bae39951ee --- /dev/null +++ b/arch/arm/include/asm/arch-armada8k/soc-info.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_ */ diff --git a/arch/arm/mach-mvebu/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile index 84c69d90e7..0facf14942 100644 --- a/arch/arm/mach-mvebu/armada8k/Makefile +++ b/arch/arm/mach-mvebu/armada8k/Makefile @@ -5,3 +5,4 @@ # obj-y = cpu.o +obj-y += cache_llc.o diff --git a/arch/arm/mach-mvebu/armada8k/cache_llc.S b/arch/arm/mach-mvebu/armada8k/cache_llc.S new file mode 100644 index 0000000000..71aecb2dde --- /dev/null +++ b/arch/arm/mach-mvebu/armada8k/cache_llc.S @@ -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) diff --git a/cmd/Kconfig b/cmd/Kconfig index 586a6456e4..bffa7134f7 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -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 diff --git a/cmd/Makefile b/cmd/Makefile index 9c9a9d112b..34bc5448b9 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -163,3 +163,5 @@ obj-$(CONFIG_CMD_BLOB) += blob.o # core command obj-y += nvedit.o + +obj-$(CONFIG_ARCH_MVEBU) += mvebu/ diff --git a/cmd/mvebu/Kconfig b/cmd/mvebu/Kconfig new file mode 100644 index 0000000000..ad10a572a3 --- /dev/null +++ b/cmd/mvebu/Kconfig @@ -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 diff --git a/cmd/mvebu/Makefile b/cmd/mvebu/Makefile new file mode 100644 index 0000000000..03de53ecdd --- /dev/null +++ b/cmd/mvebu/Makefile @@ -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 diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c new file mode 100644 index 0000000000..1cbfcf0863 --- /dev/null +++ b/cmd/mvebu/bubt.c @@ -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" + +); diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig index f153b9cd77..a2bb97a9ba 100644 --- a/configs/mvebu_db-88f7040_defconfig +++ b/configs/mvebu_db-88f7040_defconfig @@ -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 diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db-88f8040_defconfig index 61d58b50c2..1e92e9fa5b 100644 --- a/configs/mvebu_db-88f8040_defconfig +++ b/configs/mvebu_db-88f8040_defconfig @@ -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 diff --git a/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt new file mode 100644 index 0000000000..51f2f2c79c --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/marvell,armada-apn806-pinctrl.txt @@ -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 - diff --git a/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt new file mode 100644 index 0000000000..3adcf3aae4 --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/marvell,armada-cp110-pinctrl.txt @@ -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 - - - diff --git a/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt b/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt new file mode 100644 index 0000000000..5f86c0a00b --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/marvell,mvebu-pinctrl.txt @@ -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>; + }; + }; + }; +} diff --git a/doc/mvebu/cmd/bubt.txt b/doc/mvebu/cmd/bubt.txt new file mode 100644 index 0000000000..6f9f525936 --- /dev/null +++ b/doc/mvebu/cmd/bubt.txt @@ -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> + diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 12be3cfe0b..efcb4c0003 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -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 diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f28b5c18f6..512112af64 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -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/ diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig new file mode 100644 index 0000000000..cf9c299f13 --- /dev/null +++ b/drivers/pinctrl/mvebu/Kconfig @@ -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. diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile new file mode 100644 index 0000000000..f4f78640b9 --- /dev/null +++ b/drivers/pinctrl/mvebu/Makefile @@ -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 diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c new file mode 100644 index 0000000000..b07763931f --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -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 +}; diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.h b/drivers/pinctrl/mvebu/pinctrl-mvebu.h new file mode 100644 index 0000000000..1a1d3ef5e0 --- /dev/null +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.h @@ -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_ */ |