summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/dts/Makefile4
-rw-r--r--arch/arm/dts/dragonboard410c.dts22
-rw-r--r--arch/arm/dts/dragonboard820c-uboot.dtsi19
-rw-r--r--arch/arm/dts/dragonboard820c.dts108
-rw-r--r--arch/arm/dts/imx6sx-sdb.dts138
-rw-r--r--arch/arm/dts/imx6sx-sdb.dtsi612
-rw-r--r--arch/arm/dts/imx6ull-14x14-evk.dts5
-rw-r--r--arch/arm/dts/imx6ull.dtsi9
-rw-r--r--arch/arm/include/asm/mach-imx/hab.h46
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/hab.c461
-rw-r--r--arch/arm/mach-imx/imx_bootaux.c13
-rw-r--r--arch/arm/mach-imx/mx5/clock.c4
-rw-r--r--arch/arm/mach-imx/mx6/Kconfig6
-rw-r--r--arch/arm/mach-imx/mx6/ddr.c4
-rw-r--r--arch/arm/mach-imx/mx7/clock.c2
-rw-r--r--arch/arm/mach-imx/mx7ulp/clock.c2
-rw-r--r--arch/arm/mach-imx/spl.c45
-rw-r--r--arch/arm/mach-snapdragon/Kconfig10
-rw-r--r--arch/arm/mach-snapdragon/Makefile7
-rw-r--r--arch/arm/mach-snapdragon/clock-apq8016.c181
-rw-r--r--arch/arm/mach-snapdragon/clock-apq8096.c62
-rw-r--r--arch/arm/mach-snapdragon/clock-snapdragon.c134
-rw-r--r--arch/arm/mach-snapdragon/clock-snapdragon.h40
-rw-r--r--arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h29
-rw-r--r--arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h29
-rw-r--r--arch/arm/mach-snapdragon/sysmap-apq8096.c32
-rw-r--r--arch/sandbox/dts/test.dts7
28 files changed, 1642 insertions, 391 deletions
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index bbc4f476d0..e22b52cbb6 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -211,7 +211,8 @@ dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds-duart.dtb \
fsl-ls1012a-rdb.dtb \
fsl-ls1012a-frdm.dtb
-dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb
+dtb-$(CONFIG_TARGET_DRAGONBOARD410C) += dragonboard410c.dtb
+dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb
dtb-$(CONFIG_STM32F4) += stm32f429-disco.dtb \
stm32f469-disco.dtb
@@ -384,6 +385,7 @@ dtb-$(CONFIG_MX6) += imx6ull-14x14-evk.dtb \
imx6q-icore-rqs.dtb \
imx6q-logicpd.dtb \
imx6sx-sabreauto.dtb \
+ imx6sx-sdb.dtb \
imx6ul-geam-kit.dtb \
imx6ul-isiot-emmc.dtb \
imx6ul-isiot-mmc.dtb \
diff --git a/arch/arm/dts/dragonboard410c.dts b/arch/arm/dts/dragonboard410c.dts
index 7746622dda..5ccfe7f8c8 100644
--- a/arch/arm/dts/dragonboard410c.dts
+++ b/arch/arm/dts/dragonboard410c.dts
@@ -23,11 +23,16 @@
reg = <0 0x80000000 0 0x3da00000>;
};
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ };
+
chosen {
stdout-path = "/soc/serial@78b0000";
};
-
soc {
#address-cells = <0x1>;
#size-cells = <0x1>;
@@ -48,11 +53,6 @@
clock = <&clkc 4>;
};
- restart@4ab000 {
- compatible = "qcom,pshold";
- reg = <0x4ab000 0x4>;
- };
-
soc_gpios: pinctrl@1000000 {
compatible = "qcom,apq8016-pinctrl";
reg = <0x1000000 0x300000>;
@@ -86,6 +86,16 @@
clock-frequency = <200000000>;
};
+ wcnss {
+ bt {
+ compatible="qcom,wcnss-bt";
+ };
+
+ wifi {
+ compatible="qcom,wcnss-wlan";
+ };
+ };
+
spmi@200f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x200f800 0x200 0x2400000 0x400000 0x2c00000 0x400000>;
diff --git a/arch/arm/dts/dragonboard820c-uboot.dtsi b/arch/arm/dts/dragonboard820c-uboot.dtsi
new file mode 100644
index 0000000000..167e72c0ae
--- /dev/null
+++ b/arch/arm/dts/dragonboard820c-uboot.dtsi
@@ -0,0 +1,19 @@
+/*
+ * U-Boot addition to handle Dragonboard 820c pins
+ *
+ * (C) Copyright 2017 Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+&pm8994_pon {
+ key_vol_down {
+ gpios = <&pm8994_pon 1 0>;
+ label = "key_vol_down";
+ };
+
+ key_power {
+ gpios = <&pm8994_pon 0 0>;
+ label = "key_power";
+ };
+};
diff --git a/arch/arm/dts/dragonboard820c.dts b/arch/arm/dts/dragonboard820c.dts
new file mode 100644
index 0000000000..64249449af
--- /dev/null
+++ b/arch/arm/dts/dragonboard820c.dts
@@ -0,0 +1,108 @@
+/*
+ * Qualcomm APQ8096 based Dragonboard 820C board device tree source
+ *
+ * (C) Copyright 2017 Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/dts-v1/;
+
+#include "skeleton64.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. DB820c";
+ compatible = "arrow,apq8096-db820c", "qcom,apq8096-sbc";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases {
+ serial0 = &blsp2_uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0 0x80000000 0 0xc0000000>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ soc: soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ gcc: clock-controller@300000 {
+ compatible = "qcom,gcc-msm8996";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ reg = <0x300000 0x90000>;
+ };
+
+ blsp2_uart1: serial@75b0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x75b0000 0x1000>;
+ };
+
+ sdhc2: sdhci@74a4900 {
+ compatible = "qcom,sdhci-msm-v4";
+ reg = <0x74a4900 0x314>, <0x74a4000 0x800>;
+ index = <0x0>;
+ bus-width = <4>;
+ clock = <&gcc 0>;
+ clock-frequency = <200000000>;
+ };
+
+ spmi@400f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x400f800 0x200>,
+ <0x4400000 0x400000>,
+ <0x4c00000 0x400000>;
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+
+ pmic0: pm8994@0 {
+ compatible = "qcom,spmi-pmic";
+ reg = <0x0 0x1>;
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+
+ pm8994_pon: pm8994_pon@800 {
+ compatible = "qcom,pm8994-pwrkey";
+ reg = <0x800 0x96>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-bank-name="pm8994_key.";
+ };
+
+ pm8994_gpios: pm8994_gpios@c000 {
+ compatible = "qcom,pm8994-gpio";
+ reg = <0xc000 0x400>;
+ gpio-controller;
+ gpio-count = <24>;
+ #gpio-cells = <2>;
+ gpio-bank-name="pm8994.";
+ };
+ };
+
+ pmic1: pm8994@1 {
+ compatible = "qcom,spmi-pmic";
+ reg = <0x1 0x1>;
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ };
+ };
+ };
+
+};
+
+#include "dragonboard820c-uboot.dtsi"
diff --git a/arch/arm/dts/imx6sx-sdb.dts b/arch/arm/dts/imx6sx-sdb.dts
new file mode 100644
index 0000000000..6dd9bebfe0
--- /dev/null
+++ b/arch/arm/dts/imx6sx-sdb.dts
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "imx6sx-sdb.dtsi"
+
+/ {
+ model = "Freescale i.MX6 SoloX SDB RevB Board";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ pmic: pfuze100@8 {
+ compatible = "fsl,pfuze200";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&qspi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi2>;
+ status = "okay";
+
+ flash0: n25q256a@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a", "jedec,spi-nor";
+ spi-max-frequency = <29000000>;
+ reg = <0>;
+ };
+
+ flash1: n25q256a@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "micron,n25q256a", "jedec,spi-nor";
+ spi-max-frequency = <29000000>;
+ reg = <1>;
+ };
+};
+
+&reg_arm {
+ vin-supply = <&sw1a_reg>;
+};
+
+&reg_soc {
+ vin-supply = <&sw1a_reg>;
+};
diff --git a/arch/arm/dts/imx6sx-sdb.dtsi b/arch/arm/dts/imx6sx-sdb.dtsi
new file mode 100644
index 0000000000..da815527a7
--- /dev/null
+++ b/arch/arm/dts/imx6sx-sdb.dtsi
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sx.dtsi"
+
+/ {
+ model = "Freescale i.MX6 SoloX SDB Board";
+ compatible = "fsl,imx6sx-sdb", "fsl,imx6sx";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm3 0 5000000>;
+ brightness-levels = <0 4 8 16 32 64 128 255>;
+ default-brightness-level = <6>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ vcc_sd3: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_sd3>;
+ regulator-name = "VCC_SD3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg1_vbus: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1>;
+ regulator-name = "usb_otg1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usb_otg2_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg2>;
+ regulator-name = "usb_otg2_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_psu_5v: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "PSU-5V0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_lcd_3v3: regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <4>;
+ regulator-name = "lcd-3v3";
+ gpio = <&gpio3 27 0>;
+ enable-active-high;
+ };
+
+ reg_peri_3v3: regulator@5 {
+ compatible = "regulator-fixed";
+ reg = <5>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_peri_3v3>;
+ regulator-name = "peri_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ reg_enet_3v3: regulator@6 {
+ compatible = "regulator-fixed";
+ reg = <6>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_3v3>;
+ regulator-name = "enet_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ sound {
+ compatible = "fsl,imx6sx-sdb-wm8962", "fsl,imx-audio-wm8962";
+ model = "wm8962-audio";
+ ssi-controller = <&ssi2>;
+ audio-codec = <&codec>;
+ audio-routing =
+ "Headphone Jack", "HPOUTL",
+ "Headphone Jack", "HPOUTR",
+ "Ext Spk", "SPKOUTL",
+ "Ext Spk", "SPKOUTR",
+ "AMIC", "MICBIAS",
+ "IN3R", "AMIC";
+ mux-int-port = <2>;
+ mux-ext-port = <6>;
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-supply = <&reg_enet_3v3>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy1>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+
+ ethphy2: ethernet-phy@2 {
+ reg = <2>;
+ };
+ };
+};
+
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy2>;
+ status = "okay";
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ codec: wm8962@1a {
+ compatible = "wlf,wm8962";
+ reg = <0x1a>;
+ clocks = <&clks IMX6SX_CLK_AUDIO>;
+ DCVDD-supply = <&vgen4_reg>;
+ DBVDD-supply = <&vgen4_reg>;
+ AVDD-supply = <&vgen4_reg>;
+ CPVDD-supply = <&vgen4_reg>;
+ MICVDD-supply = <&vgen3_reg>;
+ PLLVDD-supply = <&vgen4_reg>;
+ SPKVDD1-supply = <&reg_psu_5v>;
+ SPKVDD2-supply = <&reg_psu_5v>;
+ };
+};
+
+&lcdif1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lcd>;
+ lcd-supply = <&reg_lcd_3v3>;
+ display = <&display0>;
+ status = "okay";
+
+ display0: display0 {
+ bits-per-pixel = <16>;
+ bus-width = <24>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: timing0 {
+ clock-frequency = <33500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <89>;
+ hfront-porch = <164>;
+ vback-porch = <23>;
+ vfront-porch = <10>;
+ hsync-len = <10>;
+ vsync-len = <10>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <0>;
+ };
+ };
+ };
+};
+
+&pwm3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm3>;
+ status = "okay";
+};
+
+&snvs_poweroff {
+ status = "okay";
+};
+
+&sai1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sai1>;
+ status = "disabled";
+};
+
+&ssi2 {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart5 { /* for bluetooth */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbotg1 {
+ vbus-supply = <&reg_usb_otg1_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_otg1_id>;
+ status = "okay";
+};
+
+&usbotg2 {
+ vbus-supply = <&reg_usb_otg2_vbus>;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbphy1 {
+ fsl,tx-d-cal = <106>;
+};
+
+&usbphy2 {
+ fsl,tx-d-cal = <106>;
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ non-removable;
+ no-1-8-v;
+ keep-power-in-suspend;
+ wakeup-source;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ bus-width = <8>;
+ cd-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ wakeup-source;
+ vmmc-supply = <&vcc_sd3>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ cd-gpios = <&gpio6 21 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+};
+
+&iomuxc {
+ imx6x-sdb {
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__AUDMUX_AUD6_TXC 0x130b0
+ MX6SX_PAD_CSI_DATA01__AUDMUX_AUD6_TXFS 0x130b0
+ MX6SX_PAD_CSI_HSYNC__AUDMUX_AUD6_TXD 0x120b0
+ MX6SX_PAD_CSI_VSYNC__AUDMUX_AUD6_RXD 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
+
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 0xa0b1
+ MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b1
+ MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M 0x91
+ >;
+ };
+
+ pinctrl_enet_3v3: enet3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET2_COL__GPIO2_IO_6 0x80000000
+ >;
+ };
+
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA04__GPIO1_IO_18 0x17059
+ MX6SX_PAD_CSI_DATA05__GPIO1_IO_19 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO01__I2C1_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO00__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA07__I2C4_SDA 0x4001b8b1
+ MX6SX_PAD_CSI_DATA06__I2C4_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_lcd: lcdgrp {
+ fsl,pins = <
+ MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22 0x4001b0b0
+ MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23 0x4001b0b0
+ MX6SX_PAD_LCD1_CLK__LCDIF1_CLK 0x4001b0b0
+ MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE 0x4001b0b0
+ MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC 0x4001b0b0
+ MX6SX_PAD_LCD1_RESET__GPIO3_IO_27 0x4001b0b0
+ >;
+ };
+
+ pinctrl_peri_3v3: peri3v3grp {
+ fsl,pins = <
+ MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16 0x80000000
+ >;
+ };
+
+ pinctrl_pwm3: pwm3grp-1 {
+ fsl,pins = <
+ MX6SX_PAD_SD1_DATA2__PWM3_OUT 0x110b0
+ >;
+ };
+
+ pinctrl_qspi2: qspi2grp {
+ fsl,pins = <
+ MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1
+ MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70f1
+ MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70f1
+ MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70f1
+ MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70f1
+ MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70f1
+ MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70f1
+ MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70f1
+ MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70f1
+ MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70f1
+ MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70f1
+ MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70f1
+ >;
+ };
+
+ pinctrl_vcc_sd3: vccsd3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
+ >;
+ };
+
+ pinctrl_sai1: sai1grp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK 0x130b0
+ MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC 0x130b0
+ MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0 0x120b0
+ MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0 0x130b0
+ MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK 0x130b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW3__UART5_RX 0x1b0b1
+ MX6SX_PAD_KEY_COL3__UART5_TX 0x1b0b1
+ MX6SX_PAD_KEY_ROW2__UART5_CTS_B 0x1b0b1
+ MX6SX_PAD_KEY_COL2__UART5_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_usb_otg1: usbotg1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9 0x10b0
+ >;
+ };
+
+ pinctrl_usb_otg1_id: usbotg1idgrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usb_otg2: usbot2ggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO12__GPIO1_IO_12 0x10b0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SX_PAD_SD2_CMD__USDHC2_CMD 0x17059
+ MX6SX_PAD_SD2_CLK__USDHC2_CLK 0x10059
+ MX6SX_PAD_SD2_DATA0__USDHC2_DATA0 0x17059
+ MX6SX_PAD_SD2_DATA1__USDHC2_DATA1 0x17059
+ MX6SX_PAD_SD2_DATA2__USDHC2_DATA2 0x17059
+ MX6SX_PAD_SD2_DATA3__USDHC2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
+ MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */
+ MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+ };
+};
diff --git a/arch/arm/dts/imx6ull-14x14-evk.dts b/arch/arm/dts/imx6ull-14x14-evk.dts
index 375bd4ea31..2a941bff1c 100644
--- a/arch/arm/dts/imx6ull-14x14-evk.dts
+++ b/arch/arm/dts/imx6ull-14x14-evk.dts
@@ -67,7 +67,7 @@
};
};
- spi4 {
+ spi5 {
compatible = "spi-gpio";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_spi4>;
@@ -455,7 +455,8 @@
flash0: n25q256a@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "micron,n25q256a";
+ /* compatible = "micron,n25q256a"; */
+ compatible = "spi-flash";
spi-max-frequency = <29000000>;
spi-nor,ddr-quad-read-dummy = <6>;
reg = <0>;
diff --git a/arch/arm/dts/imx6ull.dtsi b/arch/arm/dts/imx6ull.dtsi
index 65950e8019..ea882a7f14 100644
--- a/arch/arm/dts/imx6ull.dtsi
+++ b/arch/arm/dts/imx6ull.dtsi
@@ -38,10 +38,11 @@
serial5 = &uart6;
serial6 = &uart7;
serial7 = &uart8;
- spi0 = &ecspi1;
- spi1 = &ecspi2;
- spi2 = &ecspi3;
- spi3 = &ecspi4;
+ spi0 = &qspi;
+ spi1 = &ecspi1;
+ spi2 = &ecspi2;
+ spi3 = &ecspi3;
+ spi4 = &ecspi4;
usbphy0 = &usbphy1;
usbphy1 = &usbphy2;
};
diff --git a/arch/arm/include/asm/mach-imx/hab.h b/arch/arm/include/asm/mach-imx/hab.h
index e0ff459d53..a0cb19db2f 100644
--- a/arch/arm/include/asm/mach-imx/hab.h
+++ b/arch/arm/include/asm/mach-imx/hab.h
@@ -10,6 +10,34 @@
#include <linux/types.h>
+/*
+ * IVT header definitions
+ * Security Reference Manual for i.MX 7Dual and 7Solo Applications Processors,
+ * Rev. 0, 03/2017
+ * Section : 6.7.1.1
+ */
+#define IVT_HEADER_MAGIC 0xD1
+#define IVT_TOTAL_LENGTH 0x20
+#define IVT_HEADER_V1 0x40
+#define IVT_HEADER_V2 0x41
+
+struct ivt_header {
+ uint8_t magic;
+ uint16_t length;
+ uint8_t version;
+} __attribute__((packed));
+
+struct ivt {
+ struct ivt_header hdr; /* IVT header above */
+ uint32_t entry; /* Absolute address of first instruction */
+ uint32_t reserved1; /* Reserved should be zero */
+ uint32_t dcd; /* Absolute address of the image DCD */
+ uint32_t boot; /* Absolute address of the boot data */
+ uint32_t self; /* Absolute address of the IVT */
+ uint32_t csf; /* Absolute address of the CSF */
+ uint32_t reserved2; /* Reserved should be zero */
+};
+
/* -------- start of HAB API updates ------------*/
/* The following are taken from HAB4 SIS */
@@ -85,6 +113,12 @@ enum hab_context {
HAB_CTX_MAX
};
+enum hab_target {
+ HAB_TGT_MEMORY = 0x0f,
+ HAB_TGT_PERIPHERAL = 0xf0,
+ HAB_TGT_ANY = 0x55,
+};
+
struct imx_sec_config_fuse_t {
int bank;
int word;
@@ -104,6 +138,9 @@ typedef enum hab_status hab_rvt_entry_t(void);
typedef enum hab_status hab_rvt_exit_t(void);
typedef void *hab_rvt_authenticate_image_t(uint8_t, ptrdiff_t,
void **, size_t *, hab_loader_callback_f_t);
+typedef enum hab_status hab_rvt_check_target_t(enum hab_target, const void *,
+ size_t);
+typedef void hab_rvt_failsafe_t(void);
typedef void hapi_clock_init_t(void);
#define HAB_ENG_ANY 0x00 /* Select first compatible engine */
@@ -130,9 +167,11 @@ typedef void hapi_clock_init_t(void);
#define HAB_RVT_ENTRY (*(uint32_t *)(HAB_RVT_BASE + 0x04))
#define HAB_RVT_EXIT (*(uint32_t *)(HAB_RVT_BASE + 0x08))
+#define HAB_RVT_CHECK_TARGET (*(uint32_t *)(HAB_RVT_BASE + 0x0C))
#define HAB_RVT_AUTHENTICATE_IMAGE (*(uint32_t *)(HAB_RVT_BASE + 0x10))
#define HAB_RVT_REPORT_EVENT (*(uint32_t *)(HAB_RVT_BASE + 0x20))
#define HAB_RVT_REPORT_STATUS (*(uint32_t *)(HAB_RVT_BASE + 0x24))
+#define HAB_RVT_FAILSAFE (*(uint32_t *)(HAB_RVT_BASE + 0x28))
#define HAB_RVT_REPORT_EVENT_NEW (*(uint32_t *)0x000000B8)
#define HAB_RVT_REPORT_STATUS_NEW (*(uint32_t *)0x000000BC)
@@ -143,8 +182,13 @@ typedef void hapi_clock_init_t(void);
#define HAB_CID_ROM 0 /**< ROM Caller ID */
#define HAB_CID_UBOOT 1 /**< UBOOT Caller ID*/
+#define IVT_SIZE 0x20
+#define CSF_PAD_SIZE 0x2000
+
/* ----------- end of HAB API updates ------------*/
-uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size);
+int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
+ uint32_t ivt_offset);
+bool imx_hab_is_enabled(void);
#endif
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index d7966cfd4a..cf39d08bdd 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -28,7 +28,9 @@ obj-y += cache.o init.o
obj-$(CONFIG_SATA) += sata.o
obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
obj-$(CONFIG_IMX_RDC) += rdc-sema.o
+ifneq ($(CONFIG_SPL_BUILD),y)
obj-$(CONFIG_IMX_BOOTAUX) += imx_bootaux.o
+endif
obj-$(CONFIG_SECURE_BOOT) += hab.o
obj-$(CONFIG_SYSCOUNTER_TIMER) += syscounter.o
endif
diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c
index 02c7ae4e72..5f197775c1 100644
--- a/arch/arm/mach-imx/hab.c
+++ b/arch/arm/mach-imx/hab.c
@@ -70,9 +70,40 @@
((hab_rvt_exit_t *)HAB_RVT_EXIT) \
)
-#define IVT_SIZE 0x20
+static inline void hab_rvt_failsafe_new(void)
+{
+}
+
+#define hab_rvt_failsafe_p \
+( \
+ (is_mx6dqp()) ? \
+ ((hab_rvt_failsafe_t *)hab_rvt_failsafe_new) : \
+ (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
+ ((hab_rvt_failsafe_t *)hab_rvt_failsafe_new) : \
+ (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
+ ((hab_rvt_failsafe_t *)hab_rvt_failsafe_new) : \
+ ((hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE) \
+)
+
+static inline enum hab_status hab_rvt_check_target_new(enum hab_target target,
+ const void *start,
+ size_t bytes)
+{
+ return HAB_SUCCESS;
+}
+
+#define hab_rvt_check_target_p \
+( \
+ (is_mx6dqp()) ? \
+ ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \
+ (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
+ ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \
+ (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
+ ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \
+ ((hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET) \
+)
+
#define ALIGN_SIZE 0x1000
-#define CSF_PAD_SIZE 0x2000
#define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
#define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0
#define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18
@@ -80,38 +111,30 @@
(is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \
(is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2))
-/*
- * +------------+ 0x0 (DDR_UIMAGE_START) -
- * | Header | |
- * +------------+ 0x40 |
- * | | |
- * | | |
- * | | |
- * | | |
- * | Image Data | |
- * . | |
- * . | > Stuff to be authenticated ----+
- * . | | |
- * | | | |
- * | | | |
- * +------------+ | |
- * | | | |
- * | Fill Data | | |
- * | | | |
- * +------------+ Align to ALIGN_SIZE | |
- * | IVT | | |
- * +------------+ + IVT_SIZE - |
- * | | |
- * | CSF DATA | <---------------------------------------------------------+
- * | |
- * +------------+
- * | |
- * | Fill Data |
- * | |
- * +------------+ + CSF_PAD_SIZE
- */
+static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
+{
+ printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str,
+ ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version);
-static bool is_hab_enabled(void);
+ return 1;
+}
+
+static int verify_ivt_header(struct ivt_header *ivt_hdr)
+{
+ int result = 0;
+
+ if (ivt_hdr->magic != IVT_HEADER_MAGIC)
+ result = ivt_header_error("bad magic", ivt_hdr);
+
+ if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
+ result = ivt_header_error("bad length", ivt_hdr);
+
+ if (ivt_hdr->version != IVT_HEADER_V1 &&
+ ivt_hdr->version != IVT_HEADER_V2)
+ result = ivt_header_error("bad version", ivt_hdr);
+
+ return result;
+}
#if !defined(CONFIG_SPL_BUILD)
@@ -125,73 +148,81 @@ struct record {
bool any_rec_flag;
};
-char *rsn_str[] = {"RSN = HAB_RSN_ANY (0x00)\n",
- "RSN = HAB_ENG_FAIL (0x30)\n",
- "RSN = HAB_INV_ADDRESS (0x22)\n",
- "RSN = HAB_INV_ASSERTION (0x0C)\n",
- "RSN = HAB_INV_CALL (0x28)\n",
- "RSN = HAB_INV_CERTIFICATE (0x21)\n",
- "RSN = HAB_INV_COMMAND (0x06)\n",
- "RSN = HAB_INV_CSF (0x11)\n",
- "RSN = HAB_INV_DCD (0x27)\n",
- "RSN = HAB_INV_INDEX (0x0F)\n",
- "RSN = HAB_INV_IVT (0x05)\n",
- "RSN = HAB_INV_KEY (0x1D)\n",
- "RSN = HAB_INV_RETURN (0x1E)\n",
- "RSN = HAB_INV_SIGNATURE (0x18)\n",
- "RSN = HAB_INV_SIZE (0x17)\n",
- "RSN = HAB_MEM_FAIL (0x2E)\n",
- "RSN = HAB_OVR_COUNT (0x2B)\n",
- "RSN = HAB_OVR_STORAGE (0x2D)\n",
- "RSN = HAB_UNS_ALGORITHM (0x12)\n",
- "RSN = HAB_UNS_COMMAND (0x03)\n",
- "RSN = HAB_UNS_ENGINE (0x0A)\n",
- "RSN = HAB_UNS_ITEM (0x24)\n",
- "RSN = HAB_UNS_KEY (0x1B)\n",
- "RSN = HAB_UNS_PROTOCOL (0x14)\n",
- "RSN = HAB_UNS_STATE (0x09)\n",
- "RSN = INVALID\n",
- NULL};
-
-char *sts_str[] = {"STS = HAB_SUCCESS (0xF0)\n",
- "STS = HAB_FAILURE (0x33)\n",
- "STS = HAB_WARNING (0x69)\n",
- "STS = INVALID\n",
- NULL};
-
-char *eng_str[] = {"ENG = HAB_ENG_ANY (0x00)\n",
- "ENG = HAB_ENG_SCC (0x03)\n",
- "ENG = HAB_ENG_RTIC (0x05)\n",
- "ENG = HAB_ENG_SAHARA (0x06)\n",
- "ENG = HAB_ENG_CSU (0x0A)\n",
- "ENG = HAB_ENG_SRTC (0x0C)\n",
- "ENG = HAB_ENG_DCP (0x1B)\n",
- "ENG = HAB_ENG_CAAM (0x1D)\n",
- "ENG = HAB_ENG_SNVS (0x1E)\n",
- "ENG = HAB_ENG_OCOTP (0x21)\n",
- "ENG = HAB_ENG_DTCP (0x22)\n",
- "ENG = HAB_ENG_ROM (0x36)\n",
- "ENG = HAB_ENG_HDCP (0x24)\n",
- "ENG = HAB_ENG_RTL (0x77)\n",
- "ENG = HAB_ENG_SW (0xFF)\n",
- "ENG = INVALID\n",
- NULL};
-
-char *ctx_str[] = {"CTX = HAB_CTX_ANY(0x00)\n",
- "CTX = HAB_CTX_FAB (0xFF)\n",
- "CTX = HAB_CTX_ENTRY (0xE1)\n",
- "CTX = HAB_CTX_TARGET (0x33)\n",
- "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
- "CTX = HAB_CTX_DCD (0xDD)\n",
- "CTX = HAB_CTX_CSF (0xCF)\n",
- "CTX = HAB_CTX_COMMAND (0xC0)\n",
- "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
- "CTX = HAB_CTX_ASSERT (0xA0)\n",
- "CTX = HAB_CTX_EXIT (0xEE)\n",
- "CTX = INVALID\n",
- NULL};
-
-uint8_t hab_statuses[5] = {
+static char *rsn_str[] = {
+ "RSN = HAB_RSN_ANY (0x00)\n",
+ "RSN = HAB_ENG_FAIL (0x30)\n",
+ "RSN = HAB_INV_ADDRESS (0x22)\n",
+ "RSN = HAB_INV_ASSERTION (0x0C)\n",
+ "RSN = HAB_INV_CALL (0x28)\n",
+ "RSN = HAB_INV_CERTIFICATE (0x21)\n",
+ "RSN = HAB_INV_COMMAND (0x06)\n",
+ "RSN = HAB_INV_CSF (0x11)\n",
+ "RSN = HAB_INV_DCD (0x27)\n",
+ "RSN = HAB_INV_INDEX (0x0F)\n",
+ "RSN = HAB_INV_IVT (0x05)\n",
+ "RSN = HAB_INV_KEY (0x1D)\n",
+ "RSN = HAB_INV_RETURN (0x1E)\n",
+ "RSN = HAB_INV_SIGNATURE (0x18)\n",
+ "RSN = HAB_INV_SIZE (0x17)\n",
+ "RSN = HAB_MEM_FAIL (0x2E)\n",
+ "RSN = HAB_OVR_COUNT (0x2B)\n",
+ "RSN = HAB_OVR_STORAGE (0x2D)\n",
+ "RSN = HAB_UNS_ALGORITHM (0x12)\n",
+ "RSN = HAB_UNS_COMMAND (0x03)\n",
+ "RSN = HAB_UNS_ENGINE (0x0A)\n",
+ "RSN = HAB_UNS_ITEM (0x24)\n",
+ "RSN = HAB_UNS_KEY (0x1B)\n",
+ "RSN = HAB_UNS_PROTOCOL (0x14)\n",
+ "RSN = HAB_UNS_STATE (0x09)\n",
+ "RSN = INVALID\n",
+ NULL
+};
+
+static char *sts_str[] = {
+ "STS = HAB_SUCCESS (0xF0)\n",
+ "STS = HAB_FAILURE (0x33)\n",
+ "STS = HAB_WARNING (0x69)\n",
+ "STS = INVALID\n",
+ NULL
+};
+
+static char *eng_str[] = {
+ "ENG = HAB_ENG_ANY (0x00)\n",
+ "ENG = HAB_ENG_SCC (0x03)\n",
+ "ENG = HAB_ENG_RTIC (0x05)\n",
+ "ENG = HAB_ENG_SAHARA (0x06)\n",
+ "ENG = HAB_ENG_CSU (0x0A)\n",
+ "ENG = HAB_ENG_SRTC (0x0C)\n",
+ "ENG = HAB_ENG_DCP (0x1B)\n",
+ "ENG = HAB_ENG_CAAM (0x1D)\n",
+ "ENG = HAB_ENG_SNVS (0x1E)\n",
+ "ENG = HAB_ENG_OCOTP (0x21)\n",
+ "ENG = HAB_ENG_DTCP (0x22)\n",
+ "ENG = HAB_ENG_ROM (0x36)\n",
+ "ENG = HAB_ENG_HDCP (0x24)\n",
+ "ENG = HAB_ENG_RTL (0x77)\n",
+ "ENG = HAB_ENG_SW (0xFF)\n",
+ "ENG = INVALID\n",
+ NULL
+};
+
+static char *ctx_str[] = {
+ "CTX = HAB_CTX_ANY(0x00)\n",
+ "CTX = HAB_CTX_FAB (0xFF)\n",
+ "CTX = HAB_CTX_ENTRY (0xE1)\n",
+ "CTX = HAB_CTX_TARGET (0x33)\n",
+ "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
+ "CTX = HAB_CTX_DCD (0xDD)\n",
+ "CTX = HAB_CTX_CSF (0xCF)\n",
+ "CTX = HAB_CTX_COMMAND (0xC0)\n",
+ "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
+ "CTX = HAB_CTX_ASSERT (0xA0)\n",
+ "CTX = HAB_CTX_EXIT (0xEE)\n",
+ "CTX = INVALID\n",
+ NULL
+};
+
+static uint8_t hab_statuses[5] = {
HAB_STS_ANY,
HAB_FAILURE,
HAB_WARNING,
@@ -199,7 +230,7 @@ uint8_t hab_statuses[5] = {
-1
};
-uint8_t hab_reasons[26] = {
+static uint8_t hab_reasons[26] = {
HAB_RSN_ANY,
HAB_ENG_FAIL,
HAB_INV_ADDRESS,
@@ -228,7 +259,7 @@ uint8_t hab_reasons[26] = {
-1
};
-uint8_t hab_contexts[12] = {
+static uint8_t hab_contexts[12] = {
HAB_CTX_ANY,
HAB_CTX_FAB,
HAB_CTX_ENTRY,
@@ -243,7 +274,7 @@ uint8_t hab_contexts[12] = {
-1
};
-uint8_t hab_engines[16] = {
+static uint8_t hab_engines[16] = {
HAB_ENG_ANY,
HAB_ENG_SCC,
HAB_ENG_RTIC,
@@ -274,7 +305,7 @@ static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
return -1;
}
-void process_event_record(uint8_t *event_data, size_t bytes)
+static void process_event_record(uint8_t *event_data, size_t bytes)
{
struct record *rec = (struct record *)event_data;
@@ -284,7 +315,7 @@ void process_event_record(uint8_t *event_data, size_t bytes)
printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
}
-void display_event(uint8_t *event_data, size_t bytes)
+static void display_event(uint8_t *event_data, size_t bytes)
{
uint32_t i;
@@ -303,7 +334,7 @@ void display_event(uint8_t *event_data, size_t bytes)
process_event_record(event_data, bytes);
}
-int get_hab_status(void)
+static int get_hab_status(void)
{
uint32_t index = 0; /* Loop index */
uint8_t event_data[128]; /* Event data buffer */
@@ -316,7 +347,7 @@ int get_hab_status(void)
hab_rvt_report_event = hab_rvt_report_event_p;
hab_rvt_report_status = hab_rvt_report_status_p;
- if (is_hab_enabled())
+ if (imx_hab_is_enabled())
puts("\nSecure boot enabled\n");
else
puts("\nSecure boot disabled\n");
@@ -348,7 +379,8 @@ int get_hab_status(void)
return 0;
}
-int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
{
if ((argc != 1)) {
cmd_usage(cmdtp);
@@ -361,22 +393,43 @@ int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
- char * const argv[])
+ char * const argv[])
{
- ulong addr, ivt_offset;
+ ulong addr, length, ivt_offset;
int rcode = 0;
- if (argc < 3)
+ if (argc < 4)
return CMD_RET_USAGE;
addr = simple_strtoul(argv[1], NULL, 16);
- ivt_offset = simple_strtoul(argv[2], NULL, 16);
+ length = simple_strtoul(argv[2], NULL, 16);
+ ivt_offset = simple_strtoul(argv[3], NULL, 16);
- rcode = authenticate_image(addr, ivt_offset);
+ rcode = imx_hab_authenticate_image(addr, length, ivt_offset);
+ if (rcode == 0)
+ rcode = CMD_RET_SUCCESS;
+ else
+ rcode = CMD_RET_FAILURE;
return rcode;
}
+static int do_hab_failsafe(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ hab_rvt_failsafe_t *hab_rvt_failsafe;
+
+ if (argc != 1) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ hab_rvt_failsafe = hab_rvt_failsafe_p;
+ hab_rvt_failsafe();
+
+ return 0;
+}
+
U_BOOT_CMD(
hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
"display HAB status",
@@ -384,17 +437,23 @@ U_BOOT_CMD(
);
U_BOOT_CMD(
- hab_auth_img, 3, 0, do_authenticate_image,
+ hab_auth_img, 4, 0, do_authenticate_image,
"authenticate image via HAB",
- "addr ivt_offset\n"
+ "addr length ivt_offset\n"
"addr - image hex address\n"
+ "length - image hex length\n"
"ivt_offset - hex offset of IVT in the image"
);
+U_BOOT_CMD(
+ hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
+ "run BootROM failsafe routine",
+ ""
+ );
#endif /* !defined(CONFIG_SPL_BUILD) */
-static bool is_hab_enabled(void)
+bool imx_hab_is_enabled(void)
{
struct imx_sec_config_fuse_t *fuse =
(struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
@@ -410,107 +469,133 @@ static bool is_hab_enabled(void)
return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
}
-uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
+int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
+ uint32_t ivt_offset)
{
uint32_t load_addr = 0;
size_t bytes;
- ptrdiff_t ivt_offset = 0;
- int result = 0;
+ uint32_t ivt_addr = 0;
+ int result = 1;
ulong start;
hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
hab_rvt_entry_t *hab_rvt_entry;
hab_rvt_exit_t *hab_rvt_exit;
+ hab_rvt_check_target_t *hab_rvt_check_target;
+ struct ivt *ivt;
+ struct ivt_header *ivt_hdr;
+ enum hab_status status;
hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
hab_rvt_entry = hab_rvt_entry_p;
hab_rvt_exit = hab_rvt_exit_p;
+ hab_rvt_check_target = hab_rvt_check_target_p;
+
+ if (!imx_hab_is_enabled()) {
+ puts("hab fuse not enabled\n");
+ return 0;
+ }
+
+ printf("\nAuthenticate image from DDR location 0x%x...\n",
+ ddr_start);
- if (is_hab_enabled()) {
- printf("\nAuthenticate image from DDR location 0x%x...\n",
- ddr_start);
+ hab_caam_clock_enable(1);
- hab_caam_clock_enable(1);
+ /* Calculate IVT address header */
+ ivt_addr = ddr_start + ivt_offset;
+ ivt = (struct ivt *)ivt_addr;
+ ivt_hdr = &ivt->hdr;
- if (hab_rvt_entry() == HAB_SUCCESS) {
- /* If not already aligned, Align to ALIGN_SIZE */
- ivt_offset = (image_size + ALIGN_SIZE - 1) &
- ~(ALIGN_SIZE - 1);
+ /* Verify IVT header bugging out on error */
+ if (verify_ivt_header(ivt_hdr))
+ goto hab_caam_clock_disable;
+
+ /* Verify IVT body */
+ if (ivt->self != ivt_addr) {
+ printf("ivt->self 0x%08x pointer is 0x%08x\n",
+ ivt->self, ivt_addr);
+ goto hab_caam_clock_disable;
+ }
- start = ddr_start;
- bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
+ start = ddr_start;
+ bytes = image_size;
+
+ if (hab_rvt_entry() != HAB_SUCCESS) {
+ puts("hab entry function fail\n");
+ goto hab_exit_failure_print_status;
+ }
+
+ status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)ddr_start, bytes);
+ if (status != HAB_SUCCESS) {
+ printf("HAB check target 0x%08x-0x%08x fail\n",
+ ddr_start, ddr_start + bytes);
+ goto hab_exit_failure_print_status;
+ }
#ifdef DEBUG
- printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
- ivt_offset, ddr_start + ivt_offset);
- puts("Dumping IVT\n");
- print_buffer(ddr_start + ivt_offset,
- (void *)(ddr_start + ivt_offset),
- 4, 0x8, 0);
-
- puts("Dumping CSF Header\n");
- print_buffer(ddr_start + ivt_offset+IVT_SIZE,
- (void *)(ddr_start + ivt_offset+IVT_SIZE),
- 4, 0x10, 0);
+ printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr);
+ printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
+ ivt->dcd, ivt->csf);
+ puts("Dumping IVT\n");
+ print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0);
+
+ puts("Dumping CSF Header\n");
+ print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0);
#if !defined(CONFIG_SPL_BUILD)
- get_hab_status();
+ get_hab_status();
#endif
- puts("\nCalling authenticate_image in ROM\n");
- printf("\tivt_offset = 0x%x\n", ivt_offset);
- printf("\tstart = 0x%08lx\n", start);
- printf("\tbytes = 0x%x\n", bytes);
+ puts("\nCalling authenticate_image in ROM\n");
+ printf("\tivt_offset = 0x%x\n", ivt_offset);
+ printf("\tstart = 0x%08lx\n", start);
+ printf("\tbytes = 0x%x\n", bytes);
#endif
+ /*
+ * If the MMU is enabled, we have to notify the ROM
+ * code, or it won't flush the caches when needed.
+ * This is done, by setting the "pu_irom_mmu_enabled"
+ * word to 1. You can find its address by looking in
+ * the ROM map. This is critical for
+ * authenticate_image(). If MMU is enabled, without
+ * setting this bit, authentication will fail and may
+ * crash.
+ */
+ /* Check MMU enabled */
+ if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
+ if (is_mx6dq()) {
/*
- * If the MMU is enabled, we have to notify the ROM
- * code, or it won't flush the caches when needed.
- * This is done, by setting the "pu_irom_mmu_enabled"
- * word to 1. You can find its address by looking in
- * the ROM map. This is critical for
- * authenticate_image(). If MMU is enabled, without
- * setting this bit, authentication will fail and may
- * crash.
+ * This won't work on Rev 1.0.0 of
+ * i.MX6Q/D, since their ROM doesn't
+ * do cache flushes. don't think any
+ * exist, so we ignore them.
*/
- /* Check MMU enabled */
- if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
- if (is_mx6dq()) {
- /*
- * This won't work on Rev 1.0.0 of
- * i.MX6Q/D, since their ROM doesn't
- * do cache flushes. don't think any
- * exist, so we ignore them.
- */
- if (!is_mx6dqp())
- writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
- } else if (is_mx6sdl()) {
- writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
- } else if (is_mx6sl()) {
- writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
- }
- }
-
- load_addr = (uint32_t)hab_rvt_authenticate_image(
- HAB_CID_UBOOT,
- ivt_offset, (void **)&start,
- (size_t *)&bytes, NULL);
- if (hab_rvt_exit() != HAB_SUCCESS) {
- puts("hab exit function fail\n");
- load_addr = 0;
- }
- } else {
- puts("hab entry function fail\n");
+ if (!is_mx6dqp())
+ writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
+ } else if (is_mx6sdl()) {
+ writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
+ } else if (is_mx6sl()) {
+ writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
}
+ }
- hab_caam_clock_enable(0);
+ load_addr = (uint32_t)hab_rvt_authenticate_image(
+ HAB_CID_UBOOT,
+ ivt_offset, (void **)&start,
+ (size_t *)&bytes, NULL);
+ if (hab_rvt_exit() != HAB_SUCCESS) {
+ puts("hab exit function fail\n");
+ load_addr = 0;
+ }
+hab_exit_failure_print_status:
#if !defined(CONFIG_SPL_BUILD)
- get_hab_status();
+ get_hab_status();
#endif
- } else {
- puts("hab fuse not enabled\n");
- }
- if ((!is_hab_enabled()) || (load_addr != 0))
- result = 1;
+hab_caam_clock_disable:
+ hab_caam_clock_enable(0);
+
+ if (load_addr != 0)
+ result = 0;
return result;
}
diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c
index 69026df763..b62dfbf6bf 100644
--- a/arch/arm/mach-imx/imx_bootaux.c
+++ b/arch/arm/mach-imx/imx_bootaux.c
@@ -6,27 +6,22 @@
#include <common.h>
#include <command.h>
+#include <linux/compiler.h>
/* Allow for arch specific config before we boot */
-static int __arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
+int __weak arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
{
/* please define platform specific arch_auxiliary_core_up() */
return CMD_RET_FAILURE;
}
-int arch_auxiliary_core_up(u32 core_id, u32 boot_private_data)
- __attribute__((weak, alias("__arch_auxiliary_core_up")));
-
/* Allow for arch specific config before we boot */
-static int __arch_auxiliary_core_check_up(u32 core_id)
+int __weak arch_auxiliary_core_check_up(u32 core_id)
{
/* please define platform specific arch_auxiliary_core_check_up() */
return 0;
}
-int arch_auxiliary_core_check_up(u32 core_id)
- __attribute__((weak, alias("__arch_auxiliary_core_check_up")));
-
/*
* To i.MX6SX and i.MX7D, the image supported by bootaux needs
* the reset vector at the head for the image, with SP and PC
@@ -40,7 +35,7 @@ int arch_auxiliary_core_check_up(u32 core_id)
* The TCMUL is mapped to (M4_BOOTROM_BASE_ADDR) at A core side for
* accessing the M4 TCMUL.
*/
-int do_bootaux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_bootaux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
ulong addr;
int ret, up;
diff --git a/arch/arm/mach-imx/mx5/clock.c b/arch/arm/mach-imx/mx5/clock.c
index 610098c175..284f6d4cde 100644
--- a/arch/arm/mach-imx/mx5/clock.c
+++ b/arch/arm/mach-imx/mx5/clock.c
@@ -911,10 +911,11 @@ void mxc_set_sata_internal_clock(void)
}
#endif
+#ifndef CONFIG_SPL_BUILD
/*
* Dump some core clockes.
*/
-int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mx5_showclocks(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
u32 freq;
@@ -947,3 +948,4 @@ U_BOOT_CMD(
"display clocks",
""
);
+#endif
diff --git a/arch/arm/mach-imx/mx6/Kconfig b/arch/arm/mach-imx/mx6/Kconfig
index 567a6a6bf5..2f3e52d624 100644
--- a/arch/arm/mach-imx/mx6/Kconfig
+++ b/arch/arm/mach-imx/mx6/Kconfig
@@ -130,6 +130,7 @@ config TARGET_CM_FX6
bool "CM-FX6"
select SUPPORT_SPL
select MX6QDL
+ select BOARD_LATE_INIT
select DM
select DM_SERIAL
select DM_GPIO
@@ -377,6 +378,10 @@ config TARGET_PFLA02
config TARGET_SECOMX6
bool "secomx6 boards"
+config TARGET_SKSIMX6
+ bool "sks-imx6"
+ select SUPPORT_SPL
+
config TARGET_TBS2910
bool "TBS2910 Matrix ARM mini PC"
@@ -482,6 +487,7 @@ source "board/liebherr/display5/Kconfig"
source "board/liebherr/mccmon6/Kconfig"
source "board/logicpd/imx6/Kconfig"
source "board/seco/Kconfig"
+source "board/sks-kinkel/sksimx6/Kconfig"
source "board/solidrun/mx6cuboxi/Kconfig"
source "board/technexion/pico-imx6ul/Kconfig"
source "board/tbs/tbs2910/Kconfig"
diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 52a9a25904..39dbd2f607 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -908,7 +908,7 @@ void mx6sdl_dram_iocfg(unsigned width,
#define MR(val, ba, cmd, cs1) \
((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
#define MMDC1(entry, value) do { \
- if (!is_mx6sx() && !is_mx6ul() && !is_mx6sl()) \
+ if (!is_mx6sx() && !is_mx6ul() && !is_mx6ull() && !is_mx6sl()) \
mmdc1->entry = value; \
} while (0)
@@ -1215,7 +1215,7 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
u16 mem_speed = ddr3_cfg->mem_speed;
mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
- if (!is_mx6sx() && !is_mx6ul() && !is_mx6sl())
+ if (!is_mx6sx() && !is_mx6ul() && !is_mx6ull() && !is_mx6sl())
mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
/* Limit mem_speed for MX6D/MX6Q */
diff --git a/arch/arm/mach-imx/mx7/clock.c b/arch/arm/mach-imx/mx7/clock.c
index 8150faa1a3..c11042d6f5 100644
--- a/arch/arm/mach-imx/mx7/clock.c
+++ b/arch/arm/mach-imx/mx7/clock.c
@@ -1096,6 +1096,7 @@ void epdc_clock_disable(void)
}
#endif
+#ifndef CONFIG_SPL_BUILD
/*
* Dump some core clockes.
*/
@@ -1131,3 +1132,4 @@ U_BOOT_CMD(
"display clocks",
""
);
+#endif
diff --git a/arch/arm/mach-imx/mx7ulp/clock.c b/arch/arm/mach-imx/mx7ulp/clock.c
index 77b282addd..553d62149d 100644
--- a/arch/arm/mach-imx/mx7ulp/clock.c
+++ b/arch/arm/mach-imx/mx7ulp/clock.c
@@ -323,6 +323,7 @@ void hab_caam_clock_enable(unsigned char enable)
}
#endif
+#ifndef CONFIG_SPL_BUILD
/*
* Dump some core clockes.
*/
@@ -363,3 +364,4 @@ U_BOOT_CMD(
"display clocks",
""
);
+#endif
diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c
index 723f51fad3..6c16872f59 100644
--- a/arch/arm/mach-imx/spl.c
+++ b/arch/arm/mach-imx/spl.c
@@ -106,10 +106,13 @@ u32 spl_boot_device(void)
switch (boot_device_spl) {
case SD1_BOOT:
case MMC1_BOOT:
- return BOOT_DEVICE_MMC1;
case SD2_BOOT:
case MMC2_BOOT:
- return BOOT_DEVICE_MMC2;
+ case SD3_BOOT:
+ case MMC3_BOOT:
+ return BOOT_DEVICE_MMC1;
+ case NAND_BOOT:
+ return BOOT_DEVICE_NAND;
case SPI_NOR_BOOT:
return BOOT_DEVICE_SPI;
default:
@@ -152,9 +155,41 @@ u32 spl_boot_mode(const u32 boot_device)
#if defined(CONFIG_SECURE_BOOT)
+/*
+ * +------------+ 0x0 (DDR_UIMAGE_START) -
+ * | Header | |
+ * +------------+ 0x40 |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | Image Data | |
+ * . | |
+ * . | > Stuff to be authenticated ----+
+ * . | | |
+ * | | | |
+ * | | | |
+ * +------------+ | |
+ * | | | |
+ * | Fill Data | | |
+ * | | | |
+ * +------------+ Align to ALIGN_SIZE | |
+ * | IVT | | |
+ * +------------+ + IVT_SIZE - |
+ * | | |
+ * | CSF DATA | <---------------------------------------------------------+
+ * | |
+ * +------------+
+ * | |
+ * | Fill Data |
+ * | |
+ * +------------+ + CSF_PAD_SIZE
+ */
+
__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
typedef void __noreturn (*image_entry_noargs_t)(void);
+ uint32_t offset;
image_entry_noargs_t image_entry =
(image_entry_noargs_t)(unsigned long)spl_image->entry_point;
@@ -163,8 +198,10 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
/* HAB looks for the CSF at the end of the authenticated data therefore,
* we need to subtract the size of the CSF from the actual filesize */
- if (authenticate_image(spl_image->load_addr,
- spl_image->size - CONFIG_CSF_SIZE)) {
+ offset = spl_image->size - CONFIG_CSF_SIZE;
+ if (!imx_hab_authenticate_image(spl_image->load_addr,
+ offset + IVT_SIZE + CSF_PAD_SIZE,
+ offset)) {
image_entry();
} else {
puts("spl: ERROR: image authentication unsuccessful\n");
diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig
index dc7ba21c18..d55dc1aaa1 100644
--- a/arch/arm/mach-snapdragon/Kconfig
+++ b/arch/arm/mach-snapdragon/Kconfig
@@ -19,8 +19,18 @@ config TARGET_DRAGONBOARD410C
- HDMI
- 20-pin low speed and 40-pin high speed expanders, 4 LED, 3 buttons
+config TARGET_DRAGONBOARD820C
+ bool "96Boards Dragonboard 820C"
+ help
+ Support for 96Boards Dragonboard 820C. This board complies with
+ 96Board Open Platform Specifications. Features:
+ - Qualcomm Snapdragon 820C SoC - APQ8096 (4xKyro CPU)
+ - 3GiB RAM
+ - 32GiB UFS drive
+
endchoice
source "board/qualcomm/dragonboard410c/Kconfig"
+source "board/qualcomm/dragonboard820c/Kconfig"
endif
diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile
index d82a04dda6..090c355b6b 100644
--- a/arch/arm/mach-snapdragon/Makefile
+++ b/arch/arm/mach-snapdragon/Makefile
@@ -4,5 +4,8 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y += clock-apq8016.o
-obj-y += sysmap-apq8016.o
+obj-$(CONFIG_TARGET_DRAGONBOARD820C) += clock-apq8096.o
+obj-$(CONFIG_TARGET_DRAGONBOARD820C) += sysmap-apq8096.o
+obj-$(CONFIG_TARGET_DRAGONBOARD410C) += clock-apq8016.o
+obj-$(CONFIG_TARGET_DRAGONBOARD410C) += sysmap-apq8016.o
+obj-y += clock-snapdragon.o
diff --git a/arch/arm/mach-snapdragon/clock-apq8016.c b/arch/arm/mach-snapdragon/clock-apq8016.c
index da05015c32..a2424178c6 100644
--- a/arch/arm/mach-snapdragon/clock-apq8016.c
+++ b/arch/arm/mach-snapdragon/clock-apq8016.c
@@ -14,146 +14,12 @@
#include <errno.h>
#include <asm/io.h>
#include <linux/bitops.h>
+#include "clock-snapdragon.h"
/* GPLL0 clock control registers */
-#define GPLL0_STATUS 0x2101C
#define GPLL0_STATUS_ACTIVE BIT(17)
-
-#define APCS_GPLL_ENA_VOTE 0x45000
#define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0)
-/* vote reg for blsp1 clock */
-#define APCS_CLOCK_BRANCH_ENA_VOTE 0x45004
-#define APCS_CLOCK_BRANCH_ENA_VOTE_BLSP1 BIT(10)
-
-/* SDC(n) clock control registers; n=1,2 */
-
-/* block control register */
-#define SDCC_BCR(n) ((n * 0x1000) + 0x41000)
-/* cmd */
-#define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004)
-/* cfg */
-#define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008)
-/* m */
-#define SDCC_M(n) ((n * 0x1000) + 0x4100C)
-/* n */
-#define SDCC_N(n) ((n * 0x1000) + 0x41010)
-/* d */
-#define SDCC_D(n) ((n * 0x1000) + 0x41014)
-/* branch control */
-#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018)
-#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C)
-
-/* BLSP1 AHB clock (root clock for BLSP) */
-#define BLSP1_AHB_CBCR 0x1008
-
-/* Uart clock control registers */
-#define BLSP1_UART2_BCR 0x3028
-#define BLSP1_UART2_APPS_CBCR 0x302C
-#define BLSP1_UART2_APPS_CMD_RCGR 0x3034
-#define BLSP1_UART2_APPS_CFG_RCGR 0x3038
-#define BLSP1_UART2_APPS_M 0x303C
-#define BLSP1_UART2_APPS_N 0x3040
-#define BLSP1_UART2_APPS_D 0x3044
-
-/* CBCR register fields */
-#define CBCR_BRANCH_ENABLE_BIT BIT(0)
-#define CBCR_BRANCH_OFF_BIT BIT(31)
-
-struct msm_clk_priv {
- phys_addr_t base;
-};
-
-/* Enable clock controlled by CBC soft macro */
-static void clk_enable_cbc(phys_addr_t cbcr)
-{
- setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT);
-
- while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
- ;
-}
-
-/* clock has 800MHz */
-static void clk_enable_gpll0(phys_addr_t base)
-{
- if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE)
- return; /* clock already enabled */
-
- setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0);
-
- while ((readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) == 0)
- ;
-}
-
-#define APPS_CMD_RGCR_UPDATE BIT(0)
-
-/* Update clock command via CMD_RGCR */
-static void clk_bcr_update(phys_addr_t apps_cmd_rgcr)
-{
- setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE);
-
- /* Wait for frequency to be updated. */
- while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE)
- ;
-}
-
-struct bcr_regs {
- uintptr_t cfg_rcgr;
- uintptr_t cmd_rcgr;
- uintptr_t M;
- uintptr_t N;
- uintptr_t D;
-};
-
-/* RCGR_CFG register fields */
-#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */
-
-/* sources */
-#define CFG_CLK_SRC_CXO (0 << 8)
-#define CFG_CLK_SRC_GPLL0 (1 << 8)
-#define CFG_CLK_SRC_MASK (7 << 8)
-
-/* Mask for supported fields */
-#define CFG_MASK 0x3FFF
-
-#define CFG_DIVIDER_MASK 0x1F
-
-/* root set rate for clocks with half integer and MND divider */
-static void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
- int div, int m, int n, int source)
-{
- uint32_t cfg;
- /* M value for MND divider. */
- uint32_t m_val = m;
- /* NOT(N-M) value for MND divider. */
- uint32_t n_val = ~((n)-(m)) * !!(n);
- /* NOT 2D value for MND divider. */
- uint32_t d_val = ~(n);
-
- /* Program MND values */
- writel(m_val, base + regs->M);
- writel(n_val, base + regs->N);
- writel(d_val, base + regs->D);
-
- /* setup src select and divider */
- cfg = readl(base + regs->cfg_rcgr);
- cfg &= ~CFG_MASK;
- cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
-
- /* Set the divider; HW permits fraction dividers (+0.5), but
- for simplicity, we will support integers only */
- if (div)
- cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
-
- if (n_val)
- cfg |= CFG_MODE_DUAL_EDGE;
-
- writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */
-
- /* Inform h/w to start using the new config. */
- clk_bcr_update(base + regs->cmd_rcgr);
-}
-
static const struct bcr_regs sdc_regs[] = {
{
.cfg_rcgr = SDCC_CFG_RCGR(1),
@@ -171,7 +37,14 @@ static const struct bcr_regs sdc_regs[] = {
}
};
-/* Init clock for SDHCI controller */
+static struct gpll0_ctrl gpll0_ctrl = {
+ .status = GPLL0_STATUS,
+ .status_bit = GPLL0_STATUS_ACTIVE,
+ .ena_vote = APCS_GPLL_ENA_VOTE,
+ .vote_bit = APCS_GPLL_ENA_VOTE_GPLL0,
+};
+
+/* SDHCI */
static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
{
int div = 8; /* 100MHz default */
@@ -183,7 +56,7 @@ static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate)
/* 800Mhz/div, gpll0 */
clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0,
CFG_CLK_SRC_GPLL0);
- clk_enable_gpll0(priv->base);
+ clk_enable_gpll0(priv->base, &gpll0_ctrl);
clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot));
return rate;
@@ -197,7 +70,7 @@ static const struct bcr_regs uart2_regs = {
.D = BLSP1_UART2_APPS_D,
};
-/* Init UART clock, 115200 */
+/* UART: 115200 */
static int clk_init_uart(struct msm_clk_priv *priv)
{
/* Enable iface clk */
@@ -205,7 +78,7 @@ static int clk_init_uart(struct msm_clk_priv *priv)
/* 7372800 uart block clock @ GPLL0 */
clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625,
CFG_CLK_SRC_GPLL0);
- clk_enable_gpll0(priv->base);
+ clk_enable_gpll0(priv->base, &gpll0_ctrl);
/* Enable core clk */
clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR);
@@ -230,33 +103,3 @@ ulong msm_set_rate(struct clk *clk, ulong rate)
return 0;
}
}
-
-static int msm_clk_probe(struct udevice *dev)
-{
- struct msm_clk_priv *priv = dev_get_priv(dev);
-
- priv->base = devfdt_get_addr(dev);
- if (priv->base == FDT_ADDR_T_NONE)
- return -EINVAL;
-
- return 0;
-}
-
-static struct clk_ops msm_clk_ops = {
- .set_rate = msm_set_rate,
-};
-
-static const struct udevice_id msm_clk_ids[] = {
- { .compatible = "qcom,gcc-msm8916" },
- { .compatible = "qcom,gcc-apq8016" },
- { }
-};
-
-U_BOOT_DRIVER(clk_msm) = {
- .name = "clk_msm",
- .id = UCLASS_CLK,
- .of_match = msm_clk_ids,
- .ops = &msm_clk_ops,
- .priv_auto_alloc_size = sizeof(struct msm_clk_priv),
- .probe = msm_clk_probe,
-};
diff --git a/arch/arm/mach-snapdragon/clock-apq8096.c b/arch/arm/mach-snapdragon/clock-apq8096.c
new file mode 100644
index 0000000000..3d363d4d66
--- /dev/null
+++ b/arch/arm/mach-snapdragon/clock-apq8096.c
@@ -0,0 +1,62 @@
+/*
+ * Clock drivers for Qualcomm APQ8096
+ *
+ * (C) Copyright 2017 Jorge Ramirez Ortiz <jorge.ramirez-ortiz@linaro.org>
+ *
+ * Based on Little Kernel driver, simplified
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include "clock-snapdragon.h"
+
+/* GPLL0 clock control registers */
+#define GPLL0_STATUS_ACTIVE BIT(30)
+#define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0)
+
+static const struct bcr_regs sdc_regs = {
+ .cfg_rcgr = SDCC2_CFG_RCGR,
+ .cmd_rcgr = SDCC2_CMD_RCGR,
+ .M = SDCC2_M,
+ .N = SDCC2_N,
+ .D = SDCC2_D,
+};
+
+static const struct gpll0_ctrl gpll0_ctrl = {
+ .status = GPLL0_STATUS,
+ .status_bit = GPLL0_STATUS_ACTIVE,
+ .ena_vote = APCS_GPLL_ENA_VOTE,
+ .vote_bit = APCS_GPLL_ENA_VOTE_GPLL0,
+};
+
+static int clk_init_sdc(struct msm_clk_priv *priv, uint rate)
+{
+ int div = 3;
+
+ clk_enable_cbc(priv->base + SDCC2_AHB_CBCR);
+ clk_rcg_set_rate_mnd(priv->base, &sdc_regs, div, 0, 0,
+ CFG_CLK_SRC_GPLL0);
+ clk_enable_gpll0(priv->base, &gpll0_ctrl);
+ clk_enable_cbc(priv->base + SDCC2_APPS_CBCR);
+
+ return rate;
+}
+
+ulong msm_set_rate(struct clk *clk, ulong rate)
+{
+ struct msm_clk_priv *priv = dev_get_priv(clk->dev);
+
+ switch (clk->id) {
+ case 0: /* SDC1 */
+ return clk_init_sdc(priv, rate);
+ break;
+ default:
+ return 0;
+ }
+}
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/arch/arm/mach-snapdragon/clock-snapdragon.c
new file mode 100644
index 0000000000..899b5ba6ce
--- /dev/null
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.c
@@ -0,0 +1,134 @@
+/*
+ * Clock drivers for Qualcomm APQ8016, APQ8096
+ *
+ * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
+ *
+ * Based on Little Kernel driver, simplified
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/bitops.h>
+#include "clock-snapdragon.h"
+
+/* CBCR register fields */
+#define CBCR_BRANCH_ENABLE_BIT BIT(0)
+#define CBCR_BRANCH_OFF_BIT BIT(31)
+
+extern ulong msm_set_rate(struct clk *clk, ulong rate);
+
+/* Enable clock controlled by CBC soft macro */
+void clk_enable_cbc(phys_addr_t cbcr)
+{
+ setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT);
+
+ while (readl(cbcr) & CBCR_BRANCH_OFF_BIT)
+ ;
+}
+
+void clk_enable_gpll0(phys_addr_t base, const struct gpll0_ctrl *gpll0)
+{
+ if (readl(base + gpll0->status) & gpll0->status_bit)
+ return; /* clock already enabled */
+
+ setbits_le32(base + gpll0->ena_vote, gpll0->vote_bit);
+
+ while ((readl(base + gpll0->status) & gpll0->status_bit) == 0)
+ ;
+}
+
+#define APPS_CMD_RGCR_UPDATE BIT(0)
+
+/* Update clock command via CMD_RGCR */
+void clk_bcr_update(phys_addr_t apps_cmd_rgcr)
+{
+ setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE);
+
+ /* Wait for frequency to be updated. */
+ while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE)
+ ;
+}
+
+#define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */
+
+#define CFG_MASK 0x3FFF
+
+#define CFG_DIVIDER_MASK 0x1F
+
+/* root set rate for clocks with half integer and MND divider */
+void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
+ int div, int m, int n, int source)
+{
+ u32 cfg;
+ /* M value for MND divider. */
+ u32 m_val = m;
+ /* NOT(N-M) value for MND divider. */
+ u32 n_val = ~((n) - (m)) * !!(n);
+ /* NOT 2D value for MND divider. */
+ u32 d_val = ~(n);
+
+ /* Program MND values */
+ writel(m_val, base + regs->M);
+ writel(n_val, base + regs->N);
+ writel(d_val, base + regs->D);
+
+ /* setup src select and divider */
+ cfg = readl(base + regs->cfg_rcgr);
+ cfg &= ~CFG_MASK;
+ cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */
+
+ /* Set the divider; HW permits fraction dividers (+0.5), but
+ for simplicity, we will support integers only */
+ if (div)
+ cfg |= (2 * div - 1) & CFG_DIVIDER_MASK;
+
+ if (n_val)
+ cfg |= CFG_MODE_DUAL_EDGE;
+
+ writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */
+
+ /* Inform h/w to start using the new config. */
+ clk_bcr_update(base + regs->cmd_rcgr);
+}
+
+static int msm_clk_probe(struct udevice *dev)
+{
+ struct msm_clk_priv *priv = dev_get_priv(dev);
+
+ priv->base = devfdt_get_addr(dev);
+ if (priv->base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static ulong msm_clk_set_rate(struct clk *clk, ulong rate)
+{
+ return msm_set_rate(clk, rate);
+}
+
+static struct clk_ops msm_clk_ops = {
+ .set_rate = msm_clk_set_rate,
+};
+
+static const struct udevice_id msm_clk_ids[] = {
+ { .compatible = "qcom,gcc-msm8916" },
+ { .compatible = "qcom,gcc-apq8016" },
+ { .compatible = "qcom,gcc-msm8996" },
+ { .compatible = "qcom,gcc-apq8096" },
+ { }
+};
+
+U_BOOT_DRIVER(clk_msm) = {
+ .name = "clk_msm",
+ .id = UCLASS_CLK,
+ .of_match = msm_clk_ids,
+ .ops = &msm_clk_ops,
+ .priv_auto_alloc_size = sizeof(struct msm_clk_priv),
+ .probe = msm_clk_probe,
+};
diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.h b/arch/arm/mach-snapdragon/clock-snapdragon.h
new file mode 100644
index 0000000000..d7026aa867
--- /dev/null
+++ b/arch/arm/mach-snapdragon/clock-snapdragon.h
@@ -0,0 +1,40 @@
+/*
+ * Qualcomm APQ8016, APQ8096
+ *
+ * (C) Copyright 2017 Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _CLOCK_SNAPDRAGON_H
+#define _CLOCK_SNAPDRAGON_H
+
+#define CFG_CLK_SRC_CXO (0 << 8)
+#define CFG_CLK_SRC_GPLL0 (1 << 8)
+#define CFG_CLK_SRC_MASK (7 << 8)
+
+struct gpll0_ctrl {
+ uintptr_t status;
+ int status_bit;
+ uintptr_t ena_vote;
+ int vote_bit;
+};
+
+struct bcr_regs {
+ uintptr_t cfg_rcgr;
+ uintptr_t cmd_rcgr;
+ uintptr_t M;
+ uintptr_t N;
+ uintptr_t D;
+};
+
+struct msm_clk_priv {
+ phys_addr_t base;
+};
+
+void clk_enable_gpll0(phys_addr_t base, const struct gpll0_ctrl *pll0);
+void clk_bcr_update(phys_addr_t apps_cmd_rgcr);
+void clk_enable_cbc(phys_addr_t cbcr);
+void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs,
+ int div, int m, int n, int source);
+
+#endif
diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
index cdbfad0def..1094b14a80 100644
--- a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
+++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8016.h
@@ -8,7 +8,32 @@
#ifndef _MACH_SYSMAP_APQ8016_H
#define _MACH_SYSMAP_APQ8016_H
-#define GICD_BASE 0x0b000000
-#define GICC_BASE 0x0a20c000
+#define GICD_BASE (0x0b000000)
+#define GICC_BASE (0x0a20c000)
+
+/* Clocks: (from CLK_CTL_BASE) */
+#define GPLL0_STATUS (0x2101C)
+#define APCS_GPLL_ENA_VOTE (0x45000)
+
+#define SDCC_BCR(n) ((n * 0x1000) + 0x41000)
+#define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004)
+#define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008)
+#define SDCC_M(n) ((n * 0x1000) + 0x4100C)
+#define SDCC_N(n) ((n * 0x1000) + 0x41010)
+#define SDCC_D(n) ((n * 0x1000) + 0x41014)
+#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018)
+#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C)
+
+/* BLSP1 AHB clock (root clock for BLSP) */
+#define BLSP1_AHB_CBCR 0x1008
+
+/* Uart clock control registers */
+#define BLSP1_UART2_BCR (0x3028)
+#define BLSP1_UART2_APPS_CBCR (0x302C)
+#define BLSP1_UART2_APPS_CMD_RCGR (0x3034)
+#define BLSP1_UART2_APPS_CFG_RCGR (0x3038)
+#define BLSP1_UART2_APPS_M (0x303C)
+#define BLSP1_UART2_APPS_N (0x3040)
+#define BLSP1_UART2_APPS_D (0x3044)
#endif
diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h
new file mode 100644
index 0000000000..fb89de258d
--- /dev/null
+++ b/arch/arm/mach-snapdragon/include/mach/sysmap-apq8096.h
@@ -0,0 +1,29 @@
+/*
+ * Qualcomm APQ8096 sysmap
+ *
+ * (C) Copyright 2017 Jorge Ramirez-Ortiz <jorge.ramirez-ortiz@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _MACH_SYSMAP_APQ8096_H
+#define _MACH_SYSMAP_APQ8096_H
+
+#define TLMM_BASE_ADDR (0x1010000)
+
+/* Strength (sdc1) */
+#define SDC1_HDRV_PULL_CTL_REG (TLMM_BASE_ADDR + 0x0012D000)
+
+/* Clocks: (from CLK_CTL_BASE) */
+#define GPLL0_STATUS (0x0000)
+#define APCS_GPLL_ENA_VOTE (0x52000)
+
+#define SDCC2_BCR (0x14000) /* block reset */
+#define SDCC2_APPS_CBCR (0x14004) /* branch control */
+#define SDCC2_AHB_CBCR (0x14008)
+#define SDCC2_CMD_RCGR (0x14010)
+#define SDCC2_CFG_RCGR (0x14014)
+#define SDCC2_M (0x14018)
+#define SDCC2_N (0x1401C)
+#define SDCC2_D (0x14020)
+
+#endif
diff --git a/arch/arm/mach-snapdragon/sysmap-apq8096.c b/arch/arm/mach-snapdragon/sysmap-apq8096.c
new file mode 100644
index 0000000000..cb6d1e475b
--- /dev/null
+++ b/arch/arm/mach-snapdragon/sysmap-apq8096.c
@@ -0,0 +1,32 @@
+/*
+ * Qualcomm APQ8096 memory map
+ *
+ * (C) Copyright 2017 Jorge Ramirez Ortiz <jorge.ramirez-ortiz@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/armv8/mmu.h>
+
+static struct mm_region apq8096_mem_map[] = {
+ {
+ .virt = 0x0UL, /* Peripheral block */
+ .phys = 0x0UL, /* Peripheral block */
+ .size = 0x10000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ .virt = 0x80000000UL, /* DDR */
+ .phys = 0x80000000UL, /* DDR */
+ .size = 0xC0000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ /* List terminator */
+ 0,
+ }
+};
+
+struct mm_region *mem_map = apq8096_mem_map;
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e67d428eb2..3f9e788e6c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -478,6 +478,13 @@
wdt0: wdt@0 {
compatible = "sandbox,wdt";
};
+
+ chosen {
+ chosen-test {
+ compatible = "denx,u-boot-fdt-test";
+ reg = <9 1>;
+ };
+ };
};
#include "sandbox_pmic.dtsi"