]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Merge tag 'u-boot-imx-20190612' of git://git.denx.de/u-boot-imx
authorTom Rini <trini@konsulko.com>
Tue, 11 Jun 2019 17:41:24 +0000 (13:41 -0400)
committerTom Rini <trini@konsulko.com>
Tue, 11 Jun 2019 17:41:24 +0000 (13:41 -0400)
u-boot-imx-20190612
--------------------

- Board fixes:
- imx6logic
- wandboard
- mx6sabre boots again
- imx8qm_mek
- pico-* boards
- Toradex apalis / colibri
- engicam imx6 (environment)
- KP MX53
- opos6ul
- Switch to DM:
- vining2000
- dh MX6
- Toradex colibri i.MX7
- Novena
- Security : fix CSF size for HAB
- Other:
      - imx: fix building for i.mx8 without spl
      - pcie and switch to DM

      mx6sabreauto: Enable SPL SDP support

85 files changed:
Makefile
arch/arm/dts/imx7-colibri-emmc.dts
arch/arm/dts/imx7-colibri.dtsi
arch/arm/dts/tegra124-apalis.dts
arch/arm/dts/tegra124-cei-tk1-som.dts
arch/arm/dts/tegra124-jetson-tk1.dts
arch/arm/dts/tegra124.dtsi
arch/arm/dts/tegra186-p2771-0000-000.dts
arch/arm/dts/tegra186-p2771-0000-500.dts
arch/arm/dts/tegra186-p2771-0000.dtsi
arch/arm/dts/tegra186.dtsi
arch/arm/dts/tegra20-harmony.dts
arch/arm/dts/tegra20-trimslice.dts
arch/arm/dts/tegra20.dtsi
arch/arm/dts/tegra210-p2371-2180.dts
arch/arm/dts/tegra210.dtsi
arch/arm/dts/tegra30-apalis.dts
arch/arm/dts/tegra30-beaver.dts
arch/arm/dts/tegra30-cardhu.dts
arch/arm/dts/tegra30.dtsi
arch/arm/include/asm/arch-tegra/cboot.h [new file with mode: 0644]
arch/arm/include/asm/arch-tegra/pmc.h
arch/arm/include/asm/arch-tegra/pmu.h [moved from arch/arm/include/asm/arch-tegra20/pmu.h with 73% similarity]
arch/arm/include/asm/arch-tegra/tegra.h
arch/arm/include/asm/arch-tegra114/pmu.h [deleted file]
arch/arm/include/asm/arch-tegra124/pmu.h [deleted file]
arch/arm/include/asm/arch-tegra210/pmu.h [deleted file]
arch/arm/include/asm/arch-tegra30/pmu.h [deleted file]
arch/arm/mach-at91/spl_atmel.c
arch/arm/mach-imx/cpu.c
arch/arm/mach-imx/mx7/soc.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board.c
arch/arm/mach-tegra/board186.c [deleted file]
arch/arm/mach-tegra/board2.c
arch/arm/mach-tegra/cache.c
arch/arm/mach-tegra/cboot.c [new file with mode: 0644]
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/cmd_enterrcm.c
arch/arm/mach-tegra/cpu.c
arch/arm/mach-tegra/emc.c
arch/arm/mach-tegra/lowlevel_init.S [deleted file]
arch/arm/mach-tegra/pmc.c [new file with mode: 0644]
arch/arm/mach-tegra/powergate.c
arch/arm/mach-tegra/tegra186/Makefile
arch/arm/mach-tegra/tegra186/nvtboot_board.c [deleted file]
arch/arm/mach-tegra/tegra186/nvtboot_ll.S [deleted file]
arch/arm/mach-tegra/tegra186/nvtboot_mem.c [deleted file]
arch/arm/mach-tegra/tegra210/clock.c
board/atmel/sama5d2_icp/sama5d2_icp.c
board/nvidia/p2371-2180/p2371-2180.c
board/nvidia/p2771-0000/p2771-0000.c
common/lcd.c
common/spl/Kconfig
common/splash.c
common/stdio.c
configs/colibri_imx6_defconfig
configs/colibri_imx7_emmc_defconfig
configs/colibri_t20_defconfig
configs/e2220-1170_defconfig
configs/gardena-smart-gateway-at91sam_defconfig
configs/ids8313_defconfig
configs/p2371-0000_defconfig
configs/p2371-2180_defconfig
configs/p2571_defconfig
configs/p2771-0000-000_defconfig
configs/p2771-0000-500_defconfig
configs/sama5d2_icp_mmc_defconfig
configs/sama5d2_ptc_ek_mmc_defconfig
configs/sama5d2_ptc_ek_nandflash_defconfig
configs/sama5d4_xplained_mmc_defconfig
configs/tinker-rk3288_defconfig
doc/driver-model/MIGRATION.txt
drivers/spi/Kconfig
drivers/spi/mpc8xxx_spi.c
drivers/video/meson/meson_dw_hdmi.c
drivers/video/mxsfb.c
include/configs/colibri_imx7.h
include/configs/tegra-common-post.h
include/fdtdec.h
include/linux/string.h
include/splash.h
lib/fdtdec.c
lib/string.c

index 7e5fd23e7c3fdf554743b08e6b32afb09f3df621..c55ffa265ffae45223efafb7fd756ae1b41fb133 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 VERSION = 2019
 PATCHLEVEL = 07
 SUBLEVEL =
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
 NAME =
 
 # *DOCUMENTATION*
index deb5482e3e2aa6060a7e3ffa87f5c4a146e39a70..bc0d10c716d369a61a644d3fde48768dfff3d991 100644 (file)
        compatible = "toradex,imx7d-colibri-emmc", "fsl,imx7d";
 
        aliases {
+               u-boot,dm-pre-reloc;
                mmc0 = &usdhc3;
                mmc1 = &usdhc1;
+               display1 = &lcdif;
                usb0 = &usbotg1; /* required for ums */
        };
 
index a85702f5194783183487339c25d2a30b094edb26..81717c233d1ca9dd800d6ae44d683cf6f1c26932 100644 (file)
                >;
        };
 };
+
+&lcdif {
+       u-boot,dm-pre-reloc;
+       status = "okay";
+
+       display-timings {
+               native-mode = <&timing_vga>;
+
+               /* Standard VGA timing */
+               timing_vga: 640x480 {
+                       u-boot,dm-pre-reloc;
+                       clock-frequency = <25175000>;
+                       hactive = <640>;
+                       vactive = <480>;
+                       hback-porch = <48>;
+                       hfront-porch = <16>;
+                       vback-porch = <33>;
+                       vfront-porch = <10>;
+                       hsync-len = <96>;
+                       vsync-len = <2>;
+
+                       de-active = <1>;
+                       hsync-active = <0>;
+                       vsync-active = <0>;
+                       pixelclk-active = <0>;
+               };
+       };
+};
index fe08d3ea7304901d6af33ed57e12571c78d2f0db..a962c0a2f0ae10a34840a9dd2c5087da4ef463e0 100644 (file)
@@ -77,7 +77,7 @@
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
-       pcie-controller@01003000 {
+       pcie@1003000 {
                status = "okay";
                avddio-pex-supply = <&vdd_1v05>;
                avdd-pex-pll-supply = <&vdd_1v05>;
index b1dd4181ac038e5a1aa5cb48f2b53687185719cc..e5b41f3183cd98b02bc2c09bcd06368e81b8a57e 100644 (file)
@@ -29,7 +29,7 @@
                reg = <0x80000000 0x80000000>;
        };
 
-       pcie-controller@01003000 {
+       pcie@1003000 {
                status = "okay";
 
                avddio-pex-supply = <&vdd_1v05_run>;
index d6420436cde823469d6b71b5d6008f51e7c5b66b..59e080a8af6f6346a4d8677ac7a7fa032cdc27dc 100644 (file)
@@ -29,7 +29,7 @@
                reg = <0x80000000 0x80000000>;
        };
 
-       pcie-controller@01003000 {
+       pcie@1003000 {
                status = "okay";
 
                avddio-pex-supply = <&vdd_1v05_run>;
index 83d63480471ba07173f44187f0ec5791fa6f8df1..f473ba28e4a645e3b588436ad9bc2b8c8b479b37 100644 (file)
@@ -14,7 +14,7 @@
        interrupt-parent = <&lic>;
 
 
-       pcie-controller@01003000 {
+       pcie@1003000 {
                compatible = "nvidia,tegra124-pcie";
                device_type = "pci";
                reg = <0x01003000 0x00000800   /* PADS registers */
index d97c6fd3d09a61bca6277d968e3838239f45aafe..84e850d6fca6d6675eadcb1a61d9dea7ebe205ee 100644 (file)
@@ -11,7 +11,7 @@
                power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_HIGH>;
        };
 
-       pcie-controller@10003000 {
+       pcie@10003000 {
                status = "okay";
 
                pci@1,0 {
index 393a8b246a0bd47a76c4a17db4d17709e64d7a5c..1ac8ab431e9017b3c0e7735668e6835c9a022722 100644 (file)
@@ -11,7 +11,7 @@
                power-gpios = <&gpio_main TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
        };
 
-       pcie-controller@10003000 {
+       pcie@10003000 {
                status = "okay";
 
                pci@1,0 {
index a1319dc4936f00ff508b8f2ede12b0b00d9bd6d1..7cda0b41f74b61a84e8181352e4eb6a646113ba7 100644 (file)
@@ -9,6 +9,7 @@
        };
 
        aliases {
+               ethernet = "/ethernet@2490000";
                mmc0 = "/sdhci@3460000";
                mmc1 = "/sdhci@3400000";
                i2c0 = "/bpmp/i2c";
@@ -28,6 +29,7 @@
        ethernet@2490000 {
                status = "okay";
                phy-reset-gpios = <&gpio_main TEGRA_MAIN_GPIO(M, 4) GPIO_ACTIVE_LOW>;
+               local-mac-address = [ 00 00 00 00 00 00 ];
        };
 
        i2c@3160000 {
index dd9e3b869de716c43bcb8f559207adfbf2cb6ddb..0a9db9825b85d0ebaae38ef9b5398416bbe97340 100644 (file)
                #interrupt-cells = <2>;
        };
 
-       pcie-controller@10003000 {
+       pcie@10003000 {
                compatible = "nvidia,tegra186-pcie";
                device_type = "pci";
                reg = <0x0 0x10003000 0x0 0x00000800   /* PADS registers */
index 0c907054dbd4afbf697ec8366f546ebe6876c191..7fe7d52096c4d8c7a069e770dc8d5fa7269bcc6b 100644 (file)
                nvidia,sys-clock-req-active-high;
        };
 
-       pcie-controller@80003000 {
+       pcie@80003000 {
                status = "okay";
 
                avdd-pex-supply = <&pci_vdd_reg>;
index 31f509ab12c8022be201ad448388533864dae3fe..e19001ee2bdfdfc6e074c9beaa3158ee0ec3cb0f 100644 (file)
@@ -30,7 +30,7 @@
                spi-max-frequency = <25000000>;
        };
 
-       pcie-controller@80003000 {
+       pcie@80003000 {
                status = "okay";
 
                avdd-pex-supply = <&pci_vdd_reg>;
index e21ee258b3788cfdc77a0b22eb711706428bc127..275b3432bd88f111672a3f5161def625a6e686bf 100644 (file)
                reset-names = "fuse";
        };
 
-       pcie-controller@80003000 {
+       pcie@80003000 {
                compatible = "nvidia,tegra20-pcie";
                device_type = "pci";
                reg = <0x80003000 0x00000800   /* PADS registers */
index da4349bd039f8dbe72ea87d0857f2a1c4e155fe3..c2f497c524affd1245ebe9ac17278fa19e5e73a5 100644 (file)
@@ -21,7 +21,7 @@
                reg = <0x0 0x80000000 0x0 0xc0000000>;
        };
 
-       pcie-controller@01003000 {
+       pcie@1003000 {
                status = "okay";
 
                pci@1,0 {
index 229fed04529a1622884f8eeaf1931b76b7413070..3ec54b11c43f45841bc82ed58e366ec0d9cd272a 100644 (file)
@@ -11,7 +11,7 @@
        #address-cells = <2>;
        #size-cells = <2>;
 
-       pcie-controller@01003000 {
+       pcie@1003000 {
                compatible = "nvidia,tegra210-pcie";
                device_type = "pci";
                reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
index 1a9ce2720acd4b25537d3163860d2f737084ab04..77502dfdb4783f83f8dc535fdec1b1a87774824a 100644 (file)
@@ -32,7 +32,7 @@
                reg = <0x80000000 0x40000000>;
        };
 
-       pcie-controller@00003000 {
+       pcie@3000 {
                status = "okay";
                avdd-pexa-supply = <&vdd2_reg>;
                vdd-pexa-supply = <&vdd2_reg>;
index f5fbbe849e26eee624a4796678a7fe0e3273ec7b..9bb097b081362997c54437e0efb748837876811f 100644 (file)
@@ -28,7 +28,7 @@
                reg = <0x80000000 0x7ff00000>;
        };
 
-       pcie-controller@00003000 {
+       pcie@3000 {
                status = "okay";
 
                avdd-pexa-supply = <&ldo1_reg>;
index 5b9798c5a874035a190092fd60334787a354ab79..7534861e40d9f47203d3e669ddd5d58f7bc734a9 100644 (file)
@@ -27,7 +27,7 @@
                reg = <0x80000000 0x40000000>;
        };
 
-       pcie-controller@00003000 {
+       pcie@3000 {
                status = "okay";
 
                /* AVDD_PEXA and VDD_PEXA inputs are grounded on Cardhu. */
index 5030065cbdfe38df667fb8cc9e89e4154d5a7798..f198bc0edbe80a702a8b93cf45d7c11d9824767c 100644 (file)
@@ -10,7 +10,7 @@
        compatible = "nvidia,tegra30";
        interrupt-parent = <&lic>;
 
-       pcie-controller@00003000 {
+       pcie@3000 {
                compatible = "nvidia,tegra30-pcie";
                device_type = "pci";
                reg = <0x00003000 0x00000800   /* PADS registers */
diff --git a/arch/arm/include/asm/arch-tegra/cboot.h b/arch/arm/include/asm/arch-tegra/cboot.h
new file mode 100644 (file)
index 0000000..021c246
--- /dev/null
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2019 NVIDIA Corporation. All rights reserved.
+ */
+
+#ifndef _TEGRA_CBOOT_H_
+#define _TEGRA_CBOOT_H_
+
+#ifdef CONFIG_ARM64
+extern unsigned long cboot_boot_x0;
+
+void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+                           unsigned long x2, unsigned long x3);
+int cboot_dram_init(void);
+int cboot_dram_init_banksize(void);
+ulong cboot_get_usable_ram_top(ulong total_size);
+int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN]);
+#else
+static inline void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+                                         unsigned long x2, unsigned long x3)
+{
+}
+
+static inline int cboot_dram_init(void)
+{
+       return -ENOSYS;
+}
+
+static inline int cboot_dram_init_banksize(void)
+{
+       return -ENOSYS;
+}
+
+static inline ulong cboot_get_usable_ram_top(ulong total_size)
+{
+       return 0;
+}
+
+static inline int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN])
+{
+       return -ENOSYS;
+}
+#endif
+
+#endif
index 34bbe75d5fdb1b7ca4f6aa902af3f6882e66bc4a..1524bf29116433f3ff8e126d338f51acddacc897 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ */
 /*
- *  (C) Copyright 2010-2015
+ *  (C) Copyright 2010-2019
  *  NVIDIA Corporation <www.nvidia.com>
  */
 
@@ -388,4 +388,22 @@ struct pmc_ctlr {
 /* APBDEV_PMC_CNTRL2_0 0x440 */
 #define HOLD_CKE_LOW_EN                                (1 << 12)
 
+/* PMC read/write functions */
+u32 tegra_pmc_readl(unsigned long offset);
+void tegra_pmc_writel(u32 value, unsigned long offset);
+
+#define PMC_CNTRL              0x0
+#define  PMC_CNTRL_MAIN_RST    BIT(4)
+
+#if IS_ENABLED(CONFIG_TEGRA186)
+#  define PMC_SCRATCH0 0x32000
+#else
+#  define PMC_SCRATCH0 0x00050
+#endif
+
+/* for secure PMC */
+#define TEGRA_SMC_PMC          0xc2fffe00
+#define  TEGRA_SMC_PMC_READ    0xaa
+#define  TEGRA_SMC_PMC_WRITE   0xbb
+
 #endif /* PMC_H */
similarity index 73%
rename from arch/arm/include/asm/arch-tegra20/pmu.h
rename to arch/arm/include/asm/arch-tegra/pmu.h
index 18766dfed2bb795638acdac0907c10bc11faf46d..e850875d31662401b81b35232931eebc1698623a 100644 (file)
@@ -4,10 +4,10 @@
  *  NVIDIA Corporation <www.nvidia.com>
  */
 
-#ifndef _ARCH_PMU_H_
-#define _ARCH_PMU_H_
+#ifndef _TEGRA_PMU_H_
+#define _TEGRA_PMU_H_
 
 /* Set core and CPU voltages to nominal levels */
 int pmu_set_nominal(void);
 
-#endif /* _ARCH_PMU_H_ */
+#endif /* _TEGRA_PMU_H_ */
index 7ae0129e2db3d65b08cae7ba7b23849779658ce3..7a4e0972fb76f4d56de28247b6f6eee547465af5 100644 (file)
 #define NV_PA_SLINK5_BASE      (NV_PA_APB_MISC_BASE + 0xDC00)
 #define NV_PA_SLINK6_BASE      (NV_PA_APB_MISC_BASE + 0xDE00)
 #define TEGRA_DVC_BASE         (NV_PA_APB_MISC_BASE + 0xD000)
+#if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \
+       defined(CONFIG_TEGRA114) || defined(CONFIG_TEGRA124) || \
+       defined(CONFIG_TEGRA132) || defined(CONFIG_TEGRA210)
 #define NV_PA_PMC_BASE         (NV_PA_APB_MISC_BASE + 0xE400)
+#else
+#define NV_PA_PMC_BASE         0xc360000
+#endif
 #define NV_PA_EMC_BASE         (NV_PA_APB_MISC_BASE + 0xF400)
 #define NV_PA_FUSE_BASE                (NV_PA_APB_MISC_BASE + 0xF800)
 #if defined(CONFIG_TEGRA20) || defined(CONFIG_TEGRA30) || \
diff --git a/arch/arm/include/asm/arch-tegra114/pmu.h b/arch/arm/include/asm/arch-tegra114/pmu.h
deleted file mode 100644 (file)
index 1e571ee..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
- */
-
-#ifndef _TEGRA114_PMU_H_
-#define _TEGRA114_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif /* _TEGRA114_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra124/pmu.h b/arch/arm/include/asm/arch-tegra124/pmu.h
deleted file mode 100644 (file)
index c38393e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2010-2013
- * NVIDIA Corporation <www.nvidia.com>
- */
-
-#ifndef _TEGRA124_PMU_H_
-#define _TEGRA124_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif /* _TEGRA124_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra210/pmu.h b/arch/arm/include/asm/arch-tegra210/pmu.h
deleted file mode 100644 (file)
index 6ea36aa..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * (C) Copyright 2010-2015
- * NVIDIA Corporation <www.nvidia.com>
- */
-
-#ifndef _TEGRA210_PMU_H_
-#define _TEGRA210_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif /* _TEGRA210_PMU_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/pmu.h b/arch/arm/include/asm/arch-tegra30/pmu.h
deleted file mode 100644 (file)
index a823f0f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
- */
-
-#ifndef _TEGRA30_PMU_H_
-#define _TEGRA30_PMU_H_
-
-/* Set core and CPU voltages to nominal levels */
-int pmu_set_nominal(void);
-
-#endif /* _TEGRA30_PMU_H_ */
index ef745c94775dc81f80d0fa19650b8244642625a0..85290be3696535ffdfd5e439fc4485c689659cb6 100644 (file)
@@ -44,7 +44,15 @@ static void switch_to_main_crystal_osc(void)
 #endif
 
        tmp = readl(&pmc->mor);
+/*
+ * some boards have an external oscillator with driving.
+ * in this case we need to disable the internal SoC driving (bypass mode)
+ */
+#if defined(CONFIG_SPL_AT91_MCK_BYPASS)
+       tmp |= AT91_PMC_MOR_OSCBYPASS;
+#else
        tmp &= ~AT91_PMC_MOR_OSCBYPASS;
+#endif
        tmp &= ~AT91_PMC_MOR_KEY(0xff);
        tmp |= AT91_PMC_MOR_KEY(0x37);
        writel(tmp, &pmc->mor);
index 93e60b2039ad4aeb6cd70bc9ea4b74662f9d9d2a..d62ff6ef25df70a3e48cebb0bf3a567738ec8e46 100644 (file)
@@ -298,7 +298,7 @@ void arch_preboot_os(void)
        /* disable video before launching O/S */
        ipuv3_fb_shutdown();
 #endif
-#if defined(CONFIG_VIDEO_MXS)
+#if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
        lcdif_power_down();
 #endif
 }
index ccfab826e3696158c8cec761d9ed19d3605f8821..1b4bbc503733eb2c3c461aa1abf3126a869130c4 100644 (file)
@@ -382,7 +382,7 @@ void s_init(void)
 void reset_misc(void)
 {
 #ifndef CONFIG_SPL_BUILD
-#ifdef CONFIG_VIDEO_MXS
+#if defined(CONFIG_VIDEO_MXS) && !defined(CONFIG_DM_VIDEO)
        lcdif_power_down();
 #endif
 #endif
index 86b1cd11f752c4573a381419c71bb098ec50ff26..97e22ead59859e79631bf2b12c57f37ff41cff22 100644 (file)
@@ -12,6 +12,12 @@ config SPL_LIBGENERIC_SUPPORT
 config SPL_SERIAL_SUPPORT
        default y
 
+config TEGRA_CLKRST
+       bool
+
+config TEGRA_GP_PADCTRL
+       bool
+
 config TEGRA_IVC
        bool "Tegra IVC protocol"
        help
@@ -20,6 +26,19 @@ config TEGRA_IVC
          U-Boot, it is typically used for communication between the main CPU
          and various auxiliary processors.
 
+config TEGRA_MC
+       bool
+
+config TEGRA_PINCTRL
+       bool
+
+config TEGRA_PMC
+       bool
+
+config TEGRA_PMC_SECURE
+       bool
+       depends on TEGRA_PMC
+
 config TEGRA_COMMON
        bool "Tegra common options"
        select BINMAN
@@ -55,14 +74,20 @@ config TEGRA_ARMV7_COMMON
        select SPL
        select SPL_BOARD_INIT if SPL
        select SUPPORT_SPL
+       select TEGRA_CLKRST
        select TEGRA_COMMON
        select TEGRA_GPIO
+       select TEGRA_GP_PADCTRL
+       select TEGRA_MC
        select TEGRA_NO_BPMP
+       select TEGRA_PINCTRL
+       select TEGRA_PMC
 
 config TEGRA_ARMV8_COMMON
        bool "Tegra 64-bit common options"
        select ARM64
        select LINUX_KERNEL_IMAGE_HEADER
+       select POSITION_INDEPENDENT
        select TEGRA_COMMON
 
 if TEGRA_ARMV8_COMMON
@@ -100,8 +125,14 @@ config TEGRA124
 config TEGRA210
        bool "Tegra210 family"
        select TEGRA_ARMV8_COMMON
+       select TEGRA_CLKRST
        select TEGRA_GPIO
+       select TEGRA_GP_PADCTRL
+       select TEGRA_MC
        select TEGRA_NO_BPMP
+       select TEGRA_PINCTRL
+       select TEGRA_PMC
+       select TEGRA_PMC_SECURE
 
 config TEGRA186
        bool "Tegra186 family"
@@ -118,6 +149,7 @@ endchoice
 
 config TEGRA_DISCONNECT_UDC_ON_BOOT
        bool "Disconnect USB device mode controller on boot"
+       depends on CI_UDC
        default y
        help
          When loading U-Boot into RAM over USB protocols using tools such as
index d4b4666fb1e22a29d0689df400cd2b7edd53837d..7165d70a60da926be271ac2df8ec564f319c77f4 100644 (file)
@@ -1,11 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0+
 #
-# (C) Copyright 2010-2015 Nvidia Corporation.
+# (C) Copyright 2010-2019 Nvidia Corporation.
 #
 # (C) Copyright 2000-2008
 # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
-ifndef CONFIG_TEGRA186
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
 obj-y += cpu.o
@@ -13,25 +12,24 @@ else
 obj-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o
 endif
 
-obj-y += ap.o
+obj-$(CONFIG_TEGRA_GP_PADCTRL) += ap.o
 obj-y += board.o board2.o
 obj-y += cache.o
-obj-y += clock.o
-obj-y += pinmux-common.o
-obj-y += powergate.o
+obj-$(CONFIG_TEGRA_CLKRST) += clock.o
+obj-$(CONFIG_TEGRA_PINCTRL) += pinmux-common.o
+obj-$(CONFIG_TEGRA_PMC) += powergate.o
 obj-y += xusb-padctl-dummy.o
-endif
 
-obj-$(CONFIG_ARM64) += arm64-mmu.o
+obj-$(CONFIG_ARM64) += arm64-mmu.o cboot.o
 obj-y += dt-setup.o
 obj-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o
 obj-$(CONFIG_TEGRA_GPU) += gpu.o
 obj-$(CONFIG_TEGRA_IVC) += ivc.o
-obj-y += lowlevel_init.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMV7_PSCI) += psci.o
 endif
 obj-$(CONFIG_DISPLAY_CPUINFO) += sys_info.o
+obj-y += pmc.o
 
 obj-$(CONFIG_TEGRA20) += tegra20/
 obj-$(CONFIG_TEGRA30) += tegra30/
index 4e159075d379bdb90aad5253ef2088dc6dfbc5f8..abcae15ea3315c8ab925056b5b24e935a4019c05 100644 (file)
@@ -9,12 +9,19 @@
 #include <ns16550.h>
 #include <spl.h>
 #include <asm/io.h>
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
 #include <asm/arch/clock.h>
+#endif
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 #include <asm/arch/funcmux.h>
+#endif
+#if IS_ENABLED(CONFIG_TEGRA_MC)
 #include <asm/arch/mc.h>
+#endif
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/board.h>
+#include <asm/arch-tegra/cboot.h>
 #include <asm/arch-tegra/pmc.h>
 #include <asm/arch-tegra/sys_proto.h>
 #include <asm/arch-tegra/warmboot.h>
@@ -36,9 +43,25 @@ enum {
 static bool from_spl __attribute__ ((section(".data")));
 
 #ifndef CONFIG_SPL_BUILD
-void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
+void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
+                     unsigned long r3)
 {
        from_spl = r0 != UBOOT_NOT_LOADED_FROM_SPL;
+
+       /*
+        * The logic for this is somewhat indirect. The purpose of the marker
+        * (UBOOT_NOT_LOADED_FROM_SPL) is in fact used to determine if U-Boot
+        * was loaded from a read-only instance of itself, which is something
+        * that can happen in secure boot setups. So basically the presence
+        * of the marker is an indication that U-Boot was loaded by one such
+        * special variant of U-Boot. Conversely, the absence of the marker
+        * indicates that this instance of U-Boot was loaded by something
+        * other than a special U-Boot. This could be SPL, but it could just
+        * as well be one of any number of other first stage bootloaders.
+        */
+       if (from_spl)
+               cboot_save_boot_params(r0, r1, r2, r3);
+
        save_boot_params_ret();
 }
 #endif
@@ -66,6 +89,7 @@ bool tegra_cpu_is_non_secure(void)
 }
 #endif
 
+#if IS_ENABLED(CONFIG_TEGRA_MC)
 /* Read the RAM size directly from the memory controller */
 static phys_size_t query_sdram_size(void)
 {
@@ -115,14 +139,26 @@ static phys_size_t query_sdram_size(void)
 
        return size_bytes;
 }
+#endif
 
 int dram_init(void)
 {
+       int err;
+
+       /* try to initialize DRAM from cboot DTB first */
+       err = cboot_dram_init();
+       if (err == 0)
+               return 0;
+
+#if IS_ENABLED(CONFIG_TEGRA_MC)
        /* We do not initialise DRAM here. We just query the size */
        gd->ram_size = query_sdram_size();
+#endif
+
        return 0;
 }
 
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 static int uart_configs[] = {
 #if defined(CONFIG_TEGRA20)
  #if defined(CONFIG_TEGRA_UARTA_UAA_UAB)
@@ -190,9 +226,11 @@ static void setup_uarts(int uart_ids)
                }
        }
 }
+#endif
 
 void board_init_uart_f(void)
 {
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
        int uart_ids = 0;       /* bit mask of which UART ids to enable */
 
 #ifdef CONFIG_TEGRA_ENABLE_UARTA
@@ -211,6 +249,7 @@ void board_init_uart_f(void)
        uart_ids |= UARTE;
 #endif
        setup_uarts(uart_ids);
+#endif
 }
 
 #if !CONFIG_IS_ENABLED(OF_CONTROL)
diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c
deleted file mode 100644 (file)
index 80b5570..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016, NVIDIA CORPORATION.
- */
-
-#include <common.h>
-#include <asm/arch/tegra.h>
-
-int board_early_init_f(void)
-{
-       return 0;
-}
-
-__weak int tegra_board_init(void)
-{
-       return 0;
-}
-
-int board_init(void)
-{
-       return tegra_board_init();
-}
-
-__weak int tegra_soc_board_init_late(void)
-{
-       return 0;
-}
-
-int board_late_init(void)
-{
-       return tegra_soc_board_init_late();
-}
index 12257a42b51b645da544dd5f1b9fc458ccde7681..bbc487aa3bf6c03f9c8ed461aaae79b05466eabc 100644 (file)
 #include <asm/io.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/board.h>
+#include <asm/arch-tegra/cboot.h>
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/pmc.h>
+#include <asm/arch-tegra/pmu.h>
 #include <asm/arch-tegra/sys_proto.h>
 #include <asm/arch-tegra/uart.h>
 #include <asm/arch-tegra/warmboot.h>
 #include <asm/arch-tegra/gpu.h>
 #include <asm/arch-tegra/usb.h>
 #include <asm/arch-tegra/xusb-padctl.h>
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
 #include <asm/arch/clock.h>
+#endif
+#if IS_ENABLED(CONFIG_TEGRA_PINCTRL)
 #include <asm/arch/funcmux.h>
 #include <asm/arch/pinmux.h>
-#include <asm/arch/pmu.h>
+#endif
 #include <asm/arch/tegra.h>
 #ifdef CONFIG_TEGRA_CLOCK_SCALING
 #include <asm/arch/emc.h>
@@ -47,6 +52,7 @@ __weak void pin_mux_mmc(void) {}
 __weak void gpio_early_init_uart(void) {}
 __weak void pin_mux_display(void) {}
 __weak void start_cpu_fan(void) {}
+__weak void cboot_late_init(void) {}
 
 #if defined(CONFIG_TEGRA_NAND)
 __weak void pin_mux_nand(void)
@@ -109,8 +115,10 @@ int board_init(void)
        __maybe_unused int board_id;
 
        /* Do clocks and UART first so that printf() works */
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
        clock_init();
        clock_verify();
+#endif
 
        tegra_gpu_config();
 
@@ -181,8 +189,10 @@ void gpio_early_init(void) __attribute__((weak, alias("__gpio_early_init")));
 
 int board_early_init_f(void)
 {
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
        if (!clock_early_init_done())
                clock_early_init();
+#endif
 
 #if defined(CONFIG_TEGRA_DISCONNECT_UDC_ON_BOOT)
 #define USBCMD_FS2 (1 << 15)
@@ -193,10 +203,12 @@ int board_early_init_f(void)
 #endif
 
        /* Do any special system timer/TSC setup */
-#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
+#if IS_ENABLED(CONFIG_TEGRA_CLKRST)
+#  if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
        if (!tegra_cpu_is_non_secure())
-#endif
+#  endif
                arch_timer_init();
+#endif
 
        pinmux_init();
        board_init_uart_f();
@@ -233,6 +245,7 @@ int board_late_init(void)
        }
 #endif
        start_cpu_fan();
+       cboot_late_init();
 
        return 0;
 }
@@ -327,6 +340,15 @@ static ulong usable_ram_size_below_4g(void)
  */
 int dram_init_banksize(void)
 {
+       int err;
+
+       /* try to compute DRAM bank size based on cboot DTB first */
+       err = cboot_dram_init_banksize();
+       if (err == 0)
+               return err;
+
+       /* fall back to default DRAM bank size computation */
+
        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
        gd->bd->bi_dram[0].size = usable_ram_size_below_4g();
 
@@ -360,5 +382,14 @@ int dram_init_banksize(void)
  */
 ulong board_get_usable_ram_top(ulong total_size)
 {
+       ulong ram_top;
+
+       /* try to get top of usable RAM based on cboot DTB first */
+       ram_top = cboot_get_usable_ram_top(total_size);
+       if (ram_top > 0)
+               return ram_top;
+
+       /* fall back to default usable RAM computation */
+
        return CONFIG_SYS_SDRAM_BASE + usable_ram_size_below_4g();
 }
index be414e4e4aca296206e05cadd3534684d6b1c572..d7063490e222092e04e634df94e3edafe225ecad 100644 (file)
@@ -8,7 +8,9 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch-tegra/ap.h>
+#if IS_ENABLED(CONFIG_TEGRA_GP_PADCTRL)
 #include <asm/arch/gp_padctrl.h>
+#endif
 
 #ifndef CONFIG_ARM64
 void config_cache(void)
diff --git a/arch/arm/mach-tegra/cboot.c b/arch/arm/mach-tegra/cboot.c
new file mode 100644 (file)
index 0000000..a829ef7
--- /dev/null
@@ -0,0 +1,620 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2016-2018, NVIDIA CORPORATION.
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <fdt_support.h>
+#include <fdtdec.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/ctype.h>
+#include <linux/sizes.h>
+
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/cboot.h>
+#include <asm/armv8/mmu.h>
+
+/*
+ * Size of a region that's large enough to hold the relocated U-Boot and all
+ * other allocations made around it (stack, heap, page tables, etc.)
+ * In practice, running "bdinfo" at the shell prompt, the stack reaches about
+ * 5MB from the address selected for ram_top as of the time of writing,
+ * so a 16MB region should be plenty.
+ */
+#define MIN_USABLE_RAM_SIZE SZ_16M
+/*
+ * The amount of space we expect to require for stack usage. Used to validate
+ * that all reservations fit into the region selected for the relocation target
+ */
+#define MIN_USABLE_STACK_SIZE SZ_1M
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern struct mm_region tegra_mem_map[];
+
+/*
+ * These variables are written to before relocation, and hence cannot be
+ * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary.
+ * The section attribute forces this into .data and avoids this issue. This
+ * also has the nice side-effect of the content being valid after relocation.
+ */
+
+/* The number of valid entries in ram_banks[] */
+static int ram_bank_count __attribute__((section(".data")));
+
+/*
+ * The usable top-of-RAM for U-Boot. This is both:
+ * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing.
+ * b) At the end of a region that has enough space to hold the relocated U-Boot
+ *    and all other allocations made around it (stack, heap, page tables, etc.)
+ */
+static u64 ram_top __attribute__((section(".data")));
+/* The base address of the region of RAM that ends at ram_top */
+static u64 region_base __attribute__((section(".data")));
+
+/*
+ * Explicitly put this in the .data section because it is written before the
+ * .bss section is zeroed out but it needs to persist.
+ */
+unsigned long cboot_boot_x0 __attribute__((section(".data")));
+
+void cboot_save_boot_params(unsigned long x0, unsigned long x1,
+                           unsigned long x2, unsigned long x3)
+{
+       cboot_boot_x0 = x0;
+}
+
+int cboot_dram_init(void)
+{
+       unsigned int na, ns;
+       const void *cboot_blob = (void *)cboot_boot_x0;
+       int node, len, i;
+       const u32 *prop;
+
+       if (!cboot_blob)
+               return -EINVAL;
+
+       na = fdtdec_get_uint(cboot_blob, 0, "#address-cells", 2);
+       ns = fdtdec_get_uint(cboot_blob, 0, "#size-cells", 2);
+
+       node = fdt_path_offset(cboot_blob, "/memory");
+       if (node < 0) {
+               pr_err("Can't find /memory node in cboot DTB");
+               hang();
+       }
+       prop = fdt_getprop(cboot_blob, node, "reg", &len);
+       if (!prop) {
+               pr_err("Can't find /memory/reg property in cboot DTB");
+               hang();
+       }
+
+       /* Calculate the true # of base/size pairs to read */
+       len /= 4;               /* Convert bytes to number of cells */
+       len /= (na + ns);       /* Convert cells to number of banks */
+       if (len > CONFIG_NR_DRAM_BANKS)
+               len = CONFIG_NR_DRAM_BANKS;
+
+       /* Parse the /memory node, and save useful entries */
+       gd->ram_size = 0;
+       ram_bank_count = 0;
+       for (i = 0; i < len; i++) {
+               u64 bank_start, bank_end, bank_size, usable_bank_size;
+
+               /* Extract raw memory region data from DTB */
+               bank_start = fdt_read_number(prop, na);
+               prop += na;
+               bank_size = fdt_read_number(prop, ns);
+               prop += ns;
+               gd->ram_size += bank_size;
+               bank_end = bank_start + bank_size;
+               debug("Bank %d: %llx..%llx (+%llx)\n", i,
+                     bank_start, bank_end, bank_size);
+
+               /*
+                * Align the bank to MMU section size. This is not strictly
+                * necessary, since the translation table construction code
+                * handles page granularity without issue. However, aligning
+                * the MMU entries reduces the size and number of levels in the
+                * page table, so is worth it.
+                */
+               bank_start = ROUND(bank_start, SZ_2M);
+               bank_end = bank_end & ~(SZ_2M - 1);
+               bank_size = bank_end - bank_start;
+               debug("  aligned: %llx..%llx (+%llx)\n",
+                     bank_start, bank_end, bank_size);
+               if (bank_end <= bank_start)
+                       continue;
+
+               /* Record data used to create MMU translation tables */
+               ram_bank_count++;
+               /* Index below is deliberately 1-based to skip MMIO entry */
+               tegra_mem_map[ram_bank_count].virt = bank_start;
+               tegra_mem_map[ram_bank_count].phys = bank_start;
+               tegra_mem_map[ram_bank_count].size = bank_size;
+               tegra_mem_map[ram_bank_count].attrs =
+                       PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE;
+
+               /* Determine best bank to relocate U-Boot into */
+               if (bank_end > SZ_4G)
+                       bank_end = SZ_4G;
+               debug("  end  %llx (usable)\n", bank_end);
+               usable_bank_size = bank_end - bank_start;
+               debug("  size %llx (usable)\n", usable_bank_size);
+               if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) &&
+                   (bank_end > ram_top)) {
+                       ram_top = bank_end;
+                       region_base = bank_start;
+                       debug("ram top now %llx\n", ram_top);
+               }
+       }
+
+       /* Ensure memory map contains the desired sentinel entry */
+       tegra_mem_map[ram_bank_count + 1].virt = 0;
+       tegra_mem_map[ram_bank_count + 1].phys = 0;
+       tegra_mem_map[ram_bank_count + 1].size = 0;
+       tegra_mem_map[ram_bank_count + 1].attrs = 0;
+
+       /* Error out if a relocation target couldn't be found */
+       if (!ram_top) {
+               pr_err("Can't find a usable RAM top");
+               hang();
+       }
+
+       return 0;
+}
+
+int cboot_dram_init_banksize(void)
+{
+       int i;
+
+       if (ram_bank_count == 0)
+               return -EINVAL;
+
+       if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) {
+               pr_err("Reservations exceed chosen region size");
+               hang();
+       }
+
+       for (i = 0; i < ram_bank_count; i++) {
+               gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt;
+               gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size;
+       }
+
+#ifdef CONFIG_PCI
+       gd->pci_ram_top = ram_top;
+#endif
+
+       return 0;
+}
+
+ulong cboot_get_usable_ram_top(ulong total_size)
+{
+       return ram_top;
+}
+
+/*
+ * The following few functions run late during the boot process and dynamically
+ * calculate the load address of various binaries. To keep track of multiple
+ * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
+ * is used for this purpose to avoid making yet another copy of the list of RAM
+ * banks. This is safe because tegra_mem_map[] is only used once during very
+ * early boot to create U-Boot's page tables, long before this code runs. If
+ * this assumption becomes invalid later, we can just fix the code to copy the
+ * list of RAM banks into some private data structure before running.
+ */
+
+static char *gen_varname(const char *var, const char *ext)
+{
+       size_t len_var = strlen(var);
+       size_t len_ext = strlen(ext);
+       size_t len = len_var + len_ext + 1;
+       char *varext = malloc(len);
+
+       if (!varext)
+               return 0;
+       strcpy(varext, var);
+       strcpy(varext + len_var, ext);
+       return varext;
+}
+
+static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
+{
+       u64 bank_start = tegra_mem_map[bank].virt;
+       u64 bank_size = tegra_mem_map[bank].size;
+       u64 bank_end = bank_start + bank_size;
+       bool keep_front = allocated_start != bank_start;
+       bool keep_tail = allocated_end != bank_end;
+
+       if (keep_front && keep_tail) {
+               /*
+                * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
+                * starting at index 1 (index 0 is MMIO). So, we are at DRAM
+                * entry "bank" not "bank - 1" as for a typical 0-base array.
+                * The number of remaining DRAM entries is therefore
+                * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
+                * current entry and shift up the remaining entries, dropping
+                * the last one. Thus, we must copy one fewer entry than the
+                * number remaining.
+                */
+               memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
+                       CONFIG_NR_DRAM_BANKS - bank - 1);
+               tegra_mem_map[bank].size = allocated_start - bank_start;
+               bank++;
+               tegra_mem_map[bank].virt = allocated_end;
+               tegra_mem_map[bank].phys = allocated_end;
+               tegra_mem_map[bank].size = bank_end - allocated_end;
+       } else if (keep_front) {
+               tegra_mem_map[bank].size = allocated_start - bank_start;
+       } else if (keep_tail) {
+               tegra_mem_map[bank].virt = allocated_end;
+               tegra_mem_map[bank].phys = allocated_end;
+               tegra_mem_map[bank].size = bank_end - allocated_end;
+       } else {
+               /*
+                * We could move all subsequent banks down in the array but
+                * that's not necessary for subsequent allocations to work, so
+                * we skip doing so.
+                */
+               tegra_mem_map[bank].size = 0;
+       }
+}
+
+static void reserve_ram(u64 start, u64 size)
+{
+       int bank;
+       u64 end = start + size;
+
+       for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+               u64 bank_start = tegra_mem_map[bank].virt;
+               u64 bank_size = tegra_mem_map[bank].size;
+               u64 bank_end = bank_start + bank_size;
+
+               if (end <= bank_start || start > bank_end)
+                       continue;
+               mark_ram_allocated(bank, start, end);
+               break;
+       }
+}
+
+static u64 alloc_ram(u64 size, u64 align, u64 offset)
+{
+       int bank;
+
+       for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+               u64 bank_start = tegra_mem_map[bank].virt;
+               u64 bank_size = tegra_mem_map[bank].size;
+               u64 bank_end = bank_start + bank_size;
+               u64 allocated = ROUND(bank_start, align) + offset;
+               u64 allocated_end = allocated + size;
+
+               if (allocated_end > bank_end)
+                       continue;
+               mark_ram_allocated(bank, allocated, allocated_end);
+               return allocated;
+       }
+       return 0;
+}
+
+static void set_calculated_aliases(char *aliases, u64 address)
+{
+       char *tmp, *alias;
+       int err;
+
+       aliases = strdup(aliases);
+       if (!aliases) {
+               pr_err("strdup(aliases) failed");
+               return;
+       }
+
+       tmp = aliases;
+       while (true) {
+               alias = strsep(&tmp, " ");
+               if (!alias)
+                       break;
+               debug("%s: alias: %s\n", __func__, alias);
+               err = env_set_hex(alias, address);
+               if (err)
+                       pr_err("Could not set %s\n", alias);
+       }
+
+       free(aliases);
+}
+
+static void set_calculated_env_var(const char *var)
+{
+       char *var_size;
+       char *var_align;
+       char *var_offset;
+       char *var_aliases;
+       u64 size;
+       u64 align;
+       u64 offset;
+       char *aliases;
+       u64 address;
+       int err;
+
+       var_size = gen_varname(var, "_size");
+       if (!var_size)
+               return;
+       var_align = gen_varname(var, "_align");
+       if (!var_align)
+               goto out_free_var_size;
+       var_offset = gen_varname(var, "_offset");
+       if (!var_offset)
+               goto out_free_var_align;
+       var_aliases = gen_varname(var, "_aliases");
+       if (!var_aliases)
+               goto out_free_var_offset;
+
+       size = env_get_hex(var_size, 0);
+       if (!size) {
+               pr_err("%s not set or zero\n", var_size);
+               goto out_free_var_aliases;
+       }
+       align = env_get_hex(var_align, 1);
+       /* Handle extant variables, but with a value of 0 */
+       if (!align)
+               align = 1;
+       offset = env_get_hex(var_offset, 0);
+       aliases = env_get(var_aliases);
+
+       debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
+             __func__, var, size, align, offset);
+       if (aliases)
+               debug("%s: Aliases: %s\n", __func__, aliases);
+
+       address = alloc_ram(size, align, offset);
+       if (!address) {
+               pr_err("Could not allocate %s\n", var);
+               goto out_free_var_aliases;
+       }
+       debug("%s: Address %llx\n", __func__, address);
+
+       err = env_set_hex(var, address);
+       if (err)
+               pr_err("Could not set %s\n", var);
+       if (aliases)
+               set_calculated_aliases(aliases, address);
+
+out_free_var_aliases:
+       free(var_aliases);
+out_free_var_offset:
+       free(var_offset);
+out_free_var_align:
+       free(var_align);
+out_free_var_size:
+       free(var_size);
+}
+
+#ifdef DEBUG
+static void dump_ram_banks(void)
+{
+       int bank;
+
+       for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
+               u64 bank_start = tegra_mem_map[bank].virt;
+               u64 bank_size = tegra_mem_map[bank].size;
+               u64 bank_end = bank_start + bank_size;
+
+               if (!bank_size)
+                       continue;
+               printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
+                      bank_start, bank_end, bank_size);
+       }
+}
+#endif
+
+static void set_calculated_env_vars(void)
+{
+       char *vars, *tmp, *var;
+
+#ifdef DEBUG
+       printf("RAM banks before any calculated env. var.s:\n");
+       dump_ram_banks();
+#endif
+
+       reserve_ram(cboot_boot_x0, fdt_totalsize(cboot_boot_x0));
+
+#ifdef DEBUG
+       printf("RAM after reserving cboot DTB:\n");
+       dump_ram_banks();
+#endif
+
+       vars = env_get("calculated_vars");
+       if (!vars) {
+               debug("%s: No env var calculated_vars\n", __func__);
+               return;
+       }
+
+       vars = strdup(vars);
+       if (!vars) {
+               pr_err("strdup(calculated_vars) failed");
+               return;
+       }
+
+       tmp = vars;
+       while (true) {
+               var = strsep(&tmp, " ");
+               if (!var)
+                       break;
+               debug("%s: var: %s\n", __func__, var);
+               set_calculated_env_var(var);
+#ifdef DEBUG
+               printf("RAM banks after allocating %s:\n", var);
+               dump_ram_banks();
+#endif
+       }
+
+       free(vars);
+}
+
+static int set_fdt_addr(void)
+{
+       int ret;
+
+       ret = env_set_hex("fdt_addr", cboot_boot_x0);
+       if (ret) {
+               printf("Failed to set fdt_addr to point at DTB: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Attempt to use /chosen/nvidia,ether-mac in the cboot DTB to U-Boot's
+ * ethaddr environment variable if possible.
+ */
+static int cboot_get_ethaddr_legacy(const void *fdt, uint8_t mac[ETH_ALEN])
+{
+       const char *const properties[] = {
+               "nvidia,ethernet-mac",
+               "nvidia,ether-mac",
+       };
+       const char *prop;
+       unsigned int i;
+       int node, len;
+
+       node = fdt_path_offset(fdt, "/chosen");
+       if (node < 0) {
+               printf("Can't find /chosen node in cboot DTB\n");
+               return node;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(properties); i++) {
+               prop = fdt_getprop(fdt, node, properties[i], &len);
+               if (prop)
+                       break;
+       }
+
+       if (!prop) {
+               printf("Can't find Ethernet MAC address in cboot DTB\n");
+               return -ENOENT;
+       }
+
+       eth_parse_enetaddr(prop, mac);
+
+       if (!is_valid_ethaddr(mac)) {
+               printf("Invalid MAC address: %s\n", prop);
+               return -EINVAL;
+       }
+
+       debug("Legacy MAC address: %pM\n", mac);
+
+       return 0;
+}
+
+int cboot_get_ethaddr(const void *fdt, uint8_t mac[ETH_ALEN])
+{
+       int node, len, err = 0;
+       const uchar *prop;
+       const char *path;
+
+       path = fdt_get_alias(fdt, "ethernet");
+       if (!path) {
+               err = -ENOENT;
+               goto out;
+       }
+
+       debug("ethernet alias found: %s\n", path);
+
+       node = fdt_path_offset(fdt, path);
+       if (node < 0) {
+               err = -ENOENT;
+               goto out;
+       }
+
+       prop = fdt_getprop(fdt, node, "local-mac-address", &len);
+       if (!prop) {
+               err = -ENOENT;
+               goto out;
+       }
+
+       if (len != ETH_ALEN) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       debug("MAC address: %pM\n", prop);
+       memcpy(mac, prop, ETH_ALEN);
+
+out:
+       if (err < 0)
+               err = cboot_get_ethaddr_legacy(fdt, mac);
+
+       return err;
+}
+
+static char *strip(const char *ptr)
+{
+       const char *end;
+
+       while (*ptr && isblank(*ptr))
+               ptr++;
+
+       /* empty string */
+       if (*ptr == '\0')
+               return strdup(ptr);
+
+       end = ptr;
+
+       while (end[1])
+               end++;
+
+       while (isblank(*end))
+               end--;
+
+       return strndup(ptr, end - ptr + 1);
+}
+
+static char *cboot_get_bootargs(const void *fdt)
+{
+       const char *args;
+       int offset, len;
+
+       offset = fdt_path_offset(fdt, "/chosen");
+       if (offset < 0)
+               return NULL;
+
+       args = fdt_getprop(fdt, offset, "bootargs", &len);
+       if (!args)
+               return NULL;
+
+       return strip(args);
+}
+
+int cboot_late_init(void)
+{
+       const void *fdt = (const void *)cboot_boot_x0;
+       uint8_t mac[ETH_ALEN];
+       char *bootargs;
+       int err;
+
+       set_calculated_env_vars();
+       /*
+        * Ignore errors here; the value may not be used depending on
+        * extlinux.conf or boot script content.
+        */
+       set_fdt_addr();
+
+       /* Ignore errors here; not all cases care about Ethernet addresses */
+       err = cboot_get_ethaddr(fdt, mac);
+       if (!err) {
+               void *blob = (void *)gd->fdt_blob;
+
+               err = fdtdec_set_ethernet_mac_address(blob, mac, sizeof(mac));
+               if (err < 0)
+                       printf("failed to set MAC address %pM: %d\n", mac, err);
+       }
+
+       bootargs = cboot_get_bootargs(fdt);
+       if (bootargs) {
+               env_set("cbootargs", bootargs);
+               free(bootargs);
+       }
+
+       return 0;
+}
index dc5f16b41b60fa03737829751316a7dc7858b101..e539ad8b30a7bbe532e267cd2eb0679252e04a0c 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2010-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2019, NVIDIA CORPORATION.  All rights reserved.
  */
 
 /* Tegra SoC common clock control functions */
@@ -815,11 +815,16 @@ void tegra30_set_up_pllp(void)
 
 int clock_external_output(int clk_id)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
+       u32 val;
 
        if (clk_id >= 1 && clk_id <= 3) {
-               setbits_le32(&pmc->pmc_clk_out_cntrl,
-                            1 << (2 + (clk_id - 1) * 8));
+               val = tegra_pmc_readl(offsetof(struct pmc_ctlr,
+                                     pmc_clk_out_cntrl));
+               val |= 1 << (2 + (clk_id - 1) * 8);
+               tegra_pmc_writel(val,
+                                offsetof(struct pmc_ctlr,
+                                pmc_clk_out_cntrl));
+
        } else {
                printf("%s: Unknown output clock id %d\n", __func__, clk_id);
                return -EINVAL;
index 4e6beb3e5bb472b11bf27b11704d91b401b56737..4a889f0e3422fc1261f37bc37c7a52161cc32d26 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved.
  *
  * Derived from code (arch/arm/lib/reset.c) that is:
  *
 static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc,
                       char * const argv[])
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-
        puts("Entering RCM...\n");
        udelay(50000);
 
-       pmc->pmc_scratch0 = 2;
+       tegra_pmc_writel(2, PMC_SCRATCH0);
        disable_interrupts();
        reset_cpu(0);
 
index 1b6ad074ed8fcd7fd9a729445bcc4e67081fa3e4..3d140760e68fed6b52a9a45f7e76b6d601c936c5 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2010-2015, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2019, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #include <common.h>
@@ -299,21 +299,19 @@ void enable_cpu_clock(int enable)
 
 static int is_cpu_powered(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
-
-       return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0;
+       return (tegra_pmc_readl(offsetof(struct pmc_ctlr,
+                               pmc_pwrgate_status)) & CPU_PWRED) ? 1 : 0;
 }
 
 static void remove_cpu_io_clamps(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
        u32 reg;
        debug("%s entry\n", __func__);
 
        /* Remove the clamps on the CPU I/O signals */
-       reg = readl(&pmc->pmc_remove_clamping);
+       reg = tegra_pmc_readl(offsetof(struct pmc_ctlr, pmc_remove_clamping));
        reg |= CPU_CLMP;
-       writel(reg, &pmc->pmc_remove_clamping);
+       tegra_pmc_writel(reg, offsetof(struct pmc_ctlr, pmc_remove_clamping));
 
        /* Give I/O signals time to stabilize */
        udelay(IO_STABILIZATION_DELAY);
@@ -321,17 +319,19 @@ static void remove_cpu_io_clamps(void)
 
 void powerup_cpu(void)
 {
-       struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
        u32 reg;
        int timeout = IO_STABILIZATION_DELAY;
        debug("%s entry\n", __func__);
 
        if (!is_cpu_powered()) {
                /* Toggle the CPU power state (OFF -> ON) */
-               reg = readl(&pmc->pmc_pwrgate_toggle);
+               reg = tegra_pmc_readl(offsetof(struct pmc_ctlr,
+                                     pmc_pwrgate_toggle));
                reg &= PARTID_CP;
                reg |= START_CP;
-               writel(reg, &pmc->pmc_pwrgate_toggle);
+               tegra_pmc_writel(reg,
+                                offsetof(struct pmc_ctlr,
+                                pmc_pwrgate_toggle));
 
                /* Wait for the power to come up */
                while (!is_cpu_powered()) {
index 6697909d9a3e2269e877b59711670315f37c29c0..66628933b65398ffa6c60f614e7c269449451828 100644 (file)
@@ -8,10 +8,10 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/emc.h>
-#include <asm/arch/pmu.h>
 #include <asm/arch/tegra.h>
 #include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra/pmu.h>
 #include <asm/arch-tegra/sys_proto.h>
 
 DECLARE_GLOBAL_DATA_PTR;
diff --git a/arch/arm/mach-tegra/lowlevel_init.S b/arch/arm/mach-tegra/lowlevel_init.S
deleted file mode 100644 (file)
index 626f1b6..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * SoC-specific setup info
- *
- * (C) Copyright 2010,2011
- * NVIDIA Corporation <www.nvidia.com>
- */
-
-#include <config.h>
-#include <linux/linkage.h>
-
-#ifdef CONFIG_ARM64
-       .align  5
-ENTRY(reset_cpu)
-       /* get address for global reset register */
-       ldr     x1, =PRM_RSTCTRL
-       ldr     w3, [x1]
-       /* force reset */
-       orr     w3, w3, #0x10
-       str     w3, [x1]
-       mov     w0, w0
-1:
-       b       1b
-ENDPROC(reset_cpu)
-#else
-       .align  5
-ENTRY(reset_cpu)
-       ldr     r1, rstctl                      @ get addr for global reset
-                                               @ reg
-       ldr     r3, [r1]
-       orr     r3, r3, #0x10
-       str     r3, [r1]                        @ force reset
-       mov     r0, r0
-_loop_forever:
-       b       _loop_forever
-rstctl:
-       .word   PRM_RSTCTRL
-ENDPROC(reset_cpu)
-#endif
diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c
new file mode 100644 (file)
index 0000000..afd3c54
--- /dev/null
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
+ */
+
+#include <common.h>
+
+#include <linux/arm-smccc.h>
+
+#include <asm/io.h>
+#include <asm/arch-tegra/pmc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
+static bool tegra_pmc_detect_tz_only(void)
+{
+       static bool initialized = false;
+       static bool is_tz_only = false;
+       u32 value, saved;
+
+       if (!initialized) {
+               saved = readl(NV_PA_PMC_BASE + PMC_SCRATCH0);
+               value = saved ^ 0xffffffff;
+
+               if (value == 0xffffffff)
+                       value = 0xdeadbeef;
+
+               /* write pattern and read it back */
+               writel(value, NV_PA_PMC_BASE + PMC_SCRATCH0);
+               value = readl(NV_PA_PMC_BASE + PMC_SCRATCH0);
+
+               /* if we read all-zeroes, access is restricted to TZ only */
+               if (value == 0) {
+                       debug("access to PMC is restricted to TZ\n");
+                       is_tz_only = true;
+               } else {
+                       /* restore original value */
+                       writel(saved, NV_PA_PMC_BASE + PMC_SCRATCH0);
+               }
+
+               initialized = true;
+       }
+
+       return is_tz_only;
+}
+#endif
+
+uint32_t tegra_pmc_readl(unsigned long offset)
+{
+#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
+       if (tegra_pmc_detect_tz_only()) {
+               struct arm_smccc_res res;
+
+               arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0,
+                             0, 0, 0, &res);
+               if (res.a0)
+                       printf("%s(): SMC failed: %lu\n", __func__, res.a0);
+
+               return res.a1;
+       }
+#endif
+
+       return readl(NV_PA_PMC_BASE + offset);
+}
+
+void tegra_pmc_writel(u32 value, unsigned long offset)
+{
+#if IS_ENABLED(CONFIG_TEGRA_PMC_SECURE)
+       if (tegra_pmc_detect_tz_only()) {
+               struct arm_smccc_res res;
+
+               arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset,
+                             value, 0, 0, 0, 0, &res);
+               if (res.a0)
+                       printf("%s(): SMC failed: %lu\n", __func__, res.a0);
+
+               return;
+       }
+#endif
+
+       writel(value, NV_PA_PMC_BASE + offset);
+}
+
+void reset_cpu(ulong addr)
+{
+       u32 value;
+
+       value = tegra_pmc_readl(PMC_CNTRL);
+       value |= PMC_CNTRL_MAIN_RST;
+       tegra_pmc_writel(value, PMC_CNTRL);
+}
index e45f0961b242cdd92c344bcd186583dc80131f5b..761c9ef19e3b3abc6481bc42a5f114912bf9758e 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2019, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #include <common.h>
@@ -11,6 +11,7 @@
 
 #include <asm/arch/powergate.h>
 #include <asm/arch/tegra.h>
+#include <asm/arch-tegra/pmc.h>
 
 #define PWRGATE_TOGGLE 0x30
 #define  PWRGATE_TOGGLE_START (1 << 8)
@@ -24,18 +25,18 @@ static int tegra_powergate_set(enum tegra_powergate id, bool state)
        u32 value, mask = state ? (1 << id) : 0, old_mask;
        unsigned long start, timeout = 25;
 
-       value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+       value = tegra_pmc_readl(PWRGATE_STATUS);
        old_mask = value & (1 << id);
 
        if (mask == old_mask)
                return 0;
 
-       writel(PWRGATE_TOGGLE_START | id, NV_PA_PMC_BASE + PWRGATE_TOGGLE);
+       tegra_pmc_writel(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
 
        start = get_timer(0);
 
        while (get_timer(start) < timeout) {
-               value = readl(NV_PA_PMC_BASE + PWRGATE_STATUS);
+               value = tegra_pmc_readl(PWRGATE_STATUS);
                if ((value & (1 << id)) == mask)
                        return 0;
        }
@@ -69,7 +70,7 @@ static int tegra_powergate_remove_clamping(enum tegra_powergate id)
        else
                value = 1 << id;
 
-       writel(value, NV_PA_PMC_BASE + REMOVE_CLAMPING);
+       tegra_pmc_writel(value, REMOVE_CLAMPING);
 
        return 0;
 }
index 56f3378ecea373b938433e70b47682fd796f8326..3a24050277048c286498d0c075f0d78f4e5941c5 100644 (file)
@@ -2,8 +2,4 @@
 #
 # SPDX-License-Identifier: GPL-2.0
 
-obj-y += ../board186.o
 obj-y += cache.o
-obj-y += nvtboot_board.o
-obj-y += nvtboot_ll.o
-obj-y += nvtboot_mem.o
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_board.c b/arch/arm/mach-tegra/tegra186/nvtboot_board.c
deleted file mode 100644 (file)
index 83c0e93..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016-2018, NVIDIA CORPORATION.
- */
-
-#include <stdlib.h>
-#include <common.h>
-#include <fdt_support.h>
-#include <fdtdec.h>
-#include <asm/arch/tegra.h>
-#include <asm/armv8/mmu.h>
-
-extern unsigned long nvtboot_boot_x0;
-
-/*
- * The following few functions run late during the boot process and dynamically
- * calculate the load address of various binaries. To keep track of multiple
- * allocations, some writable list of RAM banks must be used. tegra_mem_map[]
- * is used for this purpose to avoid making yet another copy of the list of RAM
- * banks. This is safe because tegra_mem_map[] is only used once during very
- * early boot to create U-Boot's page tables, long before this code runs. If
- * this assumption becomes invalid later, we can just fix the code to copy the
- * list of RAM banks into some private data structure before running.
- */
-
-extern struct mm_region tegra_mem_map[];
-
-static char *gen_varname(const char *var, const char *ext)
-{
-       size_t len_var = strlen(var);
-       size_t len_ext = strlen(ext);
-       size_t len = len_var + len_ext + 1;
-       char *varext = malloc(len);
-
-       if (!varext)
-               return 0;
-       strcpy(varext, var);
-       strcpy(varext + len_var, ext);
-       return varext;
-}
-
-static void mark_ram_allocated(int bank, u64 allocated_start, u64 allocated_end)
-{
-       u64 bank_start = tegra_mem_map[bank].virt;
-       u64 bank_size = tegra_mem_map[bank].size;
-       u64 bank_end = bank_start + bank_size;
-       bool keep_front = allocated_start != bank_start;
-       bool keep_tail = allocated_end != bank_end;
-
-       if (keep_front && keep_tail) {
-               /*
-                * There are CONFIG_NR_DRAM_BANKS DRAM entries in the array,
-                * starting at index 1 (index 0 is MMIO). So, we are at DRAM
-                * entry "bank" not "bank - 1" as for a typical 0-base array.
-                * The number of remaining DRAM entries is therefore
-                * "CONFIG_NR_DRAM_BANKS - bank". We want to duplicate the
-                * current entry and shift up the remaining entries, dropping
-                * the last one. Thus, we must copy one fewer entry than the
-                * number remaining.
-                */
-               memmove(&tegra_mem_map[bank + 1], &tegra_mem_map[bank],
-                       CONFIG_NR_DRAM_BANKS - bank - 1);
-               tegra_mem_map[bank].size = allocated_start - bank_start;
-               bank++;
-               tegra_mem_map[bank].virt = allocated_end;
-               tegra_mem_map[bank].phys = allocated_end;
-               tegra_mem_map[bank].size = bank_end - allocated_end;
-       } else if (keep_front) {
-               tegra_mem_map[bank].size = allocated_start - bank_start;
-       } else if (keep_tail) {
-               tegra_mem_map[bank].virt = allocated_end;
-               tegra_mem_map[bank].phys = allocated_end;
-               tegra_mem_map[bank].size = bank_end - allocated_end;
-       } else {
-               /*
-                * We could move all subsequent banks down in the array but
-                * that's not necessary for subsequent allocations to work, so
-                * we skip doing so.
-                */
-               tegra_mem_map[bank].size = 0;
-       }
-}
-
-static void reserve_ram(u64 start, u64 size)
-{
-       int bank;
-       u64 end = start + size;
-
-       for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
-               u64 bank_start = tegra_mem_map[bank].virt;
-               u64 bank_size = tegra_mem_map[bank].size;
-               u64 bank_end = bank_start + bank_size;
-
-               if (end <= bank_start || start > bank_end)
-                       continue;
-               mark_ram_allocated(bank, start, end);
-               break;
-       }
-}
-
-static u64 alloc_ram(u64 size, u64 align, u64 offset)
-{
-       int bank;
-
-       for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
-               u64 bank_start = tegra_mem_map[bank].virt;
-               u64 bank_size = tegra_mem_map[bank].size;
-               u64 bank_end = bank_start + bank_size;
-               u64 allocated = ROUND(bank_start, align) + offset;
-               u64 allocated_end = allocated + size;
-
-               if (allocated_end > bank_end)
-                       continue;
-               mark_ram_allocated(bank, allocated, allocated_end);
-               return allocated;
-       }
-       return 0;
-}
-
-static void set_calculated_aliases(char *aliases, u64 address)
-{
-       char *tmp, *alias;
-       int err;
-
-       aliases = strdup(aliases);
-       if (!aliases) {
-               pr_err("strdup(aliases) failed");
-               return;
-       }
-
-       tmp = aliases;
-       while (true) {
-               alias = strsep(&tmp, " ");
-               if (!alias)
-                       break;
-               debug("%s: alias: %s\n", __func__, alias);
-               err = env_set_hex(alias, address);
-               if (err)
-                       pr_err("Could not set %s\n", alias);
-       }
-
-       free(aliases);
-}
-
-static void set_calculated_env_var(const char *var)
-{
-       char *var_size;
-       char *var_align;
-       char *var_offset;
-       char *var_aliases;
-       u64 size;
-       u64 align;
-       u64 offset;
-       char *aliases;
-       u64 address;
-       int err;
-
-       var_size = gen_varname(var, "_size");
-       if (!var_size)
-               return;
-       var_align = gen_varname(var, "_align");
-       if (!var_align)
-               goto out_free_var_size;
-       var_offset = gen_varname(var, "_offset");
-       if (!var_offset)
-               goto out_free_var_align;
-       var_aliases = gen_varname(var, "_aliases");
-       if (!var_aliases)
-               goto out_free_var_offset;
-
-       size = env_get_hex(var_size, 0);
-       if (!size) {
-               pr_err("%s not set or zero\n", var_size);
-               goto out_free_var_aliases;
-       }
-       align = env_get_hex(var_align, 1);
-       /* Handle extant variables, but with a value of 0 */
-       if (!align)
-               align = 1;
-       offset = env_get_hex(var_offset, 0);
-       aliases = env_get(var_aliases);
-
-       debug("%s: Calc var %s; size=%llx, align=%llx, offset=%llx\n",
-             __func__, var, size, align, offset);
-       if (aliases)
-               debug("%s: Aliases: %s\n", __func__, aliases);
-
-       address = alloc_ram(size, align, offset);
-       if (!address) {
-               pr_err("Could not allocate %s\n", var);
-               goto out_free_var_aliases;
-       }
-       debug("%s: Address %llx\n", __func__, address);
-
-       err = env_set_hex(var, address);
-       if (err)
-               pr_err("Could not set %s\n", var);
-       if (aliases)
-               set_calculated_aliases(aliases, address);
-
-out_free_var_aliases:
-       free(var_aliases);
-out_free_var_offset:
-       free(var_offset);
-out_free_var_align:
-       free(var_align);
-out_free_var_size:
-       free(var_size);
-}
-
-#ifdef DEBUG
-static void dump_ram_banks(void)
-{
-       int bank;
-
-       for (bank = 1; bank <= CONFIG_NR_DRAM_BANKS; bank++) {
-               u64 bank_start = tegra_mem_map[bank].virt;
-               u64 bank_size = tegra_mem_map[bank].size;
-               u64 bank_end = bank_start + bank_size;
-
-               if (!bank_size)
-                       continue;
-               printf("%d: %010llx..%010llx (+%010llx)\n", bank - 1,
-                      bank_start, bank_end, bank_size);
-       }
-}
-#endif
-
-static void set_calculated_env_vars(void)
-{
-       char *vars, *tmp, *var;
-
-#ifdef DEBUG
-       printf("RAM banks before any calculated env. var.s:\n");
-       dump_ram_banks();
-#endif
-
-       reserve_ram(nvtboot_boot_x0, fdt_totalsize(nvtboot_boot_x0));
-
-#ifdef DEBUG
-       printf("RAM after reserving cboot DTB:\n");
-       dump_ram_banks();
-#endif
-
-       vars = env_get("calculated_vars");
-       if (!vars) {
-               debug("%s: No env var calculated_vars\n", __func__);
-               return;
-       }
-
-       vars = strdup(vars);
-       if (!vars) {
-               pr_err("strdup(calculated_vars) failed");
-               return;
-       }
-
-       tmp = vars;
-       while (true) {
-               var = strsep(&tmp, " ");
-               if (!var)
-                       break;
-               debug("%s: var: %s\n", __func__, var);
-               set_calculated_env_var(var);
-#ifdef DEBUG
-               printf("RAM banks affter allocating %s:\n", var);
-               dump_ram_banks();
-#endif
-       }
-
-       free(vars);
-}
-
-static int set_fdt_addr(void)
-{
-       int ret;
-
-       ret = env_set_hex("fdt_addr", nvtboot_boot_x0);
-       if (ret) {
-               printf("Failed to set fdt_addr to point at DTB: %d\n", ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*
- * Attempt to use /chosen/nvidia,ether-mac in the nvtboot DTB to U-Boot's
- * ethaddr environment variable if possible.
- */
-static int set_ethaddr_from_nvtboot(void)
-{
-       const void *nvtboot_blob = (void *)nvtboot_boot_x0;
-       int ret, node, len;
-       const u32 *prop;
-
-       /* Already a valid address in the environment? If so, keep it */
-       if (env_get("ethaddr"))
-               return 0;
-
-       node = fdt_path_offset(nvtboot_blob, "/chosen");
-       if (node < 0) {
-               printf("Can't find /chosen node in nvtboot DTB\n");
-               return node;
-       }
-       prop = fdt_getprop(nvtboot_blob, node, "nvidia,ether-mac", &len);
-       if (!prop) {
-               printf("Can't find nvidia,ether-mac property in nvtboot DTB\n");
-               return -ENOENT;
-       }
-
-       ret = env_set("ethaddr", (void *)prop);
-       if (ret) {
-               printf("Failed to set ethaddr from nvtboot DTB: %d\n", ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-int tegra_soc_board_init_late(void)
-{
-       set_calculated_env_vars();
-       /*
-        * Ignore errors here; the value may not be used depending on
-        * extlinux.conf or boot script content.
-        */
-       set_fdt_addr();
-       /* Ignore errors here; not all cases care about Ethernet addresses */
-       set_ethaddr_from_nvtboot();
-
-       return 0;
-}
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_ll.S b/arch/arm/mach-tegra/tegra186/nvtboot_ll.S
deleted file mode 100644 (file)
index aa7a863..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Save nvtboot-related boot-time CPU state
- *
- * (C) Copyright 2015-2016 NVIDIA Corporation <www.nvidia.com>
- */
-
-#include <config.h>
-#include <linux/linkage.h>
-
-.align 8
-.globl nvtboot_boot_x0
-nvtboot_boot_x0:
-       .dword 0
-
-ENTRY(save_boot_params)
-       adr     x8, nvtboot_boot_x0
-       str     x0, [x8]
-       b       save_boot_params_ret
-ENDPROC(save_boot_params)
diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c
deleted file mode 100644 (file)
index 6214282..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2016-2018, NVIDIA CORPORATION.
- */
-
-#include <common.h>
-#include <fdt_support.h>
-#include <fdtdec.h>
-#include <linux/sizes.h>
-#include <asm/arch/tegra.h>
-#include <asm/armv8/mmu.h>
-
-/*
- * Size of a region that's large enough to hold the relocated U-Boot and all
- * other allocations made around it (stack, heap, page tables, etc.)
- * In practice, running "bdinfo" at the shell prompt, the stack reaches about
- * 5MB from the address selected for ram_top as of the time of writing,
- * so a 16MB region should be plenty.
- */
-#define MIN_USABLE_RAM_SIZE SZ_16M
-/*
- * The amount of space we expect to require for stack usage. Used to validate
- * that all reservations fit into the region selected for the relocation target
- */
-#define MIN_USABLE_STACK_SIZE SZ_1M
-
-DECLARE_GLOBAL_DATA_PTR;
-
-extern unsigned long nvtboot_boot_x0;
-extern struct mm_region tegra_mem_map[];
-
-/*
- * These variables are written to before relocation, and hence cannot be
- * in.bss, since .bss overlaps the DTB that's appended to the U-Boot binary.
- * The section attribute forces this into .data and avoids this issue. This
- * also has the nice side-effect of the content being valid after relocation.
- */
-
-/* The number of valid entries in ram_banks[] */
-static int ram_bank_count __attribute__((section(".data")));
-
-/*
- * The usable top-of-RAM for U-Boot. This is both:
- * a) Below 4GB to avoid issues with peripherals that use 32-bit addressing.
- * b) At the end of a region that has enough space to hold the relocated U-Boot
- *    and all other allocations made around it (stack, heap, page tables, etc.)
- */
-static u64 ram_top __attribute__((section(".data")));
-/* The base address of the region of RAM that ends at ram_top */
-static u64 region_base __attribute__((section(".data")));
-
-int dram_init(void)
-{
-       unsigned int na, ns;
-       const void *nvtboot_blob = (void *)nvtboot_boot_x0;
-       int node, len, i;
-       const u32 *prop;
-
-       na = fdtdec_get_uint(nvtboot_blob, 0, "#address-cells", 2);
-       ns = fdtdec_get_uint(nvtboot_blob, 0, "#size-cells", 2);
-
-       node = fdt_path_offset(nvtboot_blob, "/memory");
-       if (node < 0) {
-               pr_err("Can't find /memory node in nvtboot DTB");
-               hang();
-       }
-       prop = fdt_getprop(nvtboot_blob, node, "reg", &len);
-       if (!prop) {
-               pr_err("Can't find /memory/reg property in nvtboot DTB");
-               hang();
-       }
-
-       /* Calculate the true # of base/size pairs to read */
-       len /= 4;               /* Convert bytes to number of cells */
-       len /= (na + ns);       /* Convert cells to number of banks */
-       if (len > CONFIG_NR_DRAM_BANKS)
-               len = CONFIG_NR_DRAM_BANKS;
-
-       /* Parse the /memory node, and save useful entries */
-       gd->ram_size = 0;
-       ram_bank_count = 0;
-       for (i = 0; i < len; i++) {
-               u64 bank_start, bank_end, bank_size, usable_bank_size;
-
-               /* Extract raw memory region data from DTB */
-               bank_start = fdt_read_number(prop, na);
-               prop += na;
-               bank_size = fdt_read_number(prop, ns);
-               prop += ns;
-               gd->ram_size += bank_size;
-               bank_end = bank_start + bank_size;
-               debug("Bank %d: %llx..%llx (+%llx)\n", i,
-                     bank_start, bank_end, bank_size);
-
-               /*
-                * Align the bank to MMU section size. This is not strictly
-                * necessary, since the translation table construction code
-                * handles page granularity without issue. However, aligning
-                * the MMU entries reduces the size and number of levels in the
-                * page table, so is worth it.
-                */
-               bank_start = ROUND(bank_start, SZ_2M);
-               bank_end = bank_end & ~(SZ_2M - 1);
-               bank_size = bank_end - bank_start;
-               debug("  aligned: %llx..%llx (+%llx)\n",
-                     bank_start, bank_end, bank_size);
-               if (bank_end <= bank_start)
-                       continue;
-
-               /* Record data used to create MMU translation tables */
-               ram_bank_count++;
-               /* Index below is deliberately 1-based to skip MMIO entry */
-               tegra_mem_map[ram_bank_count].virt = bank_start;
-               tegra_mem_map[ram_bank_count].phys = bank_start;
-               tegra_mem_map[ram_bank_count].size = bank_size;
-               tegra_mem_map[ram_bank_count].attrs =
-                       PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE;
-
-               /* Determine best bank to relocate U-Boot into */
-               if (bank_end > SZ_4G)
-                       bank_end = SZ_4G;
-               debug("  end  %llx (usable)\n", bank_end);
-               usable_bank_size = bank_end - bank_start;
-               debug("  size %llx (usable)\n", usable_bank_size);
-               if ((usable_bank_size >= MIN_USABLE_RAM_SIZE) &&
-                   (bank_end > ram_top)) {
-                       ram_top = bank_end;
-                       region_base = bank_start;
-                       debug("ram top now %llx\n", ram_top);
-               }
-       }
-
-       /* Ensure memory map contains the desired sentinel entry */
-       tegra_mem_map[ram_bank_count + 1].virt = 0;
-       tegra_mem_map[ram_bank_count + 1].phys = 0;
-       tegra_mem_map[ram_bank_count + 1].size = 0;
-       tegra_mem_map[ram_bank_count + 1].attrs = 0;
-
-       /* Error out if a relocation target couldn't be found */
-       if (!ram_top) {
-               pr_err("Can't find a usable RAM top");
-               hang();
-       }
-
-       return 0;
-}
-
-int dram_init_banksize(void)
-{
-       int i;
-
-       if ((gd->start_addr_sp - region_base) < MIN_USABLE_STACK_SIZE) {
-               pr_err("Reservations exceed chosen region size");
-               hang();
-       }
-
-       for (i = 0; i < ram_bank_count; i++) {
-               gd->bd->bi_dram[i].start = tegra_mem_map[1 + i].virt;
-               gd->bd->bi_dram[i].size = tegra_mem_map[1 + i].size;
-       }
-
-#ifdef CONFIG_PCI
-       gd->pci_ram_top = ram_top;
-#endif
-
-       return 0;
-}
-
-ulong board_get_usable_ram_top(ulong total_size)
-{
-       return ram_top;
-}
index 06068c4b7b8d4406249b645138d59d5380b1d248..b240860f08cf30e8c74dbdcf0f16dd701dc1978b 100644 (file)
@@ -40,7 +40,7 @@ enum clock_type_id {
        CLOCK_TYPE_PDCT,
        CLOCK_TYPE_ACPT,
        CLOCK_TYPE_ASPTE,
-       CLOCK_TYPE_PMDACD2T,
+       CLOCK_TYPE_PDD2T,
        CLOCK_TYPE_PCST,
        CLOCK_TYPE_DP,
 
@@ -97,8 +97,8 @@ static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX+1] = {
        { CLK(AUDIO),   CLK(SFROM32KHZ),        CLK(PERIPH),    CLK(OSC),
                CLK(EPCI),      CLK(NONE),      CLK(NONE),      CLK(NONE),
                MASK_BITS_31_29},
-       { CLK(PERIPH),  CLK(MEMORY),    CLK(DISPLAY),   CLK(AUDIO),
-               CLK(CGENERAL),  CLK(DISPLAY2),  CLK(OSC),       CLK(NONE),
+       { CLK(PERIPH),  CLK(NONE),      CLK(DISPLAY),   CLK(NONE),
+               CLK(NONE),      CLK(DISPLAY2),  CLK(OSC),       CLK(NONE),
                MASK_BITS_31_29},
        { CLK(PERIPH),  CLK(CGENERAL),  CLK(SFROM32KHZ),        CLK(OSC),
                CLK(NONE),      CLK(NONE),      CLK(NONE),      CLK(NONE),
@@ -174,8 +174,8 @@ static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = {
        TYPE(PERIPHC_0bh,       CLOCK_TYPE_NONE),
        TYPE(PERIPHC_0ch,       CLOCK_TYPE_NONE),
        TYPE(PERIPHC_SBC1,      CLOCK_TYPE_PC2CC3M_T),
-       TYPE(PERIPHC_DISP1,     CLOCK_TYPE_PMDACD2T),
-       TYPE(PERIPHC_DISP2,     CLOCK_TYPE_PMDACD2T),
+       TYPE(PERIPHC_DISP1,     CLOCK_TYPE_PDD2T),
+       TYPE(PERIPHC_DISP2,     CLOCK_TYPE_PDD2T),
 
        /* 0x10 */
        TYPE(PERIPHC_10h,       CLOCK_TYPE_NONE),
@@ -1265,7 +1265,6 @@ struct periph_clk_init periph_clk_init_table[] = {
        { PERIPH_ID_SBC5, CLOCK_ID_PERIPH },
        { PERIPH_ID_SBC6, CLOCK_ID_PERIPH },
        { PERIPH_ID_HOST1X, CLOCK_ID_PERIPH },
-       { PERIPH_ID_DISP1, CLOCK_ID_CGENERAL },
        { PERIPH_ID_SDMMC1, CLOCK_ID_PERIPH },
        { PERIPH_ID_SDMMC2, CLOCK_ID_PERIPH },
        { PERIPH_ID_SDMMC3, CLOCK_ID_PERIPH },
index 807cfcdb196f631e6d4b86ed5e4c901e15069ace..1593e2bd4ea33936bc98d8d1afa1b8fe3eb99053 100644 (file)
@@ -73,6 +73,36 @@ int misc_init_r(void)
 /* SPL */
 #ifdef CONFIG_SPL_BUILD
 
+/* must set PB25 low to enable the CAN transceivers */
+static void board_can_stdby_dis(void)
+{
+       atmel_pio4_set_pio_output(AT91_PIO_PORTB, 25, 0);
+}
+
+static void board_leds_init(void)
+{
+       atmel_pio4_set_pio_output(AT91_PIO_PORTB, 0, 0); /* RED */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTB, 1, 1); /* GREEN */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTA, 31, 0); /* BLUE */
+}
+
+/* deassert reset lines for external periph in case of warm reboot */
+static void board_reset_additional_periph(void)
+{
+       atmel_pio4_set_pio_output(AT91_PIO_PORTB, 16, 0); /* LAN9252_RST */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTC, 2, 0); /* HSIC_RST */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTC, 17, 0); /* USB2534_RST */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTD, 4, 0); /* KSZ8563_RST */
+}
+
+static void board_start_additional_periph(void)
+{
+       atmel_pio4_set_pio_output(AT91_PIO_PORTB, 16, 1); /* LAN9252_RST */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTC, 2, 1); /* HSIC_RST */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTC, 17, 1); /* USB2534_RST */
+       atmel_pio4_set_pio_output(AT91_PIO_PORTD, 4, 1); /* KSZ8563_RST */
+}
+
 #ifdef CONFIG_SD_BOOT
 void spl_mmc_init(void)
 {
@@ -93,12 +123,20 @@ void spl_board_init(void)
 #ifdef CONFIG_SD_BOOT
        spl_mmc_init();
 #endif
+       board_reset_additional_periph();
+       board_can_stdby_dis();
+       board_leds_init();
 }
 
 void spl_display_print(void)
 {
 }
 
+void spl_board_prepare_for_boot(void)
+{
+       board_start_additional_periph();
+}
+
 static void ddrc_conf(struct atmel_mpddrc_config *ddrc)
 {
        ddrc->md = (ATMEL_MPDDRC_MD_DBW_32_BITS | ATMEL_MPDDRC_MD_DDR3_SDRAM);
index 212037da5ac03ccd32e51b9380080213220605db..4985302d6bc2129c74b2074e3a1d3428f6436e97 100644 (file)
@@ -5,9 +5,13 @@
  */
 
 #include <common.h>
+#include <environment.h>
+#include <fdtdec.h>
 #include <i2c.h>
+#include <linux/libfdt.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch-tegra/cboot.h>
 #include "../p2571/max77620_init.h"
 #include "pinmux-config-p2371-2180.h"
 
@@ -94,3 +98,96 @@ int tegra_pcie_board_init(void)
        return 0;
 }
 #endif /* PCI */
+
+static void ft_mac_address_setup(void *fdt)
+{
+       const void *cboot_fdt = (const void *)cboot_boot_x0;
+       uint8_t mac[ETH_ALEN], local_mac[ETH_ALEN];
+       const char *path;
+       int offset, err;
+
+       err = cboot_get_ethaddr(cboot_fdt, local_mac);
+       if (err < 0)
+               memset(local_mac, 0, ETH_ALEN);
+
+       path = fdt_get_alias(fdt, "ethernet");
+       if (!path)
+               return;
+
+       debug("ethernet alias found: %s\n", path);
+
+       offset = fdt_path_offset(fdt, path);
+       if (offset < 0) {
+               printf("ethernet alias points to absent node %s\n", path);
+               return;
+       }
+
+       if (is_valid_ethaddr(local_mac)) {
+               err = fdt_setprop(fdt, offset, "local-mac-address", local_mac,
+                                 ETH_ALEN);
+               if (!err)
+                       debug("Local MAC address set: %pM\n", local_mac);
+       }
+
+       if (eth_env_get_enetaddr("ethaddr", mac)) {
+               if (memcmp(local_mac, mac, ETH_ALEN) != 0) {
+                       err = fdt_setprop(fdt, offset, "mac-address", mac,
+                                         ETH_ALEN);
+                       if (!err)
+                               debug("MAC address set: %pM\n", mac);
+               }
+       }
+}
+
+static int ft_copy_carveout(void *dst, const void *src, const char *node)
+{
+       struct fdt_memory fb;
+       int err;
+
+       err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb);
+       if (err < 0) {
+               if (err != -FDT_ERR_NOTFOUND)
+                       printf("failed to get carveout for %s: %d\n", node,
+                              err);
+
+               return err;
+       }
+
+       err = fdtdec_set_carveout(dst, node, "memory-region", 0, "framebuffer",
+                                 &fb);
+       if (err < 0) {
+               printf("failed to set carveout for %s: %d\n", node, err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void ft_carveout_setup(void *fdt)
+{
+       const void *cboot_fdt = (const void *)cboot_boot_x0;
+       static const char * const nodes[] = {
+               "/host1x@50000000/dc@54200000",
+               "/host1x@50000000/dc@54240000",
+       };
+       unsigned int i;
+       int err;
+
+       for (i = 0; i < ARRAY_SIZE(nodes); i++) {
+               err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]);
+               if (err < 0) {
+                       if (err != -FDT_ERR_NOTFOUND)
+                               printf("failed to copy carveout for %s: %d\n",
+                                      nodes[i], err);
+                       continue;
+               }
+       }
+}
+
+int ft_board_setup(void *fdt, bd_t *bd)
+{
+       ft_mac_address_setup(fdt);
+       ft_carveout_setup(fdt);
+
+       return 0;
+}
index 496e8a02111e9a91c17f7c7026cdd8a6b6c4b5e2..d294c7ae01367ccb982e0b15dbe91dfa3b2284c3 100644 (file)
@@ -4,10 +4,14 @@
  */
 
 #include <common.h>
+#include <environment.h>
+#include <fdtdec.h>
 #include <i2c.h>
+#include <linux/libfdt.h>
+#include <asm/arch-tegra/cboot.h>
 #include "../p2571/max77620_init.h"
 
-int tegra_board_init(void)
+void pin_mux_mmc(void)
 {
        struct udevice *dev;
        uchar val;
@@ -18,19 +22,18 @@ int tegra_board_init(void)
        ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
        if (ret) {
                printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
-               return ret;
+               return;
        }
        /* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
        val = 0xF2;
        ret = dm_i2c_write(dev, MAX77620_CNFG1_L3_REG, &val, 1);
        if (ret) {
                printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
-               return ret;
+               return;
        }
-
-       return 0;
 }
 
+#ifdef CONFIG_PCI_TEGRA
 int tegra_pcie_board_init(void)
 {
        struct udevice *dev;
@@ -52,3 +55,101 @@ int tegra_pcie_board_init(void)
 
        return 0;
 }
+#endif
+
+static void ft_mac_address_setup(void *fdt)
+{
+       const void *cboot_fdt = (const void *)cboot_boot_x0;
+       uint8_t mac[ETH_ALEN], local_mac[ETH_ALEN];
+       const char *path;
+       int offset, err;
+
+       err = cboot_get_ethaddr(cboot_fdt, local_mac);
+       if (err < 0)
+               memset(local_mac, 0, ETH_ALEN);
+
+       path = fdt_get_alias(fdt, "ethernet");
+       if (!path)
+               return;
+
+       debug("ethernet alias found: %s\n", path);
+
+       offset = fdt_path_offset(fdt, path);
+       if (offset < 0) {
+               printf("ethernet alias points to absent node %s\n", path);
+               return;
+       }
+
+       if (is_valid_ethaddr(local_mac)) {
+               err = fdt_setprop(fdt, offset, "local-mac-address", local_mac,
+                                 ETH_ALEN);
+               if (!err)
+                       debug("Local MAC address set: %pM\n", local_mac);
+       }
+
+       if (eth_env_get_enetaddr("ethaddr", mac)) {
+               if (memcmp(local_mac, mac, ETH_ALEN) != 0) {
+                       err = fdt_setprop(fdt, offset, "mac-address", mac,
+                                         ETH_ALEN);
+                       if (!err)
+                               debug("MAC address set: %pM\n", mac);
+               }
+       }
+}
+
+static int ft_copy_carveout(void *dst, const void *src, const char *node)
+{
+       struct fdt_memory fb;
+       int err;
+
+       err = fdtdec_get_carveout(src, node, "memory-region", 0, &fb);
+       if (err < 0) {
+               if (err != -FDT_ERR_NOTFOUND)
+                       printf("failed to get carveout for %s: %d\n", node,
+                              err);
+
+               return err;
+       }
+
+       err = fdtdec_set_carveout(dst, node, "memory-region", 0, "framebuffer",
+                                 &fb);
+       if (err < 0) {
+               printf("failed to set carveout for %s: %d\n", node, err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void ft_carveout_setup(void *fdt)
+{
+       const void *cboot_fdt = (const void *)cboot_boot_x0;
+       static const char * const nodes[] = {
+               "/host1x@13e00000/display-hub@15200000/display@15200000",
+               "/host1x@13e00000/display-hub@15200000/display@15210000",
+               "/host1x@13e00000/display-hub@15200000/display@15220000",
+       };
+       unsigned int i;
+       int err;
+
+       for (i = 0; i < ARRAY_SIZE(nodes); i++) {
+               printf("copying carveout for %s...\n", nodes[i]);
+
+               err = ft_copy_carveout(fdt, cboot_fdt, nodes[i]);
+               if (err < 0) {
+                       if (err != -FDT_ERR_NOTFOUND)
+                               printf("failed to copy carveout for %s: %d\n",
+                                      nodes[i], err);
+
+                       continue;
+               }
+       }
+}
+
+int ft_board_setup(void *fdt, bd_t *bd)
+{
+       ft_mac_address_setup(fdt);
+       ft_carveout_setup(fdt);
+
+       return 0;
+}
index 95526b1e17e8f00e64722830274633206838ff0d..b34754fe518ca07208ed7bd8d3d107303dc8d934 100644 (file)
@@ -171,8 +171,7 @@ int drv_lcd_init(void)
 void lcd_clear(void)
 {
        int bg_color;
-       char *s;
-       ulong addr;
+       __maybe_unused ulong addr;
        static int do_splash = 1;
 #if LCD_BPP == LCD_COLOR8
        /* Setting the palette */
@@ -222,14 +221,10 @@ void lcd_clear(void)
        /* Paint the logo and retrieve LCD base address */
        debug("[LCD] Drawing the logo...\n");
        if (do_splash) {
-               s = env_get("splashimage");
-               if (s) {
+               if (splash_display() == 0) {
                        do_splash = 0;
-                       addr = simple_strtoul(s, NULL, 16);
-                       if (lcd_splash(addr) == 0) {
-                               lcd_sync();
-                               return;
-                       }
+                       lcd_sync();
+                       return;
                }
        }
 
index 48f6b39a7587ab5bc69f6f975e3c746c689dc88f..52b04976635449a15cb9bb0f73a0bd0dab3aadac 100644 (file)
@@ -1188,5 +1188,17 @@ config TPL_YMODEM_SUPPORT
 
 endif # TPL
 
+config SPL_AT91_MCK_BYPASS
+       bool "Use external clock signal as a source of main clock for AT91 platforms"
+       depends on ARCH_AT91
+       default n
+       help
+         Use external 8 to 24 Mhz clock signal as source of main clock instead
+         of an external crystal oscillator.
+         This option disables the internal driving on the XOUT pin.
+         The external source has to provide a stable clock on the XIN pin.
+         If this option is disabled, the SoC expects a crystal oscillator
+         that needs driving on both XIN and XOUT lines.
+
 endif # SPL
 endmenu
index d251b3b6547018f75faca2da742e89edd53af319..79d50577ee16c5d9e37cfd637923d43aa685053c 100644 (file)
@@ -80,11 +80,23 @@ void splash_get_pos(int *x, int *y)
 }
 #endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 
-#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
-int lcd_splash(ulong addr)
+/*
+ * Common function to show a splash image if env("splashimage") is set.
+ * Is used for both dm_video and lcd video stacks. For additional
+ * details please refer to doc/README.splashprepare.
+ */
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
+int splash_display(void)
 {
+       ulong addr;
+       char *s;
        int x = 0, y = 0, ret;
 
+       s = env_get("splashimage");
+       if (!s)
+               return -EINVAL;
+
+       addr = simple_strtoul(s, NULL, 16);
        ret = splash_screen_prepare();
        if (ret)
                return ret;
index ee22c1fd58523aa407bb7d1e63a9262e1a342306..54ecc9b53db9c2354d3b2f30c2517c58c7c77891 100644 (file)
@@ -16,6 +16,7 @@
 #include <malloc.h>
 #include <stdio_dev.h>
 #include <serial.h>
+#include <splash.h>
 
 #if defined(CONFIG_SYS_I2C)
 #include <i2c.h>
@@ -366,6 +367,9 @@ int stdio_add_devices(void)
        if (ret)
                printf("%s: Video device failed (ret=%d)\n", __func__, ret);
 #endif /* !CONFIG_SYS_CONSOLE_IS_IN_ENV */
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
+       splash_display();
+#endif /* CONFIG_SPLASH_SCREEN && CONFIG_CMD_BMP */
 #else
 # if defined(CONFIG_LCD)
        drv_lcd_init ();
index f1decf89a9f9e2616bced53d39f64ea649ba5aab..59d4ab0a041b92a3a0a9738bf8e0622223a00f92 100644 (file)
@@ -86,3 +86,4 @@ CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_IPUV3=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SYS_WHITE_ON_BLACK=y
index 2fa9f1f53244d79c4d29cb7c8d5f764ee842e2ab..bb11524794332a80ef14c14055cf06607d5b382b 100644 (file)
@@ -64,7 +64,7 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
 CONFIG_USB_GADGET_PRODUCT_NUM=0x4000
 CONFIG_CI_UDC=y
 CONFIG_USB_GADGET_DOWNLOAD=y
-CONFIG_VIDEO=y
+CONFIG_DM_VIDEO=y
 CONFIG_FAT_WRITE=y
 CONFIG_OF_LIBFDT_OVERLAY=y
 CONFIG_DM_USB=y
index 6b8a690ec354339d4e8c0ae8c1bed0c6b4756f8b..e652ebc5a57759c5405d2e310084fc0e7afda463 100644 (file)
@@ -65,3 +65,4 @@ CONFIG_DM_VIDEO=y
 CONFIG_VIDEO_TEGRA20=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_SYS_WHITE_ON_BLACK=y
index 4d253c507253a1f9fc71b0967cb818913786d084..d650acae24ce55d8f7d7de2755dce0157ee950af 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_OF_SYSTEM_SETUP=y
index 577dceb2d4b05509ac6dd9bbd3f13f254f66d71d..a25d3780640fe98b4a49f947fe5196a8e84ab9fd 100644 (file)
@@ -36,6 +36,7 @@ CONFIG_CMD_DM=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_MTD=y
 CONFIG_CMD_NAND=y
+CONFIG_CMD_WDT=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_PING=y
index 43454a122b7be2b8c1af60e6eb64338cdcddb829..154a075682695fe7d98e3e18cc04472d5fa6e0a1 100644 (file)
@@ -134,7 +134,6 @@ CONFIG_CMD_ENV_FLAGS=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_NAND=y
 CONFIG_CMD_NAND_TRIMFFS=y
-CONFIG_CMD_SPI=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
@@ -160,6 +159,4 @@ CONFIG_MII=y
 CONFIG_TSEC_ENET=y
 # CONFIG_PCI is not set
 CONFIG_SYS_NS16550=y
-CONFIG_SPI=y
-CONFIG_MPC8XXX_SPI=y
 CONFIG_OF_LIBFDT=y
index cdcb98a77eabf413479def3d6beb3a080a347136..aa9c1f66c4f0b31459081dd116518b5b4f353bf4 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_TARGET_P2371_0000=y
index 122b1b1fd5aa7000a54890e18b5cb74b69929789..2a21ff1dd08c11df01c724899d33abddfa0ce0de 100644 (file)
@@ -1,10 +1,11 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_TARGET_P2371_2180=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_SYS_PROMPT="Tegra210 (P2371-2180) # "
index d28506b1c66751218b31bca368ebd9668cc70405..1c47064c04a5be04c8a66e66de7c6e2f2f557be2 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
-CONFIG_SYS_TEXT_BASE=0x80110000
+CONFIG_SYS_TEXT_BASE=0x80080000
 CONFIG_NR_DRAM_BANKS=2
 CONFIG_TEGRA210=y
 CONFIG_TARGET_P2571=y
index 6d66cae3aafc7e394f2b86be6b86fb3e67e23848..4ac810db35d559d8bb20acc8a6a545c27c51fb50 100644 (file)
@@ -1,9 +1,10 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
 CONFIG_SYS_TEXT_BASE=0x80080000
-CONFIG_NR_DRAM_BANKS=8
+CONFIG_NR_DRAM_BANKS=1026
 CONFIG_TEGRA186=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_SYS_PROMPT="Tegra186 (P2771-0000-000) # "
index b8ac94ce60e508253e70e2a196347525043ac260..3ca85272a821bbc71bce2d8f0d461dbeb2d6f6f7 100644 (file)
@@ -1,9 +1,10 @@
 CONFIG_ARM=y
 CONFIG_TEGRA=y
 CONFIG_SYS_TEXT_BASE=0x80080000
-CONFIG_NR_DRAM_BANKS=8
+CONFIG_NR_DRAM_BANKS=1026
 CONFIG_TEGRA186=y
 CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_CONSOLE_MUX=y
 CONFIG_SYS_STDIO_DEREGISTER=y
 CONFIG_SYS_PROMPT="Tegra186 (P2771-0000-500) # "
index 1fafb767af78ad428ef9e536ea3263fdb04cd019..e0471086d6a3a1c445fc2ac13dc25c014caf90ab 100644 (file)
@@ -23,12 +23,12 @@ CONFIG_SD_BOOT=y
 CONFIG_BOOTDELAY=3
 CONFIG_USE_BOOTARGS=y
 # CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_SPL_TEXT_BASE=0x200000
 CONFIG_SPL_SEPARATE_BSS=y
 CONFIG_SPL_DISPLAY_PRINT=y
 # CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR is not set
 CONFIG_SPL_RAM_SUPPORT=y
 CONFIG_SPL_RAM_DEVICE=y
+CONFIG_SPL_AT91_MCK_BYPASS=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMI is not set
@@ -75,3 +75,4 @@ CONFIG_TIMER=y
 CONFIG_SPL_TIMER=y
 CONFIG_ATMEL_PIT_TIMER=y
 CONFIG_OF_LIBFDT_OVERLAY=y
+# CONFIG_EFI_LOADER_HII is not set
index bf2b5584df17b53d0d2ba8a5d21459da7fabb934..25b3aaf623edb339bcd2643036f5067a8cee8c24 100644 (file)
@@ -51,6 +51,7 @@ CONFIG_MMC_SDHCI_ATMEL=y
 CONFIG_NAND=y
 CONFIG_NAND_ATMEL=y
 CONFIG_ATMEL_NAND_HW_PMECC=y
+CONFIG_PMECC_CAP=4
 CONFIG_DM_ETH=y
 CONFIG_MACB=y
 CONFIG_PINCTRL=y
index 9608ecd0b33fb2e043bec9de8e9e61113c578e29..3f7e6270d0ca86409bdc30b4fe23b28edb53777b 100644 (file)
@@ -50,6 +50,7 @@ CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ATMEL=y
 CONFIG_NAND_ATMEL=y
 CONFIG_ATMEL_NAND_HW_PMECC=y
+CONFIG_PMECC_CAP=4
 CONFIG_DM_ETH=y
 CONFIG_MACB=y
 CONFIG_PINCTRL=y
index f673832dffcd313d2e7bb023edfcca399fa0e914..0504b4ec0fc6aa75360514a38ba56d4fb4624aa1 100644 (file)
@@ -59,6 +59,8 @@ CONFIG_DM_MMC=y
 CONFIG_GENERIC_ATMEL_MCI=y
 CONFIG_NAND=y
 CONFIG_NAND_ATMEL=y
+CONFIG_ATMEL_NAND_HW_PMECC=y
+CONFIG_PMECC_CAP=8
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
 CONFIG_SF_DEFAULT_SPEED=30000000
index 4b48689ee81914200e6cd69c027951446fb32165..0e8cf73fe9f02343eb4e8738b02240e0abd4b3fc 100644 (file)
@@ -20,7 +20,6 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_SPL_TEXT_BASE=0xff704000
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000
-CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
index df659f3dd921e9a6c3e7b3513e60589a2a4fb3fd..d38be3538a811aa99ad85cfdc4252b8fab0bc147 100644 (file)
@@ -59,10 +59,7 @@ No dm conversion yet:
        drivers/spi/cf_spi.c
        drivers/spi/fsl_espi.c
        drivers/spi/lpc32xx_ssp.c
-       drivers/spi/mpc8xx_spi.c
-       drivers/spi/mpc8xxx_spi.c
        drivers/spi/mxs_spi.c
-       drivers/spi/sh_qspi.c
        drivers/spi/sh_spi.c
        drivers/spi/soft_spi_legacy.c
 
@@ -70,13 +67,12 @@ No dm conversion yet:
        Deadline: 2019.04
 
 Partially converted:
-       drivers/spi/atcspi200_spi.c
        drivers/spi/davinci_spi.c
        drivers/spi/fsl_dspi.c
-       drivers/spi/fsl_qspi.c
        drivers/spi/kirkwood_spi.c
        drivers/spi/mxc_spi.c
        drivers/spi/omap3_spi.c
+       drivers/spi/sh_qspi.c
 
        Status: In progress
        Deadline: 2019.07
index 7044da35d68e45c771c4ded88c936d28a9e7e33c..eb32f082fe978fddc13bdadd38e3bc0e821134b9 100644 (file)
@@ -137,6 +137,11 @@ config MPC8XX_SPI
        help
          Enable support for SPI on MPC8XX
 
+config MPC8XXX_SPI
+       bool "MPC8XXX SPI Driver"
+       help
+         Enable support for SPI on the MPC8XXX PowerPC SoCs.
+
 config MT7621_SPI
        bool "MediaTek MT7621 SPI driver"
        depends on SOC_MT7628
@@ -370,11 +375,6 @@ config LPC32XX_SSP
        help
          Enable support for SPI on LPC32xx
 
-config MPC8XXX_SPI
-       bool "MPC8XXX SPI Driver"
-       help
-         Enable support for SPI on the MPC8XXX PowerPC SoCs.
-
 config MXC_SPI
        bool "MXC SPI Driver"
        help
index 8d6d86d2b0a1728aaf832b321b9e2352b4d72b5f..1c7bf10f91e37ccd83f314c0b9b73b230c6fef7d 100644 (file)
  */
 
 #include <common.h>
-
+#include <dm.h>
+#include <errno.h>
 #include <malloc.h>
 #include <spi.h>
 #include <asm/mpc8xxx_spi.h>
+#include <asm-generic/gpio.h>
+
+enum {
+       SPI_EV_NE = BIT(31 - 22),       /* Receiver Not Empty */
+       SPI_EV_NF = BIT(31 - 23),       /* Transmitter Not Full */
+};
+
+enum {
+       SPI_MODE_LOOP  = BIT(31 - 1),   /* Loopback mode */
+       SPI_MODE_CI    = BIT(31 - 2),   /* Clock invert */
+       SPI_MODE_CP    = BIT(31 - 3),   /* Clock phase */
+       SPI_MODE_DIV16 = BIT(31 - 4),   /* Divide clock source by 16 */
+       SPI_MODE_REV   = BIT(31 - 5),   /* Reverse mode - MSB first */
+       SPI_MODE_MS    = BIT(31 - 6),   /* Always master */
+       SPI_MODE_EN    = BIT(31 - 7),   /* Enable interface */
+
+       SPI_MODE_LEN_MASK = 0xf00000,
+       SPI_MODE_PM_MASK = 0xf0000,
+
+       SPI_COM_LST = BIT(31 - 9),
+};
+
+struct mpc8xxx_priv {
+       spi8xxx_t *spi;
+       struct gpio_desc gpios[16];
+       int max_cs;
+};
+
+static inline u32 to_prescale_mod(u32 val)
+{
+       return (min(val, (u32)15) << 16);
+}
 
-#define SPI_EV_NE      (0x80000000 >> 22)      /* Receiver Not Empty */
-#define SPI_EV_NF      (0x80000000 >> 23)      /* Transmitter Not Full */
-
-#define SPI_MODE_LOOP  (0x80000000 >> 1)       /* Loopback mode */
-#define SPI_MODE_REV   (0x80000000 >> 5)       /* Reverse mode - MSB first */
-#define SPI_MODE_MS    (0x80000000 >> 6)       /* Always master */
-#define SPI_MODE_EN    (0x80000000 >> 7)       /* Enable interface */
+static void set_char_len(spi8xxx_t *spi, u32 val)
+{
+       clrsetbits_be32(&spi->mode, SPI_MODE_LEN_MASK, (val << 20));
+}
 
 #define SPI_TIMEOUT    1000
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-               unsigned int max_hz, unsigned int mode)
+static int __spi_set_speed(spi8xxx_t *spi, uint speed)
 {
-       struct spi_slave *slave;
+       /* TODO(mario.six@gdsys.cc): This only ever sets one fixed speed */
 
-       if (!spi_cs_is_valid(bus, cs))
-               return NULL;
+       /* Use SYSCLK / 8 (16.67MHz typ.) */
+       clrsetbits_be32(&spi->mode, SPI_MODE_PM_MASK, to_prescale_mod(1));
 
-       slave = spi_alloc_slave_base(bus, cs);
-       if (!slave)
-               return NULL;
-
-       /*
-        * TODO: Some of the code in spi_init() should probably move
-        * here, or into spi_claim_bus() below.
-        */
-
-       return slave;
+       return 0;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+static int mpc8xxx_spi_ofdata_to_platdata(struct udevice *dev)
 {
-       free(slave);
+       struct mpc8xxx_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       priv->spi = (spi8xxx_t *)dev_read_addr(dev);
+
+       /* TODO(mario.six@gdsys.cc): Read clock and save the value */
+
+       ret = gpio_request_list_by_name(dev, "gpios", priv->gpios,
+                                       ARRAY_SIZE(priv->gpios), GPIOD_IS_OUT | GPIOD_ACTIVE_LOW);
+       if (ret < 0)
+               return -EINVAL;
+
+       priv->max_cs = ret;
+
+       return 0;
 }
 
-void spi_init(void)
+static int mpc8xxx_spi_probe(struct udevice *dev)
 {
-       volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
+       struct mpc8xxx_priv *priv = dev_get_priv(dev);
 
        /*
         * SPI pins on the MPC83xx are not muxed, so all we do is initialize
         * some registers
         */
-       spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
-       spi->mode = (spi->mode & 0xfff0ffff) | BIT(16); /* Use SYSCLK / 8
-                                                            (16.67MHz typ.) */
-       spi->event = 0xffffffff;        /* Clear all SPI events */
-       spi->mask = 0x00000000; /* Mask  all SPI interrupts */
-       spi->com = 0;           /* LST bit doesn't do anything, so disregard */
+       out_be32(&priv->spi->mode, SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN);
+
+       __spi_set_speed(priv->spi, 16666667);
+
+       /* Clear all SPI events */
+       setbits_be32(&priv->spi->event, 0xffffffff);
+       /* Mask  all SPI interrupts */
+       clrbits_be32(&priv->spi->mask, 0xffffffff);
+       /* LST bit doesn't do anything, so disregard */
+       out_be32(&priv->spi->com, 0);
+
+       return 0;
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+static void mpc8xxx_spi_cs_activate(struct udevice *dev)
 {
-       return 0;
+       struct mpc8xxx_priv *priv = dev_get_priv(dev->parent);
+       struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+
+       dm_gpio_set_dir_flags(&priv->gpios[platdata->cs], GPIOD_IS_OUT);
+       dm_gpio_set_value(&priv->gpios[platdata->cs], 0);
 }
 
-void spi_release_bus(struct spi_slave *slave)
+static void mpc8xxx_spi_cs_deactivate(struct udevice *dev)
 {
+       struct mpc8xxx_priv *priv = dev_get_priv(dev->parent);
+       struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
 
+       dm_gpio_set_dir_flags(&priv->gpios[platdata->cs], GPIOD_IS_OUT);
+       dm_gpio_set_value(&priv->gpios[platdata->cs], 1);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-               void *din, unsigned long flags)
+static int mpc8xxx_spi_xfer(struct udevice *dev, uint bitlen,
+                           const void *dout, void *din, ulong flags)
 {
-       volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
-       unsigned int tmpdout, tmpdin, event;
-       int numBlks = DIV_ROUND_UP(bitlen, 32);
-       int tm, isRead = 0;
-       unsigned char charSize = 32;
+       struct udevice *bus = dev->parent;
+       struct mpc8xxx_priv *priv = dev_get_priv(bus);
+       spi8xxx_t *spi = priv->spi;
+       struct dm_spi_slave_platdata *platdata = dev_get_parent_platdata(dev);
+       u32 tmpdin = 0;
+       int num_blks = DIV_ROUND_UP(bitlen, 32);
 
-       debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
-             slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);
+       debug("%s: slave %s:%u dout %08X din %08X bitlen %u\n", __func__,
+             bus->name, platdata->cs, *(uint *)dout, *(uint *)din, bitlen);
 
        if (flags & SPI_XFER_BEGIN)
-               spi_cs_activate(slave);
+               mpc8xxx_spi_cs_activate(dev);
+
+       /* Clear all SPI events */
+       setbits_be32(&spi->event, 0xffffffff);
+
+       /* Handle data in 32-bit chunks */
+       while (num_blks--) {
+               u32 tmpdout = 0;
+               uchar xfer_bitlen = (bitlen >= 32 ? 32 : bitlen);
+               ulong start;
 
-       spi->event = 0xffffffff;        /* Clear all SPI events */
+               clrbits_be32(&spi->mode, SPI_MODE_EN);
 
-       /* handle data in 32-bit chunks */
-       while (numBlks--) {
-               tmpdout = 0;
-               charSize = (bitlen >= 32 ? 32 : bitlen);
+               /* Set up length for this transfer */
+
+               if (bitlen <= 4) /* 4 bits or less */
+                       set_char_len(spi, 3);
+               else if (bitlen <= 16) /* at most 16 bits */
+                       set_char_len(spi, bitlen - 1);
+               else /* more than 16 bits -> full 32 bit transfer */
+                       set_char_len(spi, 0);
+
+               setbits_be32(&spi->mode, SPI_MODE_EN);
 
                /* Shift data so it's msb-justified */
-               tmpdout = *(u32 *) dout >> (32 - charSize);
-
-               /* The LEN field of the SPMODE register is set as follows:
-                *
-                * Bit length             setting
-                * len <= 4               3
-                * 4 < len <= 16          len - 1
-                * len > 16               0
-                */
+               tmpdout = *(u32 *)dout >> (32 - xfer_bitlen);
 
-               spi->mode &= ~SPI_MODE_EN;
-
-               if (bitlen <= 16) {
-                       if (bitlen <= 4)
-                               spi->mode = (spi->mode & 0xff0fffff) |
-                                           (3 << 20);
-                       else
-                               spi->mode = (spi->mode & 0xff0fffff) |
-                                           ((bitlen - 1) << 20);
-               } else {
-                       spi->mode = (spi->mode & 0xff0fffff);
+               if (bitlen > 32) {
                        /* Set up the next iteration if sending > 32 bits */
                        bitlen -= 32;
                        dout += 4;
                }
 
-               spi->mode |= SPI_MODE_EN;
+               /* Write the data out */
+               out_be32(&spi->tx, tmpdout);
 
-               spi->tx = tmpdout;      /* Write the data out */
-               debug("*** spi_xfer: ... %08x written\n", tmpdout);
+               debug("*** %s: ... %08x written\n", __func__, tmpdout);
 
                /*
                 * Wait for SPI transmit to get out
                 * or time out (1 second = 1000 ms)
                 * The NE event must be read and cleared first
                 */
-               for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) {
-                       event = spi->event;
-                       if (event & SPI_EV_NE) {
-                               tmpdin = spi->rx;
-                               spi->event |= SPI_EV_NE;
-                               isRead = 1;
-
-                               *(u32 *) din = (tmpdin << (32 - charSize));
-                               if (charSize == 32) {
-                                       /* Advance output buffer by 32 bits */
-                                       din += 4;
-                               }
+               start = get_timer(0);
+               do {
+                       u32 event = in_be32(&spi->event);
+                       bool have_ne = event & SPI_EV_NE;
+                       bool have_nf = event & SPI_EV_NF;
+
+                       if (!have_ne)
+                               continue;
+
+                       tmpdin = in_be32(&spi->rx);
+                       setbits_be32(&spi->event, SPI_EV_NE);
+
+                       *(u32 *)din = (tmpdin << (32 - xfer_bitlen));
+                       if (xfer_bitlen == 32) {
+                               /* Advance output buffer by 32 bits */
+                               din += 4;
                        }
+
                        /*
                         * Only bail when we've had both NE and NF events.
                         * This will cause timeouts on RO devices, so maybe
                         * in the future put an arbitrary delay after writing
                         * the device.  Arbitrary delays suck, though...
                         */
-                       if (isRead && (event & SPI_EV_NF))
+                       if (have_nf)
                                break;
+
+                       mdelay(1);
+               } while (get_timer(start) < SPI_TIMEOUT);
+
+               if (get_timer(start) >= SPI_TIMEOUT) {
+                       debug("*** %s: Time out during SPI transfer\n",
+                             __func__);
+                       return -ETIMEDOUT;
                }
-               if (tm >= SPI_TIMEOUT)
-                       puts("*** spi_xfer: Time out during SPI transfer");
 
-               debug("*** spi_xfer: transfer ended. Value=%08x\n", tmpdin);
+               debug("*** %s: transfer ended. Value=%08x\n", __func__, tmpdin);
        }
 
        if (flags & SPI_XFER_END)
-               spi_cs_deactivate(slave);
+               mpc8xxx_spi_cs_deactivate(dev);
 
        return 0;
 }
+
+static int mpc8xxx_spi_set_speed(struct udevice *dev, uint speed)
+{
+       struct mpc8xxx_priv *priv = dev_get_priv(dev);
+
+       return __spi_set_speed(priv->spi, speed);
+}
+
+static int mpc8xxx_spi_set_mode(struct udevice *dev, uint mode)
+{
+       /* TODO(mario.six@gdsys.cc): Using SPI_CPHA (for clock phase) and
+        * SPI_CPOL (for clock polarity) should work
+        */
+       return 0;
+}
+
+static const struct dm_spi_ops mpc8xxx_spi_ops = {
+       .xfer           = mpc8xxx_spi_xfer,
+       .set_speed      = mpc8xxx_spi_set_speed,
+       .set_mode       = mpc8xxx_spi_set_mode,
+       /*
+        * cs_info is not needed, since we require all chip selects to be
+        * in the device tree explicitly
+        */
+};
+
+static const struct udevice_id mpc8xxx_spi_ids[] = {
+       { .compatible = "fsl,spi" },
+       { }
+};
+
+U_BOOT_DRIVER(mpc8xxx_spi) = {
+       .name   = "mpc8xxx_spi",
+       .id     = UCLASS_SPI,
+       .of_match = mpc8xxx_spi_ids,
+       .ops    = &mpc8xxx_spi_ops,
+       .ofdata_to_platdata = mpc8xxx_spi_ofdata_to_platdata,
+       .probe  = mpc8xxx_spi_probe,
+       .priv_auto_alloc_size = sizeof(struct mpc8xxx_priv),
+};
index 7a1c060856a3b25bed58fe110ba8a082b2bda316..483c93f6b6cb50a185340e32e80f4773926661ec 100644 (file)
@@ -361,13 +361,19 @@ static int meson_dw_hdmi_probe(struct udevice *dev)
        priv->hdmi.i2c_clk_high = 0x67;
        priv->hdmi.i2c_clk_low = 0x78;
 
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
        ret = device_get_supply_regulator(dev, "hdmi-supply", &supply);
-       if (ret)
+       if (ret && ret != -ENOENT) {
+               pr_err("Failed to get HDMI regulator\n");
                return ret;
+       }
 
-       ret = regulator_set_enable(supply, true);
-       if (ret)
-               return ret;
+       if (!ret) {
+               ret = regulator_set_enable(supply, true);
+               if (ret)
+                       return ret;
+       }
+#endif
 
        ret = reset_get_bulk(dev, &resets);
        if (ret)
index 02fde0590829a098d8af87b1af886f7b2e6787a9..f02ba201384619d8e9b07a78ed90a9f56ba79383 100644 (file)
@@ -5,22 +5,26 @@
  * Copyright (C) 2011-2013 Marek Vasut <marex@denx.de>
  */
 #include <common.h>
+#include <dm.h>
+#include <linux/errno.h>
 #include <malloc.h>
+#include <video.h>
 #include <video_fb.h>
 
-#include <asm/arch/imx-regs.h>
 #include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
 #include <asm/arch/sys_proto.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-
 #include <asm/mach-imx/dma.h>
+#include <asm/io.h>
 
 #include "videomodes.h"
 
 #define        PS2KHZ(ps)      (1000000000UL / (ps))
+#define HZ2PS(hz)      (1000000000UL / ((hz) / 1000))
+
+#define BITS_PP                18
+#define BYTES_PP       4
 
-static GraphicDevice panel;
 struct mxs_dma_desc desc;
 
 /**
@@ -46,8 +50,7 @@ __weak void mxsfb_system_setup(void)
  *      le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0
  */
 
-static void mxs_lcd_init(GraphicDevice *panel,
-                       struct ctfb_res_modes *mode, int bpp)
+static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp)
 {
        struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
        uint32_t word_len = 0, bus_width = 0;
@@ -112,8 +115,8 @@ static void mxs_lcd_init(GraphicDevice *panel,
        writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | mode->xres,
                &regs->hw_lcdif_vdctrl4);
 
-       writel(panel->frameAdrs, &regs->hw_lcdif_cur_buf);
-       writel(panel->frameAdrs, &regs->hw_lcdif_next_buf);
+       writel(fb_addr, &regs->hw_lcdif_cur_buf);
+       writel(fb_addr, &regs->hw_lcdif_next_buf);
 
        /* Flush FIFO first */
        writel(LCDIF_CTRL1_FIFO_CLEAR, &regs->hw_lcdif_ctrl1_set);
@@ -130,16 +133,47 @@ static void mxs_lcd_init(GraphicDevice *panel,
        writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
 }
 
-void lcdif_power_down(void)
+static int mxs_probe_common(struct ctfb_res_modes *mode, int bpp, u32 fb)
+{
+       /* Start framebuffer */
+       mxs_lcd_init(fb, mode, bpp);
+
+#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
+       /*
+        * If the LCD runs in system mode, the LCD refresh has to be triggered
+        * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid
+        * having to set this bit manually after every single change in the
+        * framebuffer memory, we set up specially crafted circular DMA, which
+        * sets the RUN bit, then waits until it gets cleared and repeats this
+        * infinitelly. This way, we get smooth continuous updates of the LCD.
+        */
+       struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+
+       memset(&desc, 0, sizeof(struct mxs_dma_desc));
+       desc.address = (dma_addr_t)&desc;
+       desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
+                       MXS_DMA_DESC_WAIT4END |
+                       (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+       desc.cmd.pio_words[0] = readl(&regs->hw_lcdif_ctrl) | LCDIF_CTRL_RUN;
+       desc.cmd.next = (uint32_t)&desc.cmd;
+
+       /* Execute the DMA chain. */
+       mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc);
+#endif
+
+       return 0;
+}
+
+static int mxs_remove_common(u32 fb)
 {
        struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
        int timeout = 1000000;
 
-       if (!panel.frameAdrs)
-               return;
+       if (!fb)
+               return -EINVAL;
 
-       writel(panel.frameAdrs, &regs->hw_lcdif_cur_buf_reg);
-       writel(panel.frameAdrs, &regs->hw_lcdif_next_buf_reg);
+       writel(fb, &regs->hw_lcdif_cur_buf_reg);
+       writel(fb, &regs->hw_lcdif_next_buf_reg);
        writel(LCDIF_CTRL1_VSYNC_EDGE_IRQ, &regs->hw_lcdif_ctrl1_clr);
        while (--timeout) {
                if (readl(&regs->hw_lcdif_ctrl1_reg) &
@@ -148,13 +182,25 @@ void lcdif_power_down(void)
                udelay(1);
        }
        mxs_reset_block((struct mxs_register_32 *)&regs->hw_lcdif_ctrl_reg);
+
+       return 0;
+}
+
+#ifndef CONFIG_DM_VIDEO
+
+static GraphicDevice panel;
+
+void lcdif_power_down(void)
+{
+       mxs_remove_common(panel.frameAdrs);
 }
 
 void *video_hw_init(void)
 {
        int bpp = -1;
+       int ret = 0;
        char *penv;
-       void *fb;
+       void *fb = NULL;
        struct ctfb_res_modes mode;
 
        puts("Video: ");
@@ -169,8 +215,7 @@ void *video_hw_init(void)
        bpp = video_get_params(&mode, penv);
 
        /* fill in Graphic device struct */
-       sprintf(panel.modeIdent, "%dx%dx%d",
-                       mode.xres, mode.yres, bpp);
+       sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp);
 
        panel.winSizeX = mode.xres;
        panel.winSizeY = mode.yres;
@@ -213,31 +258,125 @@ void *video_hw_init(void)
 
        printf("%s\n", panel.modeIdent);
 
-       /* Start framebuffer */
-       mxs_lcd_init(&panel, &mode, bpp);
+       ret = mxs_probe_common(&mode, bpp, (u32)fb);
+       if (ret)
+               goto dealloc_fb;
 
-#ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM
-       /*
-        * If the LCD runs in system mode, the LCD refresh has to be triggered
-        * manually by setting the RUN bit in HW_LCDIF_CTRL register. To avoid
-        * having to set this bit manually after every single change in the
-        * framebuffer memory, we set up specially crafted circular DMA, which
-        * sets the RUN bit, then waits until it gets cleared and repeats this
-        * infinitelly. This way, we get smooth continuous updates of the LCD.
-        */
-       struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
+       return (void *)&panel;
 
-       memset(&desc, 0, sizeof(struct mxs_dma_desc));
-       desc.address = (dma_addr_t)&desc;
-       desc.cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_CHAIN |
-                       MXS_DMA_DESC_WAIT4END |
-                       (1 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
-       desc.cmd.pio_words[0] = readl(&regs->hw_lcdif_ctrl) | LCDIF_CTRL_RUN;
-       desc.cmd.next = (uint32_t)&desc.cmd;
+dealloc_fb:
+       free(fb);
 
-       /* Execute the DMA chain. */
-       mxs_dma_circ_start(MXS_DMA_CHANNEL_AHB_APBH_LCDIF, &desc);
-#endif
+       return NULL;
+}
+#else /* ifndef CONFIG_DM_VIDEO */
 
-       return (void *)&panel;
+static int mxs_video_probe(struct udevice *dev)
+{
+       struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+
+       struct ctfb_res_modes mode;
+       struct display_timing timings;
+       int bpp = -1;
+       u32 fb_start, fb_end;
+       int ret;
+
+       debug("%s() plat: base 0x%lx, size 0x%x\n",
+              __func__, plat->base, plat->size);
+
+       ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, &timings);
+       if (ret) {
+               dev_err(dev, "failed to get any display timings\n");
+               return -EINVAL;
+       }
+
+       mode.xres = timings.hactive.typ;
+       mode.yres = timings.vactive.typ;
+       mode.left_margin = timings.hback_porch.typ;
+       mode.right_margin = timings.hfront_porch.typ;
+       mode.upper_margin = timings.vback_porch.typ;
+       mode.lower_margin = timings.vfront_porch.typ;
+       mode.hsync_len = timings.hsync_len.typ;
+       mode.vsync_len = timings.vsync_len.typ;
+       mode.pixclock = HZ2PS(timings.pixelclock.typ);
+
+       bpp = BITS_PP;
+
+       ret = mxs_probe_common(&mode, bpp, plat->base);
+       if (ret)
+               return ret;
+
+       switch (bpp) {
+       case 24:
+       case 18:
+               uc_priv->bpix = VIDEO_BPP32;
+               break;
+       case 16:
+               uc_priv->bpix = VIDEO_BPP16;
+               break;
+       case 8:
+               uc_priv->bpix = VIDEO_BPP8;
+               break;
+       default:
+               dev_err(dev, "invalid bpp specified (bpp = %i)\n", bpp);
+               return -EINVAL;
+       }
+
+       uc_priv->xsize = mode.xres;
+       uc_priv->ysize = mode.yres;
+
+       /* Enable dcache for the frame buffer */
+       fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
+       fb_end = plat->base + plat->size;
+       fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
+       mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
+                                       DCACHE_WRITEBACK);
+       video_set_flush_dcache(dev, true);
+
+       return ret;
+}
+
+static int mxs_video_bind(struct udevice *dev)
+{
+       struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+       struct display_timing timings;
+       int ret;
+
+       ret = ofnode_decode_display_timing(dev_ofnode(dev), 0, &timings);
+       if (ret) {
+               dev_err(dev, "failed to get any display timings\n");
+               return -EINVAL;
+       }
+
+       plat->size = timings.hactive.typ * timings.vactive.typ * BYTES_PP;
+
+       return 0;
 }
+
+static int mxs_video_remove(struct udevice *dev)
+{
+       struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+       mxs_remove_common(plat->base);
+
+       return 0;
+}
+
+static const struct udevice_id mxs_video_ids[] = {
+       { .compatible = "fsl,imx23-lcdif" },
+       { .compatible = "fsl,imx28-lcdif" },
+       { .compatible = "fsl,imx7ulp-lcdif" },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(mxs_video) = {
+       .name   = "mxs_video",
+       .id     = UCLASS_VIDEO,
+       .of_match = mxs_video_ids,
+       .bind   = mxs_video_bind,
+       .probe  = mxs_video_probe,
+       .remove = mxs_video_remove,
+       .flags  = DM_FLAG_PRE_RELOC,
+};
+#endif /* ifndef CONFIG_DM_VIDEO */
index 3e4f63e7ba04e195c16f2472e1bc4c97026a9bd6..545f506e97f75bc27c1b6a69f1c0eb56cf5e877a 100644 (file)
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE   SZ_16M
 #define DFU_DEFAULT_POLL_TIMEOUT       300
 
-#ifdef CONFIG_VIDEO
+#if defined(CONFIG_VIDEO) || defined(CONFIG_DM_VIDEO)
 #define CONFIG_VIDEO_MXS
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_SPLASH_SCREEN
index e54428ba43e202acdd8a363874c1bbd4f4feb65b..9685ee5059abede014ee3089c76c65e769159685 100644 (file)
 #define CONFIG_SYS_NONCACHED_MEMORY    (1 << 20)       /* 1 MiB */
 
 #ifndef CONFIG_SPL_BUILD
+#ifndef BOOT_TARGET_DEVICES
 #define BOOT_TARGET_DEVICES(func) \
        func(MMC, mmc, 1) \
        func(MMC, mmc, 0) \
        func(USB, usb, 0) \
        func(PXE, pxe, na) \
        func(DHCP, dhcp, na)
+#endif
 #include <config_distro_bootcmd.h>
 #else
 #define BOOTENV
index fa8e34f6f9608e48e380c8c4e0011d342832f5e7..e6c22dd5cd5c17abc7f0eb3c57402d4ffd52dd3a 100644 (file)
@@ -996,6 +996,30 @@ int fdtdec_setup_memory_banksize_fdt(const void *blob);
  */
 int fdtdec_setup_memory_banksize(void);
 
+/**
+ * fdtdec_set_ethernet_mac_address() - set MAC address for default interface
+ *
+ * Looks up the default interface via the "ethernet" alias (in the /aliases
+ * node) and stores the given MAC in its "local-mac-address" property. This
+ * is useful on platforms that store the MAC address in a custom location.
+ * Board code can call this in the late init stage to make sure that the
+ * interface device tree node has the right MAC address configured for the
+ * Ethernet uclass to pick it up.
+ *
+ * Typically the FDT passed into this function will be U-Boot's control DTB.
+ * Given that a lot of code may be holding offsets to various nodes in that
+ * tree, this code will only set the "local-mac-address" property in-place,
+ * which means that it needs to exist and have space for the 6-byte address.
+ * This ensures that the operation is non-destructive and does not invalidate
+ * offsets that other drivers may be using.
+ *
+ * @param fdt FDT blob
+ * @param mac buffer containing the MAC address to set
+ * @param size size of MAC address
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size);
+
 /**
  * fdtdec_set_phandle() - sets the phandle of a given node
  *
index 36066207392e9c478b1e7a08c389ba34196827a3..5d63be4ce5b065a1b81fd57ca6612f04716af7db 100644 (file)
@@ -94,6 +94,7 @@ size_t strcspn(const char *s, const char *reject);
 #ifndef __HAVE_ARCH_STRDUP
 extern char * strdup(const char *);
 #endif
+extern char * strndup(const char *, size_t);
 #ifndef __HAVE_ARCH_STRSWAB
 extern char * strswab(const char *);
 #endif
index 228aff441b87f46c3747d5376773b559898ebea5..7fd2de8fea1dd582f5b6f9e936d86b764bde6ec4 100644 (file)
@@ -66,10 +66,10 @@ void splash_get_pos(int *x, int *y);
 static inline void splash_get_pos(int *x, int *y) { }
 #endif
 
-#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_LCD)
-int lcd_splash(ulong addr);
+#if defined(CONFIG_SPLASH_SCREEN) && defined(CONFIG_CMD_BMP)
+int splash_display(void);
 #else
-static inline int lcd_splash(ulong addr)
+static inline int splash_display(void)
 {
        return -ENOSYS;
 }
index d0ba8889733592001dc41d3a4a77a54270c6ce4c..3ee786b57940df4b12f89cce3003f2c2a252c9e0 100644 (file)
@@ -1261,6 +1261,35 @@ __weak void *board_fdt_blob_setup(void)
 }
 #endif
 
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size)
+{
+       const char *path;
+       int offset, err;
+
+       if (!is_valid_ethaddr(mac))
+               return -EINVAL;
+
+       path = fdt_get_alias(fdt, "ethernet");
+       if (!path)
+               return 0;
+
+       debug("ethernet alias found: %s\n", path);
+
+       offset = fdt_path_offset(fdt, path);
+       if (offset < 0) {
+               debug("ethernet alias points to absent node %s\n", path);
+               return -ENOENT;
+       }
+
+       err = fdt_setprop_inplace(fdt, offset, "local-mac-address", mac, size);
+       if (err < 0)
+               return err;
+
+       debug("MAC address: %pM\n", mac);
+
+       return 0;
+}
+
 static int fdtdec_init_reserved_memory(void *blob)
 {
        int na, ns, node, err;
index af17c16f616db4b8afc71cb55b31ad394457636b..9b779ddc3bbe42b6df36a70c3ece2213b40e5fa6 100644 (file)
@@ -326,6 +326,29 @@ char * strdup(const char *s)
 }
 #endif
 
+char * strndup(const char *s, size_t n)
+{
+       size_t len;
+       char *new;
+
+       if (s == NULL)
+               return NULL;
+
+       len = strlen(s);
+
+       if (n < len)
+               len = n;
+
+       new = malloc(len + 1);
+       if (new == NULL)
+               return NULL;
+
+       strncpy(new, s, len);
+       new[len] = '\0';
+
+       return new;
+}
+
 #ifndef __HAVE_ARCH_STRSPN
 /**
  * strspn - Calculate the length of the initial substring of @s which only