diff options
186 files changed, 8266 insertions, 1063 deletions
@@ -453,7 +453,7 @@ config SYS_EXTRA_OPTIONS config SYS_TEXT_BASE depends on !NIOS2 && !XTENSA depends on !EFI_APP - default 0x80800000 if ARCH_OMAP2PLUS + default 0x80800000 if ARCH_OMAP2PLUS || ARCH_K3 default 0x4a000000 if ARCH_SUNXI && !MACH_SUN9I && !MACH_SUN8I_V3S default 0x2a000000 if ARCH_SUNXI && MACH_SUN9I default 0x42e00000 if ARCH_SUNXI && MACH_SUN8I_V3S diff --git a/MAINTAINERS b/MAINTAINERS index 27bdd88120..39d28e5d45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -113,7 +113,7 @@ M: Thomas Fitzsimmons <fitzsim@fitzsim.org> S: Maintained F: arch/arm/mach-bcmstb/ F: board/broadcom/bcmstb/ -F: configs/bcm7445_defconfig +F: configs/bcm7*_defconfig F: doc/README.bcm7xxx F: drivers/mmc/bcmstb_sdhci.c F: drivers/spi/bcmstb_spi.c @@ -272,6 +272,7 @@ M: Tom Rini <trini@konsulko.com> S: Maintained T: git git://git.denx.de/u-boot-ti.git F: arch/arm/mach-davinci/ +F: arch/arm/mach-k3/ F: arch/arm/mach-keystone/ F: arch/arm/include/asm/arch-omap*/ F: arch/arm/include/asm/ti-common/ @@ -3015,11 +3015,6 @@ Configuration Settings: If defined, don't allow the -f switch to env set override variable access flags. -- CONFIG_USE_STDINT - If stdint.h is available with your toolchain you can define this - option to enable it. You can provide option 'USE_STDINT=1' when - building U-Boot to enable this. - The following definitions that deal with the placement and management of environment data (variable area); in general, we support the following configurations: diff --git a/arch/arc/include/asm/types.h b/arch/arc/include/asm/types.h index 3e37781677..f31dcdf28e 100644 --- a/arch/arc/include/asm/types.h +++ b/arch/arc/include/asm/types.h @@ -6,41 +6,9 @@ #ifndef __ASM_ARC_TYPES_H #define __ASM_ARC_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; +#include <asm-generic/int-ll64.h> -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; +typedef unsigned short umode_t; #define BITS_PER_LONG 32 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8a23c76db8..0f8dd32bdd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -646,6 +646,12 @@ config ARCH_KEYSTONE imply CMD_SAVES imply FIT +config ARCH_K3 + bool "Texas Instruments' K3 Architecture" + select SPL + select SUPPORT_SPL + select FIT + config ARCH_OMAP2PLUS bool "TI OMAP2+" select CPU_V7A @@ -1266,7 +1272,6 @@ config STM32 select CPU_V7M select DM select DM_SERIAL - select SYS_THUMB_BUILD imply CMD_DM config ARCH_STI @@ -1378,6 +1383,8 @@ source "arch/arm/mach-highbank/Kconfig" source "arch/arm/mach-integrator/Kconfig" +source "arch/arm/mach-k3/Kconfig" + source "arch/arm/mach-keystone/Kconfig" source "arch/arm/mach-kirkwood/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index cac58bdc4d..8f50560434 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -15,7 +15,7 @@ arch-$(CONFIG_CPU_PXA) = arch-$(CONFIG_CPU_ARM1136) =-march=armv5 arch-$(CONFIG_CPU_ARM1176) =-march=armv5t arch-$(CONFIG_CPU_V7A) =$(call cc-option, -march=armv7-a, \ - $(call cc-option, -march=armv7, -march=armv5)) + $(call cc-option, -march=armv7)) arch-$(CONFIG_CPU_V7M) =-march=armv7-m arch-$(CONFIG_CPU_V7R) =-march=armv7-r arch-$(CONFIG_ARM64) =-march=armv8-a @@ -40,7 +40,7 @@ tune-$(CONFIG_CPU_SA1100) =-mtune=strongarm1100 tune-$(CONFIG_CPU_PXA) =-mcpu=xscale tune-$(CONFIG_CPU_ARM1136) = tune-$(CONFIG_CPU_ARM1176) = -tune-$(CONFIG_CPU_V7A) = +tune-$(CONFIG_CPU_V7A) =-mtune=generic-armv7-a tune-$(CONFIG_CPU_V7R) = tune-$(CONFIG_ARM64) = @@ -58,6 +58,7 @@ machine-$(CONFIG_ARCH_BCMSTB) += bcmstb machine-$(CONFIG_ARCH_DAVINCI) += davinci machine-$(CONFIG_ARCH_EXYNOS) += exynos machine-$(CONFIG_ARCH_HIGHBANK) += highbank +machine-$(CONFIG_ARCH_K3) += k3 machine-$(CONFIG_ARCH_KEYSTONE) += keystone # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD machine-$(CONFIG_KIRKWOOD) += kirkwood diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c index 3b89391c37..22a55f52e0 100644 --- a/arch/arm/cpu/arm926ejs/cache.c +++ b/arch/arm/cpu/arm926ejs/cache.c @@ -65,3 +65,26 @@ __weak void l2_cache_disable(void) {} #if CONFIG_IS_ENABLED(SYS_THUMB_BUILD) __weak void invalidate_l2_cache(void) {} #endif + +#ifndef CONFIG_SYS_ICACHE_OFF +/* Invalidate entire I-cache and branch predictor array */ +void invalidate_icache_all(void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); +} +#else +void invalidate_icache_all(void) {} +#endif + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +#ifndef CONFIG_SYS_DCACHE_OFF + dcache_enable(); +#endif +} + diff --git a/arch/arm/cpu/arm926ejs/mx25/generic.c b/arch/arm/cpu/arm926ejs/mx25/generic.c index e6eef36c0e..2795a5f22e 100644 --- a/arch/arm/cpu/arm926ejs/mx25/generic.c +++ b/arch/arm/cpu/arm926ejs/mx25/generic.c @@ -214,14 +214,6 @@ int print_cpuinfo(void) } #endif -void enable_caches(void) -{ -#ifndef CONFIG_SYS_DCACHE_OFF - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -#endif -} - #if defined(CONFIG_FEC_MXC) /* * Initializes on-chip ethernet controllers. diff --git a/arch/arm/cpu/arm926ejs/mx27/generic.c b/arch/arm/cpu/arm926ejs/mx27/generic.c index a593283438..08b1b4de71 100644 --- a/arch/arm/cpu/arm926ejs/mx27/generic.c +++ b/arch/arm/cpu/arm926ejs/mx27/generic.c @@ -374,11 +374,3 @@ void mx27_sd2_init_pins(void) } #endif /* CONFIG_MMC_MXC */ - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -} -#endif /* CONFIG_SYS_DCACHE_OFF */ diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs.c b/arch/arm/cpu/arm926ejs/mxs/mxs.c index f42f311cbc..85c65dcb44 100644 --- a/arch/arm/cpu/arm926ejs/mxs/mxs.c +++ b/arch/arm/cpu/arm926ejs/mxs/mxs.c @@ -49,16 +49,6 @@ void reset_cpu(ulong ignored) ; } -void enable_caches(void) -{ -#ifndef CONFIG_SYS_ICACHE_OFF - icache_enable(); -#endif -#ifndef CONFIG_SYS_DCACHE_OFF - dcache_enable(); -#endif -} - /* * This function will craft a jumptable at 0x0 which will redirect interrupt * vectoring to proper location of U-Boot in RAM. diff --git a/arch/arm/cpu/arm926ejs/spear/cpu.c b/arch/arm/cpu/arm926ejs/spear/cpu.c index 0970aca2ef..88a40c6036 100644 --- a/arch/arm/cpu/arm926ejs/spear/cpu.c +++ b/arch/arm/cpu/arm926ejs/spear/cpu.c @@ -49,22 +49,15 @@ int arch_cpu_init(void) #if defined(CONFIG_USB_EHCI_SPEAR) periph1_clken |= PERIPH_USBH1 | PERIPH_USBH2; #endif +#if defined(CONFIG_SPEAR_GPIO) + periph1_clken |= MISC_GPIO3ENB | MISC_GPIO4ENB; +#endif writel(periph1_clken, &misc_p->periph1_clken); return 0; } -void enable_caches(void) -{ -#ifndef CONFIG_SYS_ICACHE_OFF - icache_enable(); -#endif -#ifndef CONFIG_SYS_DCACHE_OFF - dcache_enable(); -#endif -} - #ifdef CONFIG_DISPLAY_CPUINFO int print_cpuinfo(void) { diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 31d9256a3e..44ebc50bfa 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0+ -dtb-$(CONFIG_AT91FAMILY) += at91sam9260-smartweb.dtb \ - at91sam9g20-taurus.dtb \ - at91sam9g45-corvus.dtb \ - at91sam9g45-gurnard.dtb +dtb-$(CONFIG_TARGET_SMARTWEB) += at91sam9260-smartweb.dtb +dtb-$(CONFIG_TARGET_TAURUS) += at91sam9g20-taurus.dtb +dtb-$(CONFIG_TARGET_CORVUS) += at91sam9g45-corvus.dtb +dtb-$(CONFIG_TARGET_GURNARD) += at91sam9g45-gurnard.dtb dtb-$(CONFIG_S5PC100) += s5pc1xx-smdkc100.dtb dtb-$(CONFIG_S5PC110) += s5pc1xx-goni.dtb @@ -552,6 +552,8 @@ dtb-$(CONFIG_TARGET_STM32MP1) += \ stm32mp157c-ed1.dtb \ stm32mp157c-ev1.dtb +dtb-$(CONFIG_SOC_K3_AM6) += k3-am654-base-board.dtb + targets += $(dtb-y) # Add any required device tree compiler flags here diff --git a/arch/arm/dts/at91-vinco.dts b/arch/arm/dts/at91-vinco.dts index ff6d2e3205..0ecb64e718 100644 --- a/arch/arm/dts/at91-vinco.dts +++ b/arch/arm/dts/at91-vinco.dts @@ -152,6 +152,8 @@ }; tcb2: timer@fc024000 { + #address-cells = <1>; + #size-cells = <0>; timer@0 { compatible = "atmel,tcb-timer"; reg = <0>; diff --git a/arch/arm/dts/at91sam9260.dtsi b/arch/arm/dts/at91sam9260.dtsi index 69d9ceadaf..476ad1dad2 100644 --- a/arch/arm/dts/at91sam9260.dtsi +++ b/arch/arm/dts/at91sam9260.dtsi @@ -37,9 +37,6 @@ spi0 = &spi0; }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; diff --git a/arch/arm/dts/at91sam9261.dtsi b/arch/arm/dts/at91sam9261.dtsi index 69c2d6e416..b6357d3cb3 100644 --- a/arch/arm/dts/at91sam9261.dtsi +++ b/arch/arm/dts/at91sam9261.dtsi @@ -34,9 +34,6 @@ }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; diff --git a/arch/arm/dts/at91sam9263.dtsi b/arch/arm/dts/at91sam9263.dtsi index 0b594be221..61b056266b 100644 --- a/arch/arm/dts/at91sam9263.dtsi +++ b/arch/arm/dts/at91sam9263.dtsi @@ -36,9 +36,6 @@ }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; diff --git a/arch/arm/dts/at91sam9g45.dtsi b/arch/arm/dts/at91sam9g45.dtsi index 1be1270c57..c9b2e4698b 100644 --- a/arch/arm/dts/at91sam9g45.dtsi +++ b/arch/arm/dts/at91sam9g45.dtsi @@ -41,9 +41,6 @@ pwm0 = &pwm0; }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; @@ -1042,8 +1039,6 @@ }; adc0: adc@fffb0000 { - #address-cells = <1>; - #size-cells = <0>; compatible = "atmel,at91sam9g45-adc"; reg = <0xfffb0000 0x100>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0>; @@ -1086,10 +1081,6 @@ clocks = <&isi_clk>; clock-names = "isi_clk"; status = "disabled"; - port { - #address-cells = <1>; - #size-cells = <0>; - }; }; pwm0: pwm@fffb8000 { diff --git a/arch/arm/dts/at91sam9n12.dtsi b/arch/arm/dts/at91sam9n12.dtsi index 7ba7116e8f..024be13dab 100644 --- a/arch/arm/dts/at91sam9n12.dtsi +++ b/arch/arm/dts/at91sam9n12.dtsi @@ -38,9 +38,6 @@ spi0 = &spi0; }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; diff --git a/arch/arm/dts/at91sam9rl.dtsi b/arch/arm/dts/at91sam9rl.dtsi index 4602cd21e1..6d6aee5524 100644 --- a/arch/arm/dts/at91sam9rl.dtsi +++ b/arch/arm/dts/at91sam9rl.dtsi @@ -38,9 +38,6 @@ }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; @@ -253,8 +250,6 @@ }; adc0: adc@fffd0000 { - #address-cells = <1>; - #size-cells = <0>; compatible = "atmel,at91sam9rl-adc"; reg = <0xfffd0000 0x100>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH 0>; diff --git a/arch/arm/dts/at91sam9x5.dtsi b/arch/arm/dts/at91sam9x5.dtsi index a422c98706..ea319cc18b 100644 --- a/arch/arm/dts/at91sam9x5.dtsi +++ b/arch/arm/dts/at91sam9x5.dtsi @@ -41,9 +41,6 @@ }; cpus { - #address-cells = <0>; - #size-cells = <0>; - cpu { compatible = "arm,arm926ej-s"; device_type = "cpu"; @@ -1048,8 +1045,6 @@ }; adc0: adc@f804c000 { - #address-cells = <1>; - #size-cells = <0>; compatible = "atmel,at91sam9x5-adc"; reg = <0xf804c000 0x100>; interrupts = <19 IRQ_TYPE_LEVEL_HIGH 0>; diff --git a/arch/arm/dts/k3-am65-main.dtsi b/arch/arm/dts/k3-am65-main.dtsi new file mode 100644 index 0000000000..2409344df4 --- /dev/null +++ b/arch/arm/dts/k3-am65-main.dtsi @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for AM6 SoC Family Main Domain peripherals + * + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +&cbass_main { + gic500: interrupt-controller@1800000 { + compatible = "arm,gic-v3"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x01800000 0x10000>, /* GICD */ + <0x01880000 0x90000>; /* GICR */ + /* + * vcpumntirq: + * virtual CPU interface maintenance interrupt + */ + interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>; + + gic_its: gic-its@18200000 { + compatible = "arm,gic-v3-its"; + reg = <0x01820000 0x10000>; + msi-controller; + #msi-cells = <1>; + }; + }; +}; diff --git a/arch/arm/dts/k3-am65.dtsi b/arch/arm/dts/k3-am65.dtsi new file mode 100644 index 0000000000..cede1fa098 --- /dev/null +++ b/arch/arm/dts/k3-am65.dtsi @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for AM6 SoC Family + * + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> + +/ { + model = "Texas Instruments K3 AM654 SoC"; + compatible = "ti,am654"; + interrupt-parent = <&gic500>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + firmware { + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; + + psci: psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + }; + + a53_timer0: timer-cl0-cpu0 { + compatible = "arm,armv8-timer"; + interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* cntpsirq */ + <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, /* cntpnsirq */ + <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, /* cntvirq */ + <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; /* cnthpirq */ + }; + + pmu: pmu { + compatible = "arm,armv8-pmuv3"; + /* Recommendation from GIC500 TRM Table A.3 */ + interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; + }; + + cbass_main: interconnect@100000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x00100000 0x00 0x00100000 0x00020000>, /* ctrl mmr */ + <0x00600000 0x00 0x00600000 0x00001100>, /* GPIO */ + <0x00900000 0x00 0x00900000 0x00012000>, /* serdes */ + <0x01000000 0x00 0x01000000 0x0af02400>, /* Most peripherals */ + <0x30800000 0x00 0x30800000 0x0bc00000>, /* MAIN NAVSS */ + /* MCUSS Range */ + <0x28380000 0x00 0x28380000 0x03880000>, + <0x40200000 0x00 0x40200000 0x00900100>, + <0x42040000 0x00 0x42040000 0x03ac2400>, + <0x45100000 0x00 0x45100000 0x00c24000>, + <0x46000000 0x00 0x46000000 0x00200000>, + <0x47000000 0x00 0x47000000 0x00068400>; + + cbass_mcu: interconnect@28380000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x28380000 0x28380000 0x03880000>, /* MCU NAVSS*/ + <0x40200000 0x40200000 0x00900100>, /* First peripheral window */ + <0x42040000 0x42040000 0x03ac2400>, /* WKUP */ + <0x45100000 0x45100000 0x00c24000>, /* MMRs, remaining NAVSS */ + <0x46000000 0x46000000 0x00200000>, /* CPSW */ + <0x47000000 0x47000000 0x00068400>; /* OSPI space 1 */ + + cbass_wakeup: interconnect@42040000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + /* WKUP Basic peripherals */ + ranges = <0x42040000 0x42040000 0x03ac2400>; + }; + }; + }; +}; + +/* Now include the peripherals for each bus segments */ +#include "k3-am65-main.dtsi" diff --git a/arch/arm/dts/k3-am654-base-board-u-boot.dtsi b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi new file mode 100644 index 0000000000..d4ecb3be10 --- /dev/null +++ b/arch/arm/dts/k3-am654-base-board-u-boot.dtsi @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include <dt-bindings/pinctrl/k3-am65.h> + +/ { + chosen { + stdout-path = "serial2:115200n8"; + }; + + aliases { + serial2 = &main_uart0; + }; +}; + +&cbass_main{ + u-boot,dm-spl; + secure_proxy: secure_proxy@32c00000 { + compatible = "ti,am654-secure-proxy"; + #mbox-cells = <1>; + reg-names = "target_data", "rt", "scfg"; + reg = <0x32c00000 0x100000>, + <0x32400000 0x100000>, + <0x32800000 0x100000>; + interrupt-names = "rx_011"; + interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; + }; + + dmsc: dmsc { + compatible = "ti,k2g-sci"; + ti,host-id = <12>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + /* + * In case of rare platforms that does not use am6 as + * system master, use /delete-property/ + */ + ti,system-reboot-controller; + mbox-names = "rx", "tx"; + + mboxes= <&secure_proxy 11>, + <&secure_proxy 13>; + + k3_pds: power-controller { + compatible = "ti,sci-pm-domain"; + #power-domain-cells = <1>; + }; + + k3_clks: clocks { + compatible = "ti,k2g-sci-clk"; + #clock-cells = <2>; + }; + + k3_reset: reset-controller { + compatible = "ti,sci-reset"; + #reset-cells = <2>; + }; + + k3_sysreset: sysreset-controller { + compatible = "ti,sci-sysreset"; + }; + }; + + main_pmx0: pinmux@11c000 { + compatible = "pinctrl-single"; + reg = <0x11c000 0x2e4>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + main_pmx1: pinmux@11c2e8 { + compatible = "pinctrl-single"; + reg = <0x11c2e8 0x24>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + main_uart0: serial@2800000 { + compatible = "ti,am654-uart", "ti,omap4-uart", "ns16550a"; + reg = <0x02800000 0x100>; + reg-shift = <2>; + reg-io-width = <4>; + interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <48000000>; + current-speed = <115200>; + status = "disabled"; + u-boot,dm-pre-reloc; + }; + + sdhci0: sdhci@04F80000 { + compatible = "arasan,sdhci-5.1"; + reg = <0x4F80000 0x1000>, + <0x4F90000 0x400>; + clocks = <&k3_clks 47 1>; + power-domains = <&k3_pds 47>; + max-frequency = <25000000>; + }; + + sdhci1: sdhci@04FA0000 { + compatible = "arasan,sdhci-5.1"; + reg = <0x4FA0000 0x1000>, + <0x4FB0000 0x400>; + clocks = <&k3_clks 48 1>; + power-domains = <&k3_pds 48>; + max-frequency = <25000000>; + }; + +}; + +&secure_proxy { + u-boot,dm-spl; +}; + +&dmsc { + u-boot,dm-spl; +}; + +&k3_pds { + u-boot,dm-spl; +}; + +&k3_clks { + u-boot,dm-spl; +}; + +&k3_reset { + u-boot,dm-spl; +}; + +&main_pmx0 { + u-boot,dm-spl; + main_uart0_pins_default: main_uart0_pins_default { + pinctrl-single,pins = < + AM65X_IOPAD(0x01e4, PIN_INPUT | MUX_MODE0) /* (AF11) UART0_RXD */ + AM65X_IOPAD(0x01e8, PIN_OUTPUT | MUX_MODE0) /* (AE11) UART0_TXD */ + AM65X_IOPAD(0x01ec, PIN_INPUT | MUX_MODE0) /* (AG11) UART0_CTSn */ + AM65X_IOPAD(0x01f0, PIN_OUTPUT | MUX_MODE0) /* (AD11) UART0_RTSn */ + >; + }; + + main_mmc0_pins_default: main_mmc0_pins_default { + pinctrl-single,pins = < + AM65X_IOPAD(0x01a8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* (B25) MMC0_CLK */ + AM65X_IOPAD(0x01aC, PIN_INPUT_PULLUP | MUX_MODE0) /* (B27) MMC0_CMD */ + AM65X_IOPAD(0x01a4, PIN_INPUT_PULLUP | MUX_MODE0) /* (A26) MMC0_DAT0 */ + AM65X_IOPAD(0x01a0, PIN_INPUT_PULLUP | MUX_MODE0) /* (E25) MMC0_DAT1 */ + AM65X_IOPAD(0x019c, PIN_INPUT_PULLUP | MUX_MODE0) /* (C26) MMC0_DAT2 */ + AM65X_IOPAD(0x0198, PIN_INPUT_PULLUP | MUX_MODE0) /* (A25) MMC0_DAT3 */ + AM65X_IOPAD(0x0194, PIN_INPUT_PULLUP | MUX_MODE0) /* (E24) MMC0_DAT4 */ + AM65X_IOPAD(0x0190, PIN_INPUT_PULLUP | MUX_MODE0) /* (A24) MMC0_DAT5 */ + AM65X_IOPAD(0x018c, PIN_INPUT_PULLUP | MUX_MODE0) /* (B26) MMC0_DAT6 */ + AM65X_IOPAD(0x0188, PIN_INPUT_PULLUP | MUX_MODE0) /* (D25) MMC0_DAT7 */ + AM65X_IOPAD(0x01b0, PIN_INPUT | MUX_MODE0) /* (C25) MMC0_DS */ + >; + }; + + main_mmc1_pins_default: main_mmc1_pins_default { + pinctrl-single,pins = < + AM65X_IOPAD(0x02d4, PIN_INPUT_PULLDOWN | MUX_MODE0) /* (C27) MMC1_CLK */ + AM65X_IOPAD(0x02d8, PIN_INPUT_PULLUP | MUX_MODE0) /* (C28) MMC1_CMD */ + AM65X_IOPAD(0x02d0, PIN_INPUT_PULLUP | MUX_MODE0) /* (D28) MMC1_DAT0 */ + AM65X_IOPAD(0x02cc, PIN_INPUT_PULLUP | MUX_MODE0) /* (E27) MMC1_DAT1 */ + AM65X_IOPAD(0x02c8, PIN_INPUT_PULLUP | MUX_MODE0) /* (D26) MMC1_DAT2 */ + AM65X_IOPAD(0x02c4, PIN_INPUT_PULLUP | MUX_MODE0) /* (D27) MMC1_DAT3 */ + AM65X_IOPAD(0x02dc, PIN_INPUT_PULLUP | MUX_MODE0) /* (B24) MMC1_SDCD */ + AM65X_IOPAD(0x02e0, PIN_INPUT | MUX_MODE0) /* (C24) MMC1_SDWP */ + >; + }; + +}; + +&main_pmx1 { + u-boot,dm-spl; +}; + +&main_uart0 { + u-boot,dm-spl; + pinctrl-names = "default"; + pinctrl-0 = <&main_uart0_pins_default>; + status = "okay"; +}; + +&sdhci0 { + u-boot,dm-spl; + status = "okay"; + non-removable; + bus-width = <8>; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc0_pins_default>; +}; + +&sdhci1 { + u-boot,dm-spl; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&main_mmc1_pins_default>; + sdhci-caps-mask = <0x7 0x0>; +}; diff --git a/arch/arm/dts/k3-am654-base-board.dts b/arch/arm/dts/k3-am654-base-board.dts new file mode 100644 index 0000000000..af6956fdc1 --- /dev/null +++ b/arch/arm/dts/k3-am654-base-board.dts @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +/dts-v1/; + +#include "k3-am654.dtsi" + +/ { + compatible = "ti,am654-evm", "ti,am654"; + model = "Texas Instruments AM654 Base Board"; + + chosen { + stdout-path = "serial2:115200n8"; + bootargs = "earlycon=ns16550a,mmio32,0x02800000"; + }; + + memory@80000000 { + device_type = "memory"; + /* 4G RAM */ + reg = <0x00000000 0x80000000 0x00000000 0x80000000>, + <0x00000008 0x80000000 0x00000000 0x80000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + secure_ddr: secure_ddr@9e800000 { + reg = <0 0x9e800000 0 0x01800000>; /* for OP-TEE */ + alignment = <0x1000>; + no-map; + }; + }; +}; diff --git a/arch/arm/dts/k3-am654.dtsi b/arch/arm/dts/k3-am654.dtsi new file mode 100644 index 0000000000..2affa6f661 --- /dev/null +++ b/arch/arm/dts/k3-am654.dtsi @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device Tree Source for AM6 SoC family in Quad core configuration + * + * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ + */ + +#include "k3-am65.dtsi" + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu-map { + cluster0: cluster0 { + core0 { + cpu = <&cpu0>; + }; + + core1 { + cpu = <&cpu1>; + }; + }; + + cluster1: cluster1 { + core0 { + cpu = <&cpu2>; + }; + + core1 { + cpu = <&cpu3>; + }; + }; + }; + + cpu0: cpu@0 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x000>; + device_type = "cpu"; + enable-method = "psci"; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&L2_0>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x001>; + device_type = "cpu"; + enable-method = "psci"; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&L2_0>; + }; + + cpu2: cpu@100 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x100>; + device_type = "cpu"; + enable-method = "psci"; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&L2_1>; + }; + + cpu3: cpu@101 { + compatible = "arm,cortex-a53", "arm,armv8"; + reg = <0x101>; + device_type = "cpu"; + enable-method = "psci"; + i-cache-size = <0x8000>; + i-cache-line-size = <64>; + i-cache-sets = <256>; + d-cache-size = <0x8000>; + d-cache-line-size = <64>; + d-cache-sets = <128>; + next-level-cache = <&L2_1>; + }; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + cache-level = <2>; + cache-size = <0x80000>; + cache-line-size = <64>; + cache-sets = <512>; + next-level-cache = <&msmc_l3>; + }; + + L2_1: l2-cache1 { + compatible = "cache"; + cache-level = <2>; + cache-size = <0x80000>; + cache-line-size = <64>; + cache-sets = <512>; + next-level-cache = <&msmc_l3>; + }; + + msmc_l3: l3-cache0 { + compatible = "cache"; + cache-level = <3>; + }; +}; diff --git a/arch/arm/dts/sama5d27_som1.dtsi b/arch/arm/dts/sama5d27_som1.dtsi index 0c44a97f64..9efcf635ad 100644 --- a/arch/arm/dts/sama5d27_som1.dtsi +++ b/arch/arm/dts/sama5d27_som1.dtsi @@ -55,7 +55,6 @@ aliases { spi0 = &qspi1; - u-boot,dm-pre-reloc; }; ahb { diff --git a/arch/arm/dts/sama5d3.dtsi b/arch/arm/dts/sama5d3.dtsi index ee0e14e516..ba707b0ddf 100644 --- a/arch/arm/dts/sama5d3.dtsi +++ b/arch/arm/dts/sama5d3.dtsi @@ -238,10 +238,6 @@ clocks = <&isi_clk>; clock-names = "isi_clk"; status = "disabled"; - port { - #address-cells = <1>; - #size-cells = <0>; - }; }; sfr: sfr@f0038000 { diff --git a/arch/arm/dts/sama5d3xmb_cmp.dtsi b/arch/arm/dts/sama5d3xmb_cmp.dtsi index 77f989ce3c..9792b2a9d0 100644 --- a/arch/arm/dts/sama5d3xmb_cmp.dtsi +++ b/arch/arm/dts/sama5d3xmb_cmp.dtsi @@ -221,8 +221,6 @@ compatible = "gpio-keys"; status = "okay"; - #address-cells = <1>; - #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio_keys>; diff --git a/arch/arm/dts/usb_a9263.dts b/arch/arm/dts/usb_a9263.dts index bfc48a2724..9adc12af31 100644 --- a/arch/arm/dts/usb_a9263.dts +++ b/arch/arm/dts/usb_a9263.dts @@ -127,8 +127,6 @@ gpio_keys { compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; user_pb { label = "user_pb"; diff --git a/arch/arm/include/asm/arch-spear/spr_misc.h b/arch/arm/include/asm/arch-spear/spr_misc.h index c906730699..65063fca51 100644 --- a/arch/arm/include/asm/arch-spear/spr_misc.h +++ b/arch/arm/include/asm/arch-spear/spr_misc.h @@ -144,6 +144,7 @@ struct misc_regs { #define MISC_USBDENB 0x01000000 #define MISC_ETHENB 0x00800000 #define MISC_SMIENB 0x00200000 +#define MISC_GPIO3ENB 0x00040000 #define MISC_GPT3ENB 0x00010000 #define MISC_GPIO4ENB 0x00002000 #define MISC_GPT2ENB 0x00000800 diff --git a/arch/arm/include/asm/armv7m.h b/arch/arm/include/asm/armv7m.h index 278f302cdb..ad67b4fa34 100644 --- a/arch/arm/include/asm/armv7m.h +++ b/arch/arm/include/asm/armv7m.h @@ -10,11 +10,6 @@ #ifndef ARMV7M_H #define ARMV7M_H -#if defined(__ASSEMBLY__) -.syntax unified -.thumb -#endif - /* armv7m fixed base addresses */ #define V7M_SCS_BASE 0xE000E000 #define V7M_NVIC_BASE (V7M_SCS_BASE + 0x0100) diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h index 1c5e87340c..3039e66bf9 100644 --- a/arch/arm/include/asm/gpio.h +++ b/arch/arm/include/asm/gpio.h @@ -1,4 +1,5 @@ -#if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) +#if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \ + !defined(CONFIG_ARCH_K3) #include <asm/arch/gpio.h> #endif #include <asm-generic/gpio.h> diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h index b9e8a4f5d5..e568af2561 100644 --- a/arch/arm/include/asm/spl.h +++ b/arch/arm/include/asm/spl.h @@ -8,7 +8,7 @@ #if defined(CONFIG_ARCH_OMAP2PLUS) \ || defined(CONFIG_EXYNOS4) || defined(CONFIG_EXYNOS5) \ - || defined(CONFIG_EXYNOS4210) + || defined(CONFIG_EXYNOS4210) || defined(CONFIG_ARCH_K3) /* Platform-specific defines */ #include <asm/arch/spl.h> diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h index 9af7353f08..900b2619a4 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/asm/types.h @@ -1,44 +1,15 @@ #ifndef __ASM_ARM_TYPES_H #define __ASM_ARM_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; +#include <asm-generic/int-ll64.h> -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif +typedef unsigned short umode_t; /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - #ifdef CONFIG_ARM64 #define BITS_PER_LONG 64 #else /* CONFIG_ARM64 */ diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S index 0decce2c5b..fe312db690 100644 --- a/arch/arm/lib/crt0.S +++ b/arch/arm/lib/crt0.S @@ -8,9 +8,7 @@ #include <config.h> #include <asm-offsets.h> #include <linux/linkage.h> -#ifdef CONFIG_CPU_V7M -#include <asm/armv7m.h> -#endif +#include <asm/assembler.h> /* * This file handles the target-independent stages of the U-Boot @@ -139,9 +137,6 @@ here: mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at end of BSS */ -#if defined(CONFIG_CPU_V7M) - itt lo -#endif strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S index c5b135db40..e5f7267be1 100644 --- a/arch/arm/lib/relocate.S +++ b/arch/arm/lib/relocate.S @@ -6,6 +6,7 @@ */ #include <asm-offsets.h> +#include <asm/assembler.h> #include <config.h> #include <elf.h> #include <linux/linkage.h> diff --git a/arch/arm/lib/vectors.S b/arch/arm/lib/vectors.S index d629cb1dc2..2ca6e2494a 100644 --- a/arch/arm/lib/vectors.S +++ b/arch/arm/lib/vectors.S @@ -19,7 +19,11 @@ * for the non-boot0 case or by a boot0-header. */ .macro ARM_VECTORS +#ifdef CONFIG_ARCH_K3 + ldr pc, _reset +#else b reset +#endif ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort @@ -94,6 +98,7 @@ _start: ************************************************************************* */ + .globl _reset .globl _undefined_instruction .globl _software_interrupt .globl _prefetch_abort @@ -102,6 +107,9 @@ _start: .globl _irq .globl _fiq +#ifdef CONFIG_ARCH_K3 +_reset: .word reset +#endif _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort diff --git a/arch/arm/lib/vectors_m.S b/arch/arm/lib/vectors_m.S index d75e47734b..7d2d55c7f9 100644 --- a/arch/arm/lib/vectors_m.S +++ b/arch/arm/lib/vectors_m.S @@ -5,7 +5,7 @@ */ #include <config.h> -#include <asm/armv7m.h> +#include <asm/assembler.h> #include <linux/linkage.h> .type __hard_fault_entry, %function diff --git a/arch/arm/mach-at91/arm926ejs/Makefile b/arch/arm/mach-at91/arm926ejs/Makefile index a8a49ca43f..0639d7ea1e 100644 --- a/arch/arm/mach-at91/arm926ejs/Makefile +++ b/arch/arm/mach-at91/arm926ejs/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_AT91SAM9N12) += at91sam9n12_devices.o obj-$(CONFIG_AT91SAM9X5) += at91sam9x5_devices.o obj-$(CONFIG_AT91_EFLASH) += eflash.o obj-$(CONFIG_AT91_LED) += led.o -obj-y += cache.o obj-y += clock.o obj-y += cpu.o obj-y += reset.o diff --git a/arch/arm/mach-at91/arm926ejs/cache.c b/arch/arm/mach-at91/arm926ejs/cache.c deleted file mode 100644 index 024c8f5f3e..0000000000 --- a/arch/arm/mach-at91/arm926ejs/cache.c +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2016 - * Heiko Schocher, DENX Software Engineering, hs@denx.de. - */ -#include <linux/types.h> -#include <common.h> - -void enable_caches(void) -{ -#ifndef CONFIG_SYS_ICACHE_OFF - icache_enable(); -#endif -} - -#ifndef CONFIG_SYS_ICACHE_OFF -/* Invalidate entire I-cache and branch predictor array */ -void invalidate_icache_all(void) -{ - unsigned long i = 0; - - asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); -} -#else -void invalidate_icache_all(void) -{ -} -#endif diff --git a/arch/arm/mach-bcmstb/Kconfig b/arch/arm/mach-bcmstb/Kconfig index 6c7952ffe5..0a56c3c7fa 100644 --- a/arch/arm/mach-bcmstb/Kconfig +++ b/arch/arm/mach-bcmstb/Kconfig @@ -7,8 +7,14 @@ config TARGET_BCM7445 Support for the Broadcom 7445 SoC. This port assumes BOLT is acting as the second stage bootloader, and U-Boot is acting as the third stage bootloader (TSBL), loaded by BOLT. - This port may work on other BCM7xxx boards with - configuration changes. + +config TARGET_BCM7260 + bool "Broadcom 7260 TSBL" + depends on ARCH_BCMSTB + help + Support for the Broadcom 7260 SoC. This port assumes BOLT + is acting as the second stage bootloader, and U-Boot is + acting as the third stage bootloader (TSBL), loaded by BOLT. config SYS_CPU default "armv7" @@ -23,7 +29,8 @@ config SYS_SOC default "bcmstb" config SYS_CONFIG_NAME - default "bcm7445" + default "bcm7445" if TARGET_BCM7445 + default "bcm7260" if TARGET_BCM7260 config SYS_FDT_SAVE_ADDRESS hex "Address to which the prior stage provided DTB will be copied" diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig new file mode 100644 index 0000000000..2df6197af7 --- /dev/null +++ b/arch/arm/mach-k3/Kconfig @@ -0,0 +1,51 @@ +if ARCH_K3 + +choice + prompt "Texas Instruments' K3 based SoC select" + optional + +config SOC_K3_AM6 + bool "TI's K3 based AM6 SoC Family Support" + +endchoice + +config SYS_SOC + default "k3" + +config SYS_K3_NON_SECURE_MSRAM_SIZE + hex + default 0x80000 + help + Describes the total size of the MCU MSRAM. This doesn't + specify the total size of SPL as ROM can use some part + of this RAM. Once ROM gives control to SPL then this + complete size can be usable. + +config SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE + hex + default 0x58000 + help + Describes the maximum size of the image that ROM can download + from any boot media. + +config SYS_K3_MCU_SCRATCHPAD_BASE + hex + default 0x40280000 if SOC_K3_AM6 + help + Describes the base address of MCU Scratchpad RAM. + +config SYS_K3_MCU_SCRATCHPAD_SIZE + hex + default 0x200 if SOC_K3_AM6 + help + Describes the size of MCU Scratchpad RAM. + +config SYS_K3_BOOT_PARAM_TABLE_INDEX + hex + default 0x41c7fbfc if SOC_K3_AM6 + help + Address at which ROM stores the value which determines if SPL + is booted up by primary boot media or secondary boot media. + +source "board/ti/am65x/Kconfig" +endif diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile new file mode 100644 index 0000000000..e9b7ee5210 --- /dev/null +++ b/arch/arm/mach-k3/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +# Lokesh Vutla <lokeshvutla@ti.com> + +obj-$(CONFIG_SOC_K3_AM6) += am6_init.o +obj-$(CONFIG_ARM64) += arm64-mmu.o diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c new file mode 100644 index 0000000000..8a3a99f23a --- /dev/null +++ b/arch/arm/mach-k3/am6_init.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * K3: Architecture initialization + * + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <spl.h> +#include <asm/arch/hardware.h> + +#ifdef CONFIG_SPL_BUILD +static void mmr_unlock(u32 base, u32 partition) +{ + /* Translate the base address */ + phys_addr_t part_base = base + partition * CTRL_MMR0_PARTITION_SIZE; + + /* Unlock the requested partition if locked using two-step sequence */ + writel(CTRLMMR_LOCK_KICK0_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK0); + writel(CTRLMMR_LOCK_KICK1_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK1); +} + +static void ctrl_mmr_unlock(void) +{ + /* Unlock all WKUP_CTRL_MMR0 module registers */ + mmr_unlock(WKUP_CTRL_MMR0_BASE, 0); + mmr_unlock(WKUP_CTRL_MMR0_BASE, 1); + mmr_unlock(WKUP_CTRL_MMR0_BASE, 2); + mmr_unlock(WKUP_CTRL_MMR0_BASE, 3); + mmr_unlock(WKUP_CTRL_MMR0_BASE, 6); + mmr_unlock(WKUP_CTRL_MMR0_BASE, 7); + + /* Unlock all MCU_CTRL_MMR0 module registers */ + mmr_unlock(MCU_CTRL_MMR0_BASE, 0); + mmr_unlock(MCU_CTRL_MMR0_BASE, 1); + mmr_unlock(MCU_CTRL_MMR0_BASE, 2); + mmr_unlock(MCU_CTRL_MMR0_BASE, 6); + + /* Unlock all CTRL_MMR0 module registers */ + mmr_unlock(CTRL_MMR0_BASE, 0); + mmr_unlock(CTRL_MMR0_BASE, 1); + mmr_unlock(CTRL_MMR0_BASE, 2); + mmr_unlock(CTRL_MMR0_BASE, 3); + mmr_unlock(CTRL_MMR0_BASE, 6); + mmr_unlock(CTRL_MMR0_BASE, 7); +} + +static void store_boot_index_from_rom(void) +{ + u32 *boot_index = (u32 *)K3_BOOT_PARAM_TABLE_INDEX_VAL; + + *boot_index = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX); +} + +void board_init_f(ulong dummy) +{ + /* + * Cannot delay this further as there is a chance that + * K3_BOOT_PARAM_TABLE_INDEX can be over written by SPL MALLOC section. + */ + store_boot_index_from_rom(); + + /* Make all control module registers accessible */ + ctrl_mmr_unlock(); + + /* Init DM early in-order to invoke system controller */ + spl_early_init(); + + /* Prepare console output */ + preloader_console_init(); +} + +static u32 __get_backup_bootmedia(u32 devstat) +{ + u32 bkup_boot = (devstat & CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_MASK) >> + CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_SHIFT; + + switch (bkup_boot) { + case BACKUP_BOOT_DEVICE_USB: + return BOOT_DEVICE_USB; + case BACKUP_BOOT_DEVICE_UART: + return BOOT_DEVICE_UART; + case BACKUP_BOOT_DEVICE_ETHERNET: + return BOOT_DEVICE_ETHERNET; + case BACKUP_BOOT_DEVICE_MMC2: + return BOOT_DEVICE_MMC2; + case BACKUP_BOOT_DEVICE_SPI: + return BOOT_DEVICE_SPI; + case BACKUP_BOOT_DEVICE_HYPERFLASH: + return BOOT_DEVICE_HYPERFLASH; + case BACKUP_BOOT_DEVICE_I2C: + return BOOT_DEVICE_I2C; + }; + + return BOOT_DEVICE_RAM; +} + +static u32 __get_primary_bootmedia(u32 devstat) +{ + u32 bootmode = devstat & CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK; + + if (bootmode == BOOT_DEVICE_OSPI || bootmode == BOOT_DEVICE_QSPI) + bootmode = BOOT_DEVICE_SPI; + + return bootmode; +} + +u32 spl_boot_device(void) +{ + u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT); + u32 bootindex = readl(K3_BOOT_PARAM_TABLE_INDEX_VAL); + + if (bootindex == K3_PRIMARY_BOOTMODE) + return __get_primary_bootmedia(devstat); + else + return __get_backup_bootmedia(devstat); +} +#endif + +#ifndef CONFIG_SYSRESET +void reset_cpu(ulong ignored) +{ +} +#endif diff --git a/arch/arm/mach-k3/arm64-mmu.c b/arch/arm/mach-k3/arm64-mmu.c new file mode 100644 index 0000000000..f8b93fe458 --- /dev/null +++ b/arch/arm/mach-k3/arm64-mmu.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * K3: ARM64 MMU setup + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + * (This file is derived from arch/arm/cpu/armv8/zynqmp/cpu.c) + * + */ + +#include <common.h> +#include <asm/system.h> +#include <asm/armv8/mmu.h> + +/* NR_DRAM_BANKS + 32bit IO + 64bit IO + terminator */ +#define NR_MMU_REGIONS (CONFIG_NR_DRAM_BANKS + 3) + +/* ToDo: Add 64bit IO */ +struct mm_region am654_mem_map[NR_MMU_REGIONS] = { + { + .virt = 0x0UL, + .phys = 0x0UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0x880000000UL, + .phys = 0x880000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = am654_mem_map; diff --git a/arch/arm/mach-k3/config.mk b/arch/arm/mach-k3/config.mk new file mode 100644 index 0000000000..9b86ddc715 --- /dev/null +++ b/arch/arm/mach-k3/config.mk @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +# Lokesh Vutla <lokeshvutla@ti.com> + +ifdef CONFIG_SPL_BUILD + +ifdef CONFIG_ARM64 +SPL_ITS := u-boot-spl-k3.its +$(SPL_ITS): FORCE + $(srctree)/tools/k3_fit_atf.sh \ + $(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) > $@ + +ALL-y += tispl.bin +endif + +else +ALL-y += u-boot.img +endif diff --git a/arch/arm/mach-k3/include/mach/am6_hardware.h b/arch/arm/mach-k3/include/mach/am6_hardware.h new file mode 100644 index 0000000000..e4b78f8617 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/am6_hardware.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * K3: AM6 SoC definitions, structures etc. + * + * (C) Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ +#ifndef __ASM_ARCH_AM6_HARDWARE_H +#define __ASM_ARCH_AM6_HARDWARE_H + +#include <config.h> + +#define CTRL_MMR0_BASE 0x00100000 +#define CTRLMMR_MAIN_DEVSTAT (CTRL_MMR0_BASE + 0x30) + +#define CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK GENMASK(3, 0) +#define CTRLMMR_MAIN_DEVSTAT_BOOTMODE_SHIFT 0 +#define CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_MASK GENMASK(6, 4) +#define CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_SHIFT 4 + +#define WKUP_CTRL_MMR0_BASE 0x43000000 +#define MCU_CTRL_MMR0_BASE 0x40f00000 + +/* + * The CTRL_MMR0 memory space is divided into several equally-spaced + * partitions, so defining the partition size allows us to determine + * register addresses common to those partitions. + */ +#define CTRL_MMR0_PARTITION_SIZE 0x4000 + +/* + * CTRL_MMR0, WKUP_CTRL_MMR0, and MCU_CTR_MMR0 lock/kick-mechanism + * shared register definitions. + */ +#define CTRLMMR_LOCK_KICK0 0x01008 +#define CTRLMMR_LOCK_KICK0_UNLOCK_VAL 0x68ef3490 +#define CTRLMMR_LOCK_KICK0_UNLOCKED_MASK BIT(0) +#define CTRLMMR_LOCK_KICK0_UNLOCKED_SHIFT 0 +#define CTRLMMR_LOCK_KICK1 0x0100c +#define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a + +/* MCU SCRATCHPAD usage */ +#define K3_BOOT_PARAM_TABLE_INDEX_VAL CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE + +#endif /* __ASM_ARCH_AM6_HARDWARE_H */ diff --git a/arch/arm/mach-k3/include/mach/am6_spl.h b/arch/arm/mach-k3/include/mach/am6_spl.h new file mode 100644 index 0000000000..e97d8143c6 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/am6_spl.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ +#ifndef _ASM_ARCH_AM6_SPL_H_ +#define _ASM_ARCH_AM6_SPL_H_ + +#define BOOT_DEVICE_RAM 0x00 +#define BOOT_DEVICE_OSPI 0x01 +#define BOOT_DEVICE_QSPI 0x02 +#define BOOT_DEVICE_HYPERFLASH 0x03 +#define BOOT_DEVICE_SPI 0x04 +#define BOOT_DEVICE_I2C 0x05 +#define BOOT_DEVICE_MMC2 0x06 +#define BOOT_DEVICE_ETHERNET 0x07 +#define BOOT_DEVICE_USB 0x08 +#define BOOT_DEVICE_PCIE 0x09 +#define BOOT_DEVICE_UART 0x0a +#define BOOT_DEVICE_NAND 0x0c +#define BOOT_DEVICE_MMC1 0x0d +#define BOOT_DEVICE_MMC2_2 0x0e + +#define BACKUP_BOOT_DEVICE_RAM 0x0 +#define BACKUP_BOOT_DEVICE_USB 0x1 +#define BACKUP_BOOT_DEVICE_UART 0x2 +#define BACKUP_BOOT_DEVICE_ETHERNET 0x3 +#define BACKUP_BOOT_DEVICE_MMC2 0x4 +#define BACKUP_BOOT_DEVICE_SPI 0x5 +#define BACKUP_BOOT_DEVICE_HYPERFLASH 0x6 +#define BACKUP_BOOT_DEVICE_I2C 0x7 + +#define K3_PRIMARY_BOOTMODE 0x0 +#define K3_BACKUP_BOOTMODE 0x1 + +#endif diff --git a/arch/arm/mach-k3/include/mach/clock.h b/arch/arm/mach-k3/include/mach/clock.h new file mode 100644 index 0000000000..e3adbcd9de --- /dev/null +++ b/arch/arm/mach-k3/include/mach/clock.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * K3: Common SoC clock definitions. + * + * (C) Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + */ +#ifndef __ASM_ARCH_CLOCK_H +#define __ASM_ARCH_CLOCK_H + +#include <config.h> + +/* Clock Defines */ +#define V_OSCK 24000000 +#define V_SCLK V_OSCK + +#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h new file mode 100644 index 0000000000..b39f780d26 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/hardware.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ +#ifndef _ASM_ARCH_HARDWARE_H_ +#define _ASM_ARCH_HARDWARE_H_ + +#ifdef CONFIG_SOC_K3_AM6 +#include "am6_hardware.h" +#endif +#endif /* _ASM_ARCH_HARDWARE_H_ */ diff --git a/arch/arm/mach-k3/include/mach/spl.h b/arch/arm/mach-k3/include/mach/spl.h new file mode 100644 index 0000000000..2d435aec17 --- /dev/null +++ b/arch/arm/mach-k3/include/mach/spl.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ +#ifndef _ASM_ARCH_SPL_H_ +#define _ASM_ARCH_SPL_H_ + +#ifdef CONFIG_SOC_K3_AM6 +#include "am6_spl.h" +#endif +#endif /* _ASM_ARCH_SPL_H_ */ diff --git a/arch/arm/mach-omap2/omap3/lowlevel_init.S b/arch/arm/mach-omap2/omap3/lowlevel_init.S index e6e907d11f..2a05b5e521 100644 --- a/arch/arm/mach-omap2/omap3/lowlevel_init.S +++ b/arch/arm/mach-omap2/omap3/lowlevel_init.S @@ -21,6 +21,7 @@ * R0 - Service ID * R1 - paramer list */ +/* TODO: Re-evaluate the comment at the end regarding armv5 vs armv7 */ ENTRY(do_omap3_emu_romcode_call) PUSH {r4-r12, lr} @ Save all registers from ROM code! MOV r12, r0 @ Copy the Secure Service ID in R12 diff --git a/arch/m68k/include/asm/types.h b/arch/m68k/include/asm/types.h index 3ffcab20df..5d39b97b67 100644 --- a/arch/m68k/include/asm/types.h +++ b/arch/m68k/include/asm/types.h @@ -1,43 +1,17 @@ #ifndef _M68K_TYPES_H #define _M68K_TYPES_H +#include <asm-generic/int-ll64.h> + #ifndef __ASSEMBLY__ typedef unsigned short umode_t; -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif - typedef struct { __u32 u[4]; } __attribute__((aligned(16))) vector128; #ifdef __KERNEL__ -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; #define BITS_PER_LONG 32 diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h index 77094f62d6..056a3133fb 100644 --- a/arch/microblaze/include/asm/types.h +++ b/arch/microblaze/include/asm/types.h @@ -1,6 +1,8 @@ #ifndef _ASM_TYPES_H #define _ASM_TYPES_H +#include <asm-generic/int-ll64.h> + /* * This file is never included by application software unless * explicitly requested (e.g., via linux/types.h) in which case the @@ -12,41 +14,10 @@ typedef unsigned short umode_t; /* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif - -/* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - #define BITS_PER_LONG 32 /* Dma addresses are 32-bits wide. */ diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h index 7032862a29..925d7ef023 100644 --- a/arch/mips/include/asm/types.h +++ b/arch/mips/include/asm/types.h @@ -6,32 +6,12 @@ #ifndef _ASM_TYPES_H #define _ASM_TYPES_H +#include <asm-generic/int-ll64.h> + #ifndef __ASSEMBLY__ typedef unsigned short umode_t; -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#else -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif - #endif /* __ASSEMBLY__ */ /* @@ -43,18 +23,6 @@ typedef unsigned long long __u64; #ifndef __ASSEMBLY__ -typedef __signed char s8; -typedef unsigned char u8; - -typedef __signed short s16; -typedef unsigned short u16; - -typedef __signed int s32; -typedef unsigned int u32; - -typedef __signed__ long long s64; -typedef unsigned long long u64; - #if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \ || defined(CONFIG_64BIT) typedef u64 dma_addr_t; diff --git a/arch/nds32/include/asm/types.h b/arch/nds32/include/asm/types.h index 2e8924f76a..d2444da9b6 100644 --- a/arch/nds32/include/asm/types.h +++ b/arch/nds32/include/asm/types.h @@ -11,44 +11,15 @@ #ifndef __ASM_NDS_TYPES_H #define __ASM_NDS_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; +#include <asm-generic/int-ll64.h> -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif +typedef unsigned short umode_t; /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - #define BITS_PER_LONG 32 #include <stddef.h> diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h index b29ce792f7..cc8d123b8f 100644 --- a/arch/powerpc/include/asm/types.h +++ b/arch/powerpc/include/asm/types.h @@ -1,43 +1,17 @@ #ifndef _PPC_TYPES_H #define _PPC_TYPES_H +#include <asm-generic/int-ll64.h> + #ifndef __ASSEMBLY__ typedef unsigned short umode_t; -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif - typedef struct { __u32 u[4]; } __attribute__((aligned(16))) vector128; #ifdef __KERNEL__ -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; #define BITS_PER_LONG 32 diff --git a/arch/riscv/include/asm/types.h b/arch/riscv/include/asm/types.h index 9797206e5e..bd8627196d 100644 --- a/arch/riscv/include/asm/types.h +++ b/arch/riscv/include/asm/types.h @@ -12,44 +12,15 @@ #ifndef __ASM_RISCV_TYPES_H #define __ASM_RISCV_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; +#include <asm-generic/int-ll64.h> -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif +typedef unsigned short umode_t; /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - #define BITS_PER_LONG 32 #include <stddef.h> diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h index a10b4551fb..7cd56b4147 100644 --- a/arch/sandbox/include/asm/types.h +++ b/arch/sandbox/include/asm/types.h @@ -6,49 +6,15 @@ #ifndef __ASM_SANDBOX_TYPES_H #define __ASM_SANDBOX_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; +#include <asm-generic/int-ll64.h> -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif +typedef unsigned short umode_t; /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -#if !defined(CONFIG_USE_STDINT) || !defined(__INT64_TYPE__) -typedef signed long long s64; -typedef unsigned long long u64; -#else -typedef __INT64_TYPE__ s64; -typedef __UINT64_TYPE__ u64; -#endif - /* * Number of bits in a C 'long' on this architecture. */ diff --git a/arch/sh/include/asm/types.h b/arch/sh/include/asm/types.h index aed4a6eb57..c5ddbbd26b 100644 --- a/arch/sh/include/asm/types.h +++ b/arch/sh/include/asm/types.h @@ -1,29 +1,12 @@ #ifndef __ASM_SH_TYPES_H #define __ASM_SH_TYPES_H +#include <asm-generic/int-ll64.h> + #ifndef __ASSEMBLY__ typedef unsigned short umode_t; -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif - #endif /* __ASSEMBLY__ */ /* @@ -35,19 +18,6 @@ __extension__ typedef unsigned long long __u64; #ifndef __ASSEMBLY__ - -typedef __signed__ char s8; -typedef unsigned char u8; - -typedef __signed__ short s16; -typedef unsigned short u16; - -typedef __signed__ int s32; -typedef unsigned int u32; - -typedef __signed__ long long s64; -typedef unsigned long long u64; - /* Dma addresses are 32-bits wide. */ typedef u32 dma_addr_t; diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h index a47e581fe3..ba50001560 100644 --- a/arch/x86/include/asm/types.h +++ b/arch/x86/include/asm/types.h @@ -1,49 +1,15 @@ #ifndef __ASM_I386_TYPES_H #define __ASM_I386_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ +#include <asm-generic/int-ll64.h> -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif +typedef unsigned short umode_t; /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -#if !defined(CONFIG_USE_STDINT) || !defined(__INT64_TYPE__) -typedef signed long long s64; -typedef unsigned long long u64; -#else -typedef __INT64_TYPE__ s64; -typedef __UINT64_TYPE__ u64; -#endif - #if CONFIG_IS_ENABLED(X86_64) #define BITS_PER_LONG 64 #else diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 050f9d07c2..ed10755d9c 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -15,7 +15,6 @@ */ #include <common.h> -#include <inttypes.h> #include <relocate.h> #include <asm/u-boot-x86.h> #include <asm/sections.h> @@ -70,8 +69,7 @@ static void do_elf_reloc_fixups64(unsigned int text_base, uintptr_t size, *offset_ptr_ram = gd->reloc_off + re_src->r_addend; } else { - debug(" %p: %lx: rom reloc %lx, ram %p, value %lx, limit %" - PRIXPTR "\n", + debug(" %p: %lx: rom reloc %lx, ram %p, value %lx, limit %lX\n", re_src, (ulong)re_src->r_info, (ulong)re_src->r_offset, offset_ptr_ram, (ulong)*offset_ptr_ram, text_base + size); @@ -109,11 +107,9 @@ static void do_elf_reloc_fixups32(unsigned int text_base, uintptr_t size, *offset_ptr_ram <= text_base + size) { *offset_ptr_ram += gd->reloc_off; } else { - debug(" %p: rom reloc %x, ram %p, value %x," - " limit %" PRIXPTR "\n", re_src, - re_src->r_offset, offset_ptr_ram, - *offset_ptr_ram, - text_base + size); + debug(" %p: rom reloc %x, ram %p, value %x, limit %lX\n", + re_src, re_src->r_offset, offset_ptr_ram, + *offset_ptr_ram, text_base + size); } } else { debug(" %p: rom reloc %x, last %p\n", re_src, diff --git a/arch/xtensa/include/asm/types.h b/arch/xtensa/include/asm/types.h index bae1a480ee..2c5b5433cc 100644 --- a/arch/xtensa/include/asm/types.h +++ b/arch/xtensa/include/asm/types.h @@ -6,44 +6,15 @@ #ifndef _XTENSA_TYPES_H #define _XTENSA_TYPES_H -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; +#include <asm-generic/int-ll64.h> -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) -typedef __signed__ long long __s64; -typedef unsigned long long __u64; -#endif +typedef unsigned short umode_t; /* * These aren't exported outside the kernel to avoid name space clashes */ #ifdef __KERNEL__ -typedef signed char s8; -typedef unsigned char u8; - -typedef signed short s16; -typedef unsigned short u16; - -typedef signed int s32; -typedef unsigned int u32; - -typedef signed long long s64; -typedef unsigned long long u64; - #define BITS_PER_LONG 32 /* Dma addresses are 32-bits wide */ diff --git a/board/broadcom/bcmstb/MAINTAINERS b/board/broadcom/bcmstb/MAINTAINERS index 5851cb9978..eda29b95c8 100644 --- a/board/broadcom/bcmstb/MAINTAINERS +++ b/board/broadcom/bcmstb/MAINTAINERS @@ -5,3 +5,11 @@ F: board/broadcom/bcmstb/ F: include/configs/bcmstb.h F: include/configs/bcm7445.h F: configs/bcm7445_defconfig + +BCM7260 BOARD +M: Thomas Fitzsimmons <fitzsim@fitzsim.org> +S: Maintained +F: board/broadcom/bcmstb/ +F: include/configs/bcmstb.h +F: include/configs/bcm7260.h +F: configs/bcm7260_defconfig diff --git a/board/pandora/pandora.c b/board/pandora/pandora.c index 4f91dc3bee..a9aae7951d 100644 --- a/board/pandora/pandora.c +++ b/board/pandora/pandora.c @@ -13,6 +13,8 @@ * Texas Instruments, <www.ti.com> */ #include <common.h> +#include <dm.h> +#include <ns16550.h> #include <twl4030.h> #include <asm/io.h> #include <asm/gpio.h> @@ -33,6 +35,18 @@ DECLARE_GLOBAL_DATA_PTR; #define GPIO_IO_PWRDNZ (1 << 6) #define PBIASLITEVMODE1 (1 << 8) +static const struct ns16550_platdata pandora_serial = { + .base = OMAP34XX_UART3, + .reg_shift = 2, + .clock = V_NS16550_CLK, + .fcr = UART_FCR_DEFVAL, +}; + +U_BOOT_DEVICE(pandora_uart) = { + "ns16550_serial", + &pandora_serial +}; + /* * Routine: board_init * Description: Early hardware init. diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 35f5939552..649127c5bf 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -4,7 +4,6 @@ */ #include <common.h> -#include <inttypes.h> #include <config.h> #include <dm.h> #include <environment.h> @@ -384,7 +383,7 @@ static void set_serial_number(void) return; } - snprintf(serial_string, sizeof(serial_string), "%016" PRIx64, + snprintf(serial_string, sizeof(serial_string), "%016llx", msg->get_board_serial.body.resp.serial); env_set("serial#", serial_string); } diff --git a/board/ti/am65x/Kconfig b/board/ti/am65x/Kconfig new file mode 100644 index 0000000000..591600483e --- /dev/null +++ b/board/ti/am65x/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +# Lokesh Vutla <lokeshvutla@ti.com> + +choice + prompt "K3 AM65 based boards" + optional + +config TARGET_AM654_A53_EVM + bool "TI K3 based AM654 EVM running on A53" + select ARM64 + select SOC_K3_AM6 + +endchoice + +if TARGET_AM654_A53_EVM + +config SYS_BOARD + default "am65x" + +config SYS_VENDOR + default "ti" + +config SYS_CONFIG_NAME + default "am65x_evm" + +endif diff --git a/board/ti/am65x/MAINTAINERS b/board/ti/am65x/MAINTAINERS new file mode 100644 index 0000000000..ca1ce58f72 --- /dev/null +++ b/board/ti/am65x/MAINTAINERS @@ -0,0 +1,6 @@ +AM65x BOARD +M: Lokesh Vutla <lokeshvutla@ti.com> +S: Maintained +F: board/ti/am65x/ +F: include/configs/am65x_evm.h +F: configs/am65x_evm_a53_defconfig diff --git a/board/ti/am65x/Makefile b/board/ti/am65x/Makefile new file mode 100644 index 0000000000..94dddfcc4a --- /dev/null +++ b/board/ti/am65x/Makefile @@ -0,0 +1,8 @@ +# +# Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +# Lokesh Vutla <lokeshvutla@ti.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := evm.o diff --git a/board/ti/am65x/README b/board/ti/am65x/README new file mode 100644 index 0000000000..e7f4ff6578 --- /dev/null +++ b/board/ti/am65x/README @@ -0,0 +1,141 @@ +Introduction: +------------- +The AM65x family of SoCs is the first device family from K3 Multicore +SoC architecture, targeted for broad market and industrial control with +aim to meet the complex processing needs of modern embedded products. + +The device is built over three domains, each containing specific processing +cores, voltage domains and peripherals: +1. Wake-up (WKUP) domain: + - Device Management and Security Controller (DMSC) +2. Microcontroller (MCU) domain: + - Dual Core ARM Cortex-R5F processor +3. MAIN domain: + - Quad core 64-bit ARM Cortex-A53 + +More info can be found in TRM: http://www.ti.com/lit/pdf/spruid7 + +Boot Flow: +---------- +On AM65x family devices, ROM supports boot only via MCU(R5). This means that +bootloader has to run on R5 core. In order to meet this constraint, and for +the following reasons the boot flow is designed as mentioned: +1. Need to move away from R5 asap, so that we want to start *any* +firmware on the r5 cores like.... autosar can be loaded to receive CAN +response and other safety operations to be started. This operation is +very time critical and is applicable for all automotive use cases. +2. U-Boot on A53 should start other remotecores for various +applications. This should happen before running Linux. +3. In production boot flow, we might not like to use full u-boot, +instead use Flacon boot flow to reduce boot time. + ++------------------------------------------------------------------------+ +| DMSC | R5 | A53 | ++------------------------------------------------------------------------+ +| +--------+ | | | +| | Reset | | | | +| +--------+ | | | +| : | | | +| +--------+ | +-----------+ | | +| | *rom* |----------|-->| Reset rls | | | +| +--------+ | +-----------+ | | +| | | | : | | +| | rom | | : | | +| |services| | : | | +| | | | +-------------+ | | +| | | | | *R5 rom* | | | +| | | | +-------------+ | | +| | |<---------|---|Load and auth| | | +| | | | | tiboot3.bin | | | +| | | | +-------------+ | | +| | | | : | | +| | | | : | | +| | | | : | | +| | | | +-------------+ | | +| | Start | | | *R5 SPL* | | | +| | System | | +-------------+ | | +| |Firmware|<---------|---|Load and auth| | | +| +--------+ | | sysfw bin | | | +| : | +-------------+ | | +| +---------+ | | DDR | | | +| | *SYSFW* | | | config | | | +| +---------+ | +-------------+ | | +| | |<--------|---| Load | | | +| | | | | tispl.bin | | | +| | | | +-------------+ | | +| | |<--------|---| Start A53 | | | +| | | | | and Reset | | | +| | | | +-------------+ | | +| | | | | +-----------+ | +| | |---------|-----------------------|---->| Reset rls | | +| | | | | +-----------+ | +| | DMSC | | | : | +| |Services | | | +-----------+ | +| | |<--------|-----------------------|---->|*ATF/OPTEE*| | +| | | | | +-----------+ | +| | | | | : | +| | | | | +-----------+ | +| | |<--------|-----------------------|---->| *A53 SPL* | | +| | | | | +-----------+ | +| | | | | | Load | | +| | | | | | u-boot.img| | +| | | | | +-----------+ | +| | | | | : | +| | | | | +-----------+ | +| | |<--------|-----------------------|---->| *u-boot* | | +| | | | | +-----------+ | +| | | | | | prompt | | +| | | | | +-----------+ | +| +---------+ | | | +| | | | ++------------------------------------------------------------------------+ + +- Here DMSC acts as master and provides all the critical services. R5/A53 +requests DMSC to get these services done as shown in the above diagram. + +Sources: +-------- +1. SYSFW: + System Firmware repo is closed source and the binaries are delivered + to users with NDA. Please contact TI to get the System Firmware + Binary named ti-sci-firmware-am6x.bin that runs on AM65x SoC. + +2. ATF: + Tree: https://github.com/ARM-software/arm-trusted-firmware.git + Branch: master + +3. OPTEE: + Tree: https://github.com/OP-TEE/optee_os.git + Branch: master + +4. U-Boot: + Tree: http://git.denx.de/u-boot.git + Branch: master + +Build procedure: +---------------- +1. SYSFW: + ROM expects a signed binary that contains the X509 certificate. So +the binary ti-sci-firmware-am6x.bin cannot be uses as-is and needs to be signed. +Contact TI on the procedure to sign the system firmware binary. + +2. ATF: +$ make CROSS_COMPILE=aarch64-linux-gnu- ARCH=aarch64 PLAT=k3 TARGET_BOARD=generic SPD=opteed + +3. OPTEE: +$ make PLATFORM=k3-am65x CFG_ARM64_core=y + +4. U-Boot: + +4.1. R5: + TBD. + +4.2. A53: +$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- am65x_evm_a53_defconfig O=/tmp/a53 +$ make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF=<path to ATF dir>/build/k3/generic/release/bl31.bin TEE=<path to OPTEE OS dir>/out/arm-plat-k3/core/tee-pager.bin O=/tmp/a53 + +Target Images +-------------- +Copy the below images to an SD card and boot: +- tiboot3.bin from step 4.1 +- tispl.bin, u-boot.img from 4.2 diff --git a/board/ti/am65x/evm.c b/board/ti/am65x/evm.c new file mode 100644 index 0000000000..784b2b0191 --- /dev/null +++ b/board/ti/am65x/evm.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Board specific initialization for AM654 EVM + * + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + * + */ + +#include <common.h> +#include <asm/io.h> +#include <spl.h> + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + return 0; +} + +int dram_init(void) +{ +#ifdef CONFIG_PHYS_64BIT + gd->ram_size = 0x100000000; +#else + gd->ram_size = 0x80000000; +#endif + + return 0; +} + +ulong board_get_usable_ram_top(ulong total_size) +{ +#ifdef CONFIG_PHYS_64BIT + /* Limit RAM used by U-Boot to the DDR low region */ + if (gd->ram_top > 0x100000000) + return 0x100000000; +#endif + + return gd->ram_top; +} + +int dram_init_banksize(void) +{ + /* Bank 0 declares the memory available in the DDR low region */ + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = 0x80000000; + +#ifdef CONFIG_PHYS_64BIT + /* Bank 1 declares the memory available in the DDR high region */ + gd->bd->bi_dram[1].start = CONFIG_SYS_SDRAM_BASE1; + gd->bd->bi_dram[1].size = 0x80000000; +#endif + + return 0; +} + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ +#ifdef CONFIG_TARGET_AM654_A53_EVM + if (!strcmp(name, "k3-am654-base-board")) + return 0; +#endif + + return -1; +} +#endif @@ -17,7 +17,6 @@ #include <command.h> #include <console.h> #include <hash.h> -#include <inttypes.h> #include <mapmem.h> #include <watchdog.h> #include <asm/io.h> @@ -275,8 +274,7 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (word1 != word2) { ulong offset = buf1 - base; #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA - printf("%s at 0x%p (%#0*"PRIx64") != %s at 0x%p (%#0*" - PRIx64 ")\n", + printf("%s at 0x%p (%#0*llx) != %s at 0x%p (%#0*llx)\n", type, (void *)(addr1 + offset), size, word1, type, (void *)(addr2 + offset), size, word2); #else @@ -1000,7 +998,7 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) printf(" %08x", *((u32 *)ptr)); #ifdef CONFIG_SYS_SUPPORT_64BIT_DATA else if (size == 8) - printf(" %016" PRIx64, *((u64 *)ptr)); + printf(" %016llx", *((u64 *)ptr)); #endif else if (size == 2) printf(" %04x", *((u16 *)ptr)); diff --git a/cmd/part.c b/cmd/part.c index bee204fff0..bfb6488b0f 100644 --- a/cmd/part.c +++ b/cmd/part.c @@ -90,7 +90,7 @@ static int do_part_list(int argc, char * const argv[]) char str[512] = { '\0', }; disk_partition_t info; - for (p = 1; p < 128; p++) { + for (p = 1; p < MAX_SEARCH_PARTITIONS; p++) { char t[5]; int r = part_get_info(desc, p, &info); diff --git a/common/cli_readline.c b/common/cli_readline.c index 60a232b065..99b631720e 100644 --- a/common/cli_readline.c +++ b/common/cli_readline.c @@ -273,6 +273,10 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, ichar = getcmd_getch(); + /* ichar=0x0 when error occurs in U-Boot getc */ + if (!ichar) + continue; + if ((ichar == '\n') || (ichar == '\r')) { putc('\n'); break; diff --git a/common/console.c b/common/console.c index 7aa58d0a63..9a94f32192 100644 --- a/common/console.c +++ b/common/console.c @@ -311,12 +311,12 @@ int serial_printf(const char *fmt, ...) int fgetc(int file) { if (file < MAX_FILES) { -#if CONFIG_IS_ENABLED(CONSOLE_MUX) /* * Effectively poll for input wherever it may be available. */ for (;;) { WATCHDOG_RESET(); +#if CONFIG_IS_ENABLED(CONSOLE_MUX) /* * Upper layer may have already called tstc() so * check for that first. @@ -324,6 +324,10 @@ int fgetc(int file) if (tstcdev != NULL) return console_getc(file); console_tstc(file); +#else + if (console_tstc(file)) + return console_getc(file); +#endif #ifdef CONFIG_WATCHDOG /* * If the watchdog must be rate-limited then it should @@ -332,9 +336,6 @@ int fgetc(int file) udelay(1); #endif } -#else - return console_getc(file); -#endif } return -1; diff --git a/common/fdt_support.c b/common/fdt_support.c index d84f5dbade..e6daa67990 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -7,7 +7,6 @@ */ #include <common.h> -#include <inttypes.h> #include <stdio_dev.h> #include <linux/ctype.h> #include <linux/types.h> @@ -1025,8 +1024,7 @@ static u64 of_bus_default_map(fdt32_t *addr, const fdt32_t *range, s = fdt_read_number(range + na + pna, ns); da = fdt_read_number(addr, na); - debug("OF: default map, cp=%" PRIu64 ", s=%" PRIu64 - ", da=%" PRIu64 "\n", cp, s, da); + debug("OF: default map, cp=%llu, s=%llu, da=%llu\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; @@ -1081,8 +1079,7 @@ static u64 of_bus_isa_map(fdt32_t *addr, const fdt32_t *range, s = fdt_read_number(range + na + pna, ns); da = fdt_read_number(addr + 1, na - 1); - debug("OF: ISA map, cp=%" PRIu64 ", s=%" PRIu64 - ", da=%" PRIu64 "\n", cp, s, da); + debug("OF: ISA map, cp=%llu, s=%llu, da=%llu\n", cp, s, da); if (da < cp || da >= (cp + s)) return OF_BAD_ADDR; @@ -1188,7 +1185,7 @@ static int of_translate_one(const void *blob, int parent, struct of_bus *bus, finish: of_dump_addr("OF: parent translation for:", addr, pna); - debug("OF: with offset: %" PRIu64 "\n", offset); + debug("OF: with offset: %llu\n", offset); /* Translate it into parent bus space */ return pbus->translate(addr, offset, pna); @@ -1518,9 +1515,9 @@ int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr) dt_addr = fdt_translate_address(fdt, node, reg); if (addr != dt_addr) { - printf("Warning: U-Boot configured device %s at address %" - PRIx64 ",\n but the device tree has it address %" - PRIx64 ".\n", alias, addr, dt_addr); + printf("Warning: U-Boot configured device %s at address %llu,\n" + "but the device tree has it address %llx.\n", + alias, addr, dt_addr); return 0; } @@ -1668,7 +1665,7 @@ int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, if (ret < 0) return ret; - snprintf(name, sizeof(name), "framebuffer@%" PRIx64, base_address); + snprintf(name, sizeof(name), "framebuffer@%llx", base_address); ret = fdt_set_name(fdt, node, name); if (ret < 0) return ret; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 2e79d7d22b..280496fbe0 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -171,7 +171,7 @@ config SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR default 0x140 if ARCH_MVEBU default 0x200 if ARCH_SOCFPGA || ARCH_AT91 default 0x300 if ARCH_ZYNQ || ARCH_KEYSTONE || OMAP34XX || OMAP44XX || \ - OMAP54XX || AM33XX || AM43XX + OMAP54XX || AM33XX || AM43XX || ARCH_K3 default 0x4000 if ARCH_ROCKCHIP help Address on the MMC to load U-Boot from, when the MMC is being used @@ -430,6 +430,14 @@ config SPL_LIBGENERIC_SUPPORT boards. Enable this option to build the code in lib/ as part of an SPL build. +config SPL_DM_MAILBOX + bool "Support Mailbox" + help + Enable support for Mailbox within SPL. This enable the inter + processor communication protocols tobe used within SPL. Enable + this option to build the drivers in drivers/mailbox as part of + SPL build. + config SPL_MMC_SUPPORT bool "Support MMC" depends on MMC @@ -634,6 +642,12 @@ config SPL_RAM_DEVICE be already in memory when SPL takes over, e.g. loaded by the boot ROM. +config SPL_REMOTEPROC + bool "Support REMOTEPROCS" + help + Enable support for REMOTEPROCs in SPL. This permits to load + a remote processor firmware in SPL. + config SPL_RTC_SUPPORT bool "Support RTC drivers" help diff --git a/common/usb_storage.c b/common/usb_storage.c index 9cd64744f8..d92ebb6eb1 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -36,7 +36,6 @@ #include <command.h> #include <dm.h> #include <errno.h> -#include <inttypes.h> #include <mapmem.h> #include <memalign.h> #include <asm/byteorder.h> @@ -1164,8 +1163,8 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr, start = blknr; blks = blkcnt; - debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %" - PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr); + debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + block_dev->devnum, start, blks, buf_addr); do { /* XXX need some comment here */ @@ -1194,8 +1193,7 @@ retry_it: } while (blks != 0); ss->flags &= ~USB_READY; - debug("usb_read: end startblk " LBAF - ", blccnt %x buffer %" PRIxPTR "\n", + debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n", start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ @@ -1248,8 +1246,8 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, start = blknr; blks = blkcnt; - debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %" - PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr); + debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + block_dev->devnum, start, blks, buf_addr); do { /* If write fails retry for max retry count else @@ -1280,8 +1278,8 @@ retry_it: } while (blks != 0); ss->flags &= ~USB_READY; - debug("usb_write: end startblk " LBAF ", blccnt %x buffer %" - PRIxPTR "\n", start, smallblks, buf_addr); + debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n", + start, smallblks, buf_addr); usb_disable_asynch(0); /* asynch transfer allowed */ if (blkcnt >= ss->max_xfer_blk) @@ -62,11 +62,6 @@ ifdef FTRACE PLATFORM_CPPFLAGS += -finstrument-functions -DFTRACE endif -# Allow use of stdint.h if available -ifneq ($(USE_STDINT),) -PLATFORM_CPPFLAGS += -DCONFIG_USE_STDINT -endif - ######################################################################### RELFLAGS := $(PLATFORM_RELFLAGS) diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig new file mode 100644 index 0000000000..a17cf7cb50 --- /dev/null +++ b/configs/am65x_evm_a53_defconfig @@ -0,0 +1,71 @@ +CONFIG_ARM=y +CONFIG_ARCH_K3=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SOC_K3_AM6=y +CONFIG_TARGET_AM654_A53_EVM=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_SPL_FAT_SUPPORT=y +CONFIG_SPL_LIBDISK_SUPPORT=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=2 +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SPL_LOAD_FIT=y +CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run run_kern" +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SPL_SYS_MALLOC_SIMPLE=y +CONFIG_SPL_STACK_R=y +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_DM_MAILBOX=y +CONFIG_SPL_DM_RESET=y +CONFIG_SPL_POWER_DOMAIN=y +CONFIG_SPL_REMOTEPROC=y +CONFIG_SPL_YMODEM_SUPPORT=y +CONFIG_CMD_ASKENV=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_REMOTEPROC=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TIME=y +# CONFIG_ISO_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_DEFAULT_DEVICE_TREE="k3-am654-base-board" +CONFIG_SPL_MULTI_DTB_FIT=y +CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y +CONFIG_ENV_IS_IN_FAT=y +CONFIG_ENV_FAT_INTERFACE="mmc" +CONFIG_ENV_FAT_DEVICE_AND_PART="1:1" +CONFIG_DM=y +CONFIG_SPL_DM=y +CONFIG_SPL_DM_SEQ_ALIAS=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_CLK_TI_SCI=y +CONFIG_TI_SCI_PROTOCOL=y +CONFIG_DM_MAILBOX=y +CONFIG_K3_SEC_PROXY=y +CONFIG_MISC=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_K3_ARASAN=y +CONFIG_PINCTRL=y +# CONFIG_PINCTRL_GENERIC is not set +CONFIG_SPL_PINCTRL=y +# CONFIG_SPL_PINCTRL_GENERIC is not set +CONFIG_PINCTRL_SINGLE=y +CONFIG_POWER_DOMAIN=y +CONFIG_TI_SCI_POWER_DOMAIN=y +CONFIG_K3_SYSTEM_CONTROLLER=y +CONFIG_REMOTEPROC_K3=y +CONFIG_DM_RESET=y +CONFIG_RESET_TI_SCI=y +CONFIG_DM_SERIAL=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_TI_SCI=y diff --git a/configs/bcm7260_defconfig b/configs/bcm7260_defconfig new file mode 100644 index 0000000000..e3b6ed472c --- /dev/null +++ b/configs/bcm7260_defconfig @@ -0,0 +1,17 @@ +CONFIG_ARM=y +CONFIG_ARCH_BCMSTB=y +CONFIG_SYS_TEXT_BASE=0x10100000 +CONFIG_TARGET_BCM7260=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_FIT=y +CONFIG_FIT_SIGNATURE=y +CONFIG_BOOTDELAY=1 +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot>" +CONFIG_OF_PRIOR_STAGE=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_BCMSTB=y +CONFIG_CONS_INDEX=1 +CONFIG_EFI_LOADER=n +CONFIG_EFI_PARTITION=y diff --git a/configs/bcm7445_defconfig b/configs/bcm7445_defconfig index 59c745f41b..cb1522604d 100644 --- a/configs/bcm7445_defconfig +++ b/configs/bcm7445_defconfig @@ -12,10 +12,10 @@ CONFIG_OF_PRIOR_STAGE=y CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_BCMSTB=y -CONFIG_DM_SPI_FLASH=y -CONFIG_SPI_FLASH=y -CONFIG_CONS_INDEX=3 +CONFIG_CONS_INDEX=1 +CONFIG_EFI_LOADER=n CONFIG_SPI=y +CONFIG_SPI_FLASH=y CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y CONFIG_BCMSTB_SPI=y -# CONFIG_EFI_LOADER is not set diff --git a/configs/omap3_pandora_defconfig b/configs/omap3_pandora_defconfig index 6dce53834d..c2b4a4f0d2 100644 --- a/configs/omap3_pandora_defconfig +++ b/configs/omap3_pandora_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y CONFIG_SYS_TEXT_BASE=0x80008000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_TARGET_OMAP3_PANDORA=y CONFIG_DISTRO_DEFAULTS=y CONFIG_NR_DRAM_BANKS=2 @@ -25,11 +26,12 @@ CONFIG_MTDIDS_DEFAULT="nand0=omap2-nand.0" CONFIG_MTDPARTS_DEFAULT="mtdparts=omap2-nand.0:512k(xloader),1920k(uboot),128k(uboot-env),10m(boot),-(rootfs)" CONFIG_CMD_UBI=y CONFIG_ENV_IS_IN_NAND=y +CONFIG_DM=y CONFIG_TWL4030_LED=y CONFIG_MMC_OMAP_HS=y CONFIG_NAND=y CONFIG_SYS_NAND_BUSWIDTH_16BIT=y -CONFIG_CONS_INDEX=3 +CONFIG_DM_SERIAL=y CONFIG_SYS_NS16550=y CONFIG_SPI=y CONFIG_OMAP3_SPI=y diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index ed82a0a7e4..e134a66fb1 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -45,4 +45,5 @@ CONFIG_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_GPIO=y CONFIG_DM_REGULATOR_STM32_VREFBUF=y CONFIG_DM_REGULATOR_STPMU1=y +CONFIG_SERIAL_RX_BUFFER=y CONFIG_STM32_SERIAL=y diff --git a/disk/part_efi.c b/disk/part_efi.c index 2945892a24..519a637684 100644 --- a/disk/part_efi.c +++ b/disk/part_efi.c @@ -14,7 +14,6 @@ #include <command.h> #include <fdtdec.h> #include <ide.h> -#include <inttypes.h> #include <malloc.h> #include <memalign.h> #include <part_efi.h> diff --git a/doc/README.omap3 b/doc/README.omap3 index e09ac032c0..00bcbdba9a 100644 --- a/doc/README.omap3 +++ b/doc/README.omap3 @@ -23,13 +23,6 @@ Currently the following boards are supported: * CompuLab Ltd. CM-T35 [8] -Toolchain -========= - -While ARM Cortex-A8 support ARM v7 instruction set (-march=armv7a) we compile -with -march=armv5 to allow more compilers to work. For U-Boot code this has -no performance impact. - Build ===== diff --git a/doc/device-tree-bindings/clock/ti,sci-clk.txt b/doc/device-tree-bindings/clock/ti,sci-clk.txt new file mode 100644 index 0000000000..c6fe48200c --- /dev/null +++ b/doc/device-tree-bindings/clock/ti,sci-clk.txt @@ -0,0 +1,53 @@ +Texas Instruments TI SCI Clock Controller +========================================= + +All clocks on Texas Instruments' SoCs that contain a System Controller, +are only controlled by this entity. Communication between a host processor +running an OS and the System Controller happens through a protocol known +as TI SCI[1]. This clock implementation plugs into the common clock +framework and makes use of the TI SCI protocol on clock API requests. + +[1] http://processors.wiki.ti.com/index.php/TISCI + +Clock Controller Node +===================== +The clock controller node represents the clocks managed by the SYSFW. Because +this relies on the TI SCI protocol to communicate with the SYSFW it must be a +child of the sysfw node. + +Required Properties: +-------------------- +- compatible: Must be "ti,k2g-sci-clk" +- #clock-cells: Must be be 2. In clock consumers, this cell represents the + device ID and clock ID exposed by the SYSFW firmware. + +Example (AM65x): +---------------- + dmsc: dmsc { + compatible = "ti,k2g-sci"; + ... + k3_clks: clocks { + compatible = "ti,k2g-sci-clk"; + #clock-cells = <2>; + }; + }; + +Clock Consumers +=============== +Hardware blocks supplied by a clock should contain a "clocks" property that is +a phandle pointing to the clock controller node along with an index representing +the device id together with a clock ID to be passed to the SYSFW for device +control. + +Required Properties: +-------------------- +- clocks: phandle pointing to the corresponding clock node, an ID representing + the device, and an index representing a clock. + +Example (AM65x): +---------------- + uart2: serial@02800000 { + compatible = "ti,omap4-uart"; + ... + clocks = <&k3_clks 0x0007 1>; + }; diff --git a/doc/device-tree-bindings/firmware/ti,sci.txt b/doc/device-tree-bindings/firmware/ti,sci.txt new file mode 100644 index 0000000000..4d40d0dcb6 --- /dev/null +++ b/doc/device-tree-bindings/firmware/ti,sci.txt @@ -0,0 +1,76 @@ +Texas Instruments System Control Interface (TI-SCI) Message Protocol +-------------------------------------------------------------------- + +Texas Instrument's processors including those belonging to Keystone generation +of processors have separate hardware entity which is now responsible for the +management of the System on Chip (SoC) system. These include various system +level functions as well. + +An example of such an SoC is K2G, which contains the system control hardware +block called Power Management Micro Controller (PMMC). This hardware block is +initialized early into boot process and provides services to Operating Systems +on multiple processors including ones running Linux. + +See http://processors.wiki.ti.com/index.php/TISCI for protocol definition. + +TI-SCI controller Device Node: +============================= + +The TI-SCI node describes the Texas Instrument's System Controller entity node. +This parent node may optionally have additional children nodes which describe +specific functionality such as clocks, power domain, reset or additional +functionality as may be required for the SoC. This hierarchy also describes the +relationship between the TI-SCI parent node to the child node. + +Required properties: +------------------- +- compatible: should be "ti,k2g-sci" +- mbox-names: + "rx" - Mailbox corresponding to receive path + "tx" - Mailbox corresponding to transmit path + +- mboxes: Mailboxes corresponding to the mbox-names. Each value of the mboxes + property should contain a phandle to the mailbox controller device + node and an args specifier that will be the phandle to the intended + sub-mailbox child node to be used for communication. + +Optional Properties: +------------------- +- reg-names: + debug_messages - Map the Debug message region +- reg: register space corresponding to the debug_messages +- ti,system-reboot-controller: If system reboot can be triggered by SoC reboot +- ti,secure-host: If the host is defined as secure. + +Example: +------------- + dmsc: dmsc { + compatible = "ti,k2g-sci"; + ti,host-id = <12>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + } + + +TI-SCI Client Device Node: +========================= + +Client nodes are maintained as children of the relevant TI-SCI device node. + +Example: +------------- + dmsc: dmsc { + compatible = "ti,k2g-sci"; + ... + + my_clk_node: clk_node { + ... + ... + }; + + my_pd_node: pd_node { + ... + ... + }; + }; diff --git a/doc/device-tree-bindings/mailbox/k3-secure-proxy.txt b/doc/device-tree-bindings/mailbox/k3-secure-proxy.txt new file mode 100644 index 0000000000..f3add0d4e7 --- /dev/null +++ b/doc/device-tree-bindings/mailbox/k3-secure-proxy.txt @@ -0,0 +1,40 @@ +Texas Instruments' K3 Secure Proxy +=================================== + +The Texas Instruments' K3 Secure Proxy is a mailbox controller that has +configurable threads maintained by System power processor. Each thread +has different address space that can be used to send or receive messages. + +Secure Proxy Device Node: +=========================== +Required properties: +-------------------- +- compatible: Shall be: "ti,am654-secure-proxy" +- reg-names data - Map the data region + scfg - Map the secure configuration region + rt - Map the Realtime region. +- reg: Contains the register map per reg-names. +- #mbox-cells Shall be 1. Contains the thread ID. + +Example: +-------- + +secproxy: secproxy@285b0000 { + compatible = "ti,am654-secure-proxy"; + reg = <0x2a380000 0x80000>, + <0x2a400000 0x80000>, + <0x2a480000 0x80000>; + reg-names = "rt", "scfg", "data"; + #mbox-cells = <1>; +}; + +client: + +systemcontroller: systemcontroller { + [...] + # RX thread ID is 4. + # TX thread ID is 5. + mboxes= <&secproxy 4>, + <&secproxy 5>; + [...] +}; diff --git a/doc/device-tree-bindings/power/ti,sci-pm-domain.txt b/doc/device-tree-bindings/power/ti,sci-pm-domain.txt new file mode 100644 index 0000000000..0e190e20fe --- /dev/null +++ b/doc/device-tree-bindings/power/ti,sci-pm-domain.txt @@ -0,0 +1,52 @@ +Texas Instruments TI SCI Generic Power Domain +============================================= + +Some TI SoCs contain a system controller (like the SYSFW, etc...) that is +responsible for controlling the state of the IPs that are present. +Communication between the host processor running an OS and the system +controller happens through a protocol known as TI SCI [1]. + +[1] http://processors.wiki.ti.com/index.php/TISCI + +PM Domain Node +============== +The PM domain node represents the global PM domain managed by the SYSFW. Because +this relies on the TI SCI protocol to communicate with the SYSFW it must be a +child of the sysfw node. + +Required Properties: +-------------------- +- compatible: Must be "ti,sci-pm-domain" +- #power-domain-cells: Must be 1 so that an id can be provided in each + device node. + +Example (AM65x): +---------------- + sysfw: sysfw { + compatible = "ti,am654-system-controller"; + ... + k3_pds: power-controller { + compatible = "ti,sci-pm-domain"; + #power-domain-cells = <1>; + }; + }; + +PM Domain Consumers +=================== +Hardware blocks belonging to a PM domain should contain a "power-domains" +property that is a phandle pointing to the corresponding PM domain node +along with an index representing the device id to be passed to the PMMC +for device control. + +Required Properties: +-------------------- +- power-domains: phandle pointing to the corresponding PM domain node + and an ID representing the device. + +Example (AM65x): +---------------- + uart2: serial@02800000 { + compatible = "ti,omap4-uart"; + ... + power-domains = <&k3_pds 0x3f>; + }; diff --git a/doc/device-tree-bindings/remoteproc/k3-rproc.txt b/doc/device-tree-bindings/remoteproc/k3-rproc.txt new file mode 100644 index 0000000000..0a1e858225 --- /dev/null +++ b/doc/device-tree-bindings/remoteproc/k3-rproc.txt @@ -0,0 +1,50 @@ +Texas Instruments' K3 Remote processor driver +============================================= + +In K3 generation Socs, loading an image on any processing entity +cannot be done directly from U-Boot. In order to load an image, +remoteproc driver should communicate to SYSFW with a specific sequence. +Also enable the timer required for this remotecore. + +Required properties: +-------------------- +- compatible: Shall be: "ti,am654-rproc" +- reg: base address of the remoteproc timer. +- power-domains: Should contain two sets of entries: + First set corresponds to pm domain of the + remotecore timer. Seconf entry corresponds to the + remoteproc to start. + This property is as per the binding, + doc/device-tree-bindings/power/ti,sci-pm-domain.txt +- resets: Should contain a phandle to a reset controller node + and an args specifier containing the remote code + device id and reset mask value. This is as per the + doc/device-tree-bindings/reset/ti,sci-reset.txt +- ti,sci: Phandle to TI-SCI compatible System controller node. +- ti,sci-proc-id: Processor id as identified by TISCI + +Optional properties: +-------------------- +- assigned-clocks: Should contain a phandle to clock node and an args + specifier containing the remote core device id and + the clock id within the remote core. This is as per + doc/device-tree-bindings/clock/ti,sci-clk.txt +- assigned-clock-rates: One entry for each entry of assigned-clocks. This is + the frequency at which the corresponding clock needs + to be assigned. +- ti,sci-host-id: Host ID to which the processor control is transferred to + +Example: +--------- + +a53_0: a53@0 { + compatible = "ti,am654-rproc"; + power-domains = <&k3_pds 61>, + <&k3_pds 202>; + resets = <&k3_reset 202 0>; + assigned-clocks = <&k3_clks 202 0>; + assigned-clock-rates = <800000000>; + ti,sci = <&dmsc>; + ti,sci-proc-id = <32>; + ti,sci-host-id = <10>; +}; diff --git a/doc/device-tree-bindings/remoteproc/k3-system-controller.txt b/doc/device-tree-bindings/remoteproc/k3-system-controller.txt new file mode 100644 index 0000000000..32f4720b0d --- /dev/null +++ b/doc/device-tree-bindings/remoteproc/k3-system-controller.txt @@ -0,0 +1,24 @@ +Texas Instruments' K3 System Controller +========================================= + +K3 specific SoCs have a dedicated microcontroller for doing +resource management. Any HLOS/firmware on compute clusters should +load a firmware to this microcontroller before accessing any resource. +This driver communicates with ROM for loading this firmware. + +Required properties: +-------------------- +- compatible: Shall be: "ti,am654-system-controller" +- mbox-names: "tx" for Transfer channel + "rx" for Receive channel +- mboxes: Corresponding phandles to mailbox channels. + + +Example: +-------- + +system-controller: system-controller { + compatible = "ti,am654-system-controller"; + mboxes= <&secproxy 4>, <&secproxy 5>; + mbox-names = "tx", "rx"; +}; diff --git a/doc/device-tree-bindings/reset/ti,sci-reset.txt b/doc/device-tree-bindings/reset/ti,sci-reset.txt new file mode 100644 index 0000000000..e7e2d13f9f --- /dev/null +++ b/doc/device-tree-bindings/reset/ti,sci-reset.txt @@ -0,0 +1,54 @@ +Texas Instruments TI SCI Reset Controller +========================================= + +Some TI SoCs contain a system controller (like the SYSFW, etc...) that is +responsible for controlling the state of the IPs that are present. +Communication between the host processor running an OS and the system +controller happens through a protocol known as TI SCI [1]. + +[1] http://processors.wiki.ti.com/index.php/TISCI + +Reset Controller Node +===================== +The reset controller node represents the resets of various hardware modules +present on the SoC managed by the SYSFW. Because this relies on the TI SCI +protocol to communicate with the SYSFW it must be a child of the sysfw node. + +Required Properties: +-------------------- + - compatible: Must be "ti,sci-reset" + - #reset-cells: Must be 2. Please see the reset consumer node below for + usage details. + +Example (AM65x): +---------------- + sysfw: sysfw { + compatible = "ti,am654-system-controller"; + ... + k3_reset: reset-controller { + compatible = "ti,sci-reset"; + #reset-cells = <2>; + }; + }; + +Reset Consumers +=============== +Each of the reset consumer nodes should have the following properties, +in addition to their own properties. + +Required Properties: +-------------------- + - resets: A phandle and reset specifier pair, one pair for each reset signal + that affects the device, or that the device manages. The phandle + should point to the TI SCI reset controller node, and the reset + specifier should have 2 cell-values. The first cell should contain + the device ID. The second cell should contain the reset mask value + used by system controller. + +Example (AM65x): +---------------- + uart2: serial@02800000 { + compatible = "ti,omap4-uart"; + ... + resets = <&k3_reset 5 1>; + }; diff --git a/doc/device-tree-bindings/sysreset/ti,sci-sysreset.txt b/doc/device-tree-bindings/sysreset/ti,sci-sysreset.txt new file mode 100644 index 0000000000..02704c6487 --- /dev/null +++ b/doc/device-tree-bindings/sysreset/ti,sci-sysreset.txt @@ -0,0 +1,29 @@ +Texas Instruments TI SCI System Reset Controller +================================================ + +Some TI SoCs contain a system controller (like the SYSFW, etc...) that is +responsible for controlling the state of the IPs that are present. +Communication between the host processor running an OS and the system +controller happens through a protocol known as TI SCI [1]. + +[1] http://processors.wiki.ti.com/index.php/TISCI + +System Reset Controller Node +============================ +The sysreset controller node represents the reset for the overall SoC +which is managed by the SYSFW. Because this relies on the TI SCI protocol +to communicate with the SYSFW it must be a child of the sysfw node. + +Required Properties: +-------------------- + - compatible: Must be "ti,sci-sysreset" + +Example (AM65x): +---------------- + sysfw: sysfw { + compatible = "ti,am654-system-controller"; + ... + k3_sysreset: sysreset-controller { + compatible = "ti,sci-sysreset"; + }; + }; diff --git a/drivers/Makefile b/drivers/Makefile index d296354b3c..23ea609b09 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -14,6 +14,8 @@ obj-$(CONFIG_$(SPL_TPL_)SERIAL_SUPPORT) += serial/ obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_SUPPORT) += mtd/spi/ obj-$(CONFIG_$(SPL_TPL_)SPI_SUPPORT) += spi/ obj-$(CONFIG_$(SPL_TPL_)TIMER) += timer/ +obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox/ +obj-$(CONFIG_$(SPL_)REMOTEPROC) += remoteproc/ ifndef CONFIG_TPL_BUILD ifdef CONFIG_SPL_BUILD @@ -101,7 +103,6 @@ obj-y += input/ # SOC specific infrastructure drivers. obj-y += smem/ obj-y += soc/ -obj-$(CONFIG_REMOTEPROC) += remoteproc/ obj-y += thermal/ obj-y += axi/ diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index a99abed9e9..809eb3dacf 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -54,6 +54,14 @@ config CLK_STM32F This clock driver adds support for RCC clock management for STM32F4 and STM32F7 SoCs. +config CLK_TI_SCI + bool "TI System Control Interface (TI SCI) clock driver" + depends on CLK && TI_SCI_PROTOCOL && OF_CONTROL + help + This enables the clock driver support over TI System Control Interface + available on some new TI's SoCs. If you wish to use clock resources + managed by the TI System Controller, say Y here. Otherwise, say N. + config CLK_HSDK bool "Enable cgu clock driver for HSDK" depends on CLK diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 034bf44078..82c36b7478 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_MACH_PIC32) += clk_pic32.o obj-$(CONFIG_SANDBOX) += clk_sandbox.o obj-$(CONFIG_SANDBOX) += clk_sandbox_test.o obj-$(CONFIG_STM32H7) += clk_stm32h7.o +obj-$(CONFIG_CLK_TI_SCI) += clk-ti-sci.o diff --git a/drivers/clk/clk-ti-sci.c b/drivers/clk/clk-ti-sci.c new file mode 100644 index 0000000000..c25415d410 --- /dev/null +++ b/drivers/clk/clk-ti-sci.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments System Control Interface (TI SCI) clock driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg <dannenberg@ti.com> + * + * Loosely based on Linux kernel sci-clk.c... + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <clk-uclass.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +/** + * struct ti_sci_clk_data - clock controller information structure + * @sci: TI SCI handle used for communication with system controller + */ +struct ti_sci_clk_data { + const struct ti_sci_handle *sci; +}; + +static int ti_sci_clk_probe(struct udevice *dev) +{ + struct ti_sci_clk_data *data = dev_get_priv(dev); + + debug("%s(dev=%p)\n", __func__, dev); + + if (!data) + return -ENOMEM; + + /* Store handle for communication with the system controller */ + data->sci = ti_sci_get_handle(dev); + if (IS_ERR(data->sci)) + return PTR_ERR(data->sci); + + return 0; +} + +static int ti_sci_clk_of_xlate(struct clk *clk, + struct ofnode_phandle_args *args) +{ + debug("%s(clk=%p, args_count=%d)\n", __func__, clk, args->args_count); + + if (args->args_count != 2) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + /* + * On TI SCI-based devices, the clock provider id field is used as a + * device ID, and the data field is used as the associated sub-ID. + */ + clk->id = args->args[0]; + clk->data = args->args[1]; + + return 0; +} + +static int ti_sci_clk_request(struct clk *clk) +{ + debug("%s(clk=%p)\n", __func__, clk); + return 0; +} + +static int ti_sci_clk_free(struct clk *clk) +{ + debug("%s(clk=%p)\n", __func__, clk); + return 0; +} + +static ulong ti_sci_clk_get_rate(struct clk *clk) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + u64 current_freq; + int ret; + + debug("%s(clk=%p)\n", __func__, clk); + + ret = cops->get_freq(sci, clk->id, clk->data, ¤t_freq); + if (ret) { + dev_err(clk->dev, "%s: get_freq failed (%d)\n", __func__, ret); + return ret; + } + + debug("%s(current_freq=%llu)\n", __func__, current_freq); + + return current_freq; +} + +static ulong ti_sci_clk_set_rate(struct clk *clk, ulong rate) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + int ret; + + debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate); + + /* Ask for exact frequency by using same value for min/target/max */ + ret = cops->set_freq(sci, clk->id, clk->data, rate, rate, rate); + if (ret) + dev_err(clk->dev, "%s: set_freq failed (%d)\n", __func__, ret); + + return ret; +} + +static int ti_sci_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + u8 num_parents; + u8 parent_cid; + int ret; + + debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent); + + /* Make sure the clock parent is valid for a given device ID */ + if (clk->id != parent->id) + return -EINVAL; + + /* Make sure clock has parents that can be set */ + ret = cops->get_num_parents(sci, clk->id, clk->data, &num_parents); + if (ret) { + dev_err(clk->dev, "%s: get_num_parents failed (%d)\n", + __func__, ret); + return ret; + } + if (num_parents < 2) { + dev_err(clk->dev, "%s: clock has no settable parents!\n", + __func__); + return -EINVAL; + } + + /* Make sure parent clock ID is valid */ + parent_cid = parent->data - clk->data - 1; + if (parent_cid >= num_parents) { + dev_err(clk->dev, "%s: invalid parent clock!\n", __func__); + return -EINVAL; + } + + /* Ready to proceed to configure the new clock parent */ + ret = cops->set_parent(sci, clk->id, clk->data, parent->data); + if (ret) + dev_err(clk->dev, "%s: set_parent failed (%d)\n", __func__, + ret); + + return ret; +} + +static int ti_sci_clk_enable(struct clk *clk) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + int ret; + + debug("%s(clk=%p)\n", __func__, clk); + + /* + * Allow the System Controller to automatically manage the state of + * this clock. If the device is enabled, then the clock is enabled. + */ + ret = cops->put_clock(sci, clk->id, clk->data); + if (ret) + dev_err(clk->dev, "%s: put_clock failed (%d)\n", __func__, ret); + + return ret; +} + +static int ti_sci_clk_disable(struct clk *clk) +{ + struct ti_sci_clk_data *data = dev_get_priv(clk->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_clk_ops *cops = &sci->ops.clk_ops; + int ret; + + debug("%s(clk=%p)\n", __func__, clk); + + /* Unconditionally disable clock, regardless of state of the device */ + ret = cops->idle_clock(sci, clk->id, clk->data); + if (ret) + dev_err(clk->dev, "%s: idle_clock failed (%d)\n", __func__, + ret); + + return ret; +} + +static const struct udevice_id ti_sci_clk_of_match[] = { + { .compatible = "ti,k2g-sci-clk" }, + { /* sentinel */ }, +}; + +static struct clk_ops ti_sci_clk_ops = { + .of_xlate = ti_sci_clk_of_xlate, + .request = ti_sci_clk_request, + .free = ti_sci_clk_free, + .get_rate = ti_sci_clk_get_rate, + .set_rate = ti_sci_clk_set_rate, + .set_parent = ti_sci_clk_set_parent, + .enable = ti_sci_clk_enable, + .disable = ti_sci_clk_disable, +}; + +U_BOOT_DRIVER(ti_sci_clk) = { + .name = "ti-sci-clk", + .id = UCLASS_CLK, + .of_match = ti_sci_clk_of_match, + .probe = ti_sci_clk_probe, + .priv_auto_alloc_size = sizeof(struct ti_sci_clk_data), + .ops = &ti_sci_clk_ops, +}; diff --git a/drivers/clk/clk_meson.c b/drivers/clk/clk_meson.c index 3850128e5c..236d7342b7 100644 --- a/drivers/clk/clk_meson.c +++ b/drivers/clk/clk_meson.c @@ -14,12 +14,69 @@ #include <dt-bindings/clock/gxbb-clkc.h> #include "clk_meson.h" +/* This driver support only basic clock tree operations : + * - Can calculate clock frequency on a limited tree + * - Can Read muxes and basic dividers (0-based only) + * - Can enable/disable gates with limited propagation + * - Can reparent without propagation, only on muxes + * - Can set rates without reparenting + * This driver is adapted to what is actually supported by U-Boot + */ + +/* Only the clocks ids we don't want to expose, such as the internal muxes + * and dividers of composite clocks, will remain defined here. + */ +#define CLKID_MPEG_SEL 10 +#define CLKID_MPEG_DIV 11 +#define CLKID_SAR_ADC_DIV 99 +#define CLKID_MALI_0_DIV 101 +#define CLKID_MALI_1_DIV 104 +#define CLKID_CTS_AMCLK_SEL 108 +#define CLKID_CTS_AMCLK_DIV 109 +#define CLKID_CTS_MCLK_I958_SEL 111 +#define CLKID_CTS_MCLK_I958_DIV 112 +#define CLKID_32K_CLK_SEL 115 +#define CLKID_32K_CLK_DIV 116 +#define CLKID_SD_EMMC_A_CLK0_SEL 117 +#define CLKID_SD_EMMC_A_CLK0_DIV 118 +#define CLKID_SD_EMMC_B_CLK0_SEL 120 +#define CLKID_SD_EMMC_B_CLK0_DIV 121 +#define CLKID_SD_EMMC_C_CLK0_SEL 123 +#define CLKID_SD_EMMC_C_CLK0_DIV 124 +#define CLKID_VPU_0_DIV 127 +#define CLKID_VPU_1_DIV 130 +#define CLKID_VAPB_0_DIV 134 +#define CLKID_VAPB_1_DIV 137 +#define CLKID_HDMI_PLL_PRE_MULT 141 +#define CLKID_MPLL0_DIV 142 +#define CLKID_MPLL1_DIV 143 +#define CLKID_MPLL2_DIV 144 +#define CLKID_MPLL_PREDIV 145 +#define CLKID_FCLK_DIV2_DIV 146 +#define CLKID_FCLK_DIV3_DIV 147 +#define CLKID_FCLK_DIV4_DIV 148 +#define CLKID_FCLK_DIV5_DIV 149 +#define CLKID_FCLK_DIV7_DIV 150 +#define CLKID_VDEC_1_SEL 151 +#define CLKID_VDEC_1_DIV 152 +#define CLKID_VDEC_HEVC_SEL 154 +#define CLKID_VDEC_HEVC_DIV 155 + #define XTAL_RATE 24000000 struct meson_clk { void __iomem *addr; }; +static ulong meson_div_get_rate(struct clk *clk, unsigned long id); +static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, + ulong current_rate); +static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, + unsigned long parent_id); +static ulong meson_mux_get_rate(struct clk *clk, unsigned long id); +static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, + ulong rate, ulong current_rate); +static ulong meson_mux_get_parent(struct clk *clk, unsigned long id); static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id); struct meson_gate gates[] = { @@ -126,34 +183,387 @@ struct meson_gate gates[] = { MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7), MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23), MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7), + MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8), + MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24), + MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8), + MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24), + MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30), }; -static int meson_set_gate(struct clk *clk, bool on) +static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on) { struct meson_clk *priv = dev_get_priv(clk->dev); struct meson_gate *gate; - if (clk->id >= ARRAY_SIZE(gates)) + debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id); + + /* Propagate through muxes */ + switch (id) { + case CLKID_VPU: + return meson_set_gate_by_id(clk, + meson_mux_get_parent(clk, CLKID_VPU), on); + case CLKID_VAPB_SEL: + return meson_set_gate_by_id(clk, + meson_mux_get_parent(clk, CLKID_VAPB_SEL), on); + } + + if (id >= ARRAY_SIZE(gates)) return -ENOENT; - gate = &gates[clk->id]; + gate = &gates[id]; if (gate->reg == 0) return 0; + debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id); + clrsetbits_le32(priv->addr + gate->reg, BIT(gate->bit), on ? BIT(gate->bit) : 0); + + /* Propagate to next gate(s) */ + switch (id) { + case CLKID_VAPB: + return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on); + } + return 0; } static int meson_clk_enable(struct clk *clk) { - return meson_set_gate(clk, true); + return meson_set_gate_by_id(clk, clk->id, true); } static int meson_clk_disable(struct clk *clk) { - return meson_set_gate(clk, false); + return meson_set_gate_by_id(clk, clk->id, false); +} + +static struct parm meson_vpu_0_div_parm = { + HHI_VPU_CLK_CNTL, 0, 7, +}; + +int meson_vpu_0_div_parent = CLKID_VPU_0_SEL; + +static struct parm meson_vpu_1_div_parm = { + HHI_VPU_CLK_CNTL, 16, 7, +}; + +int meson_vpu_1_div_parent = CLKID_VPU_1_SEL; + +static struct parm meson_vapb_0_div_parm = { + HHI_VAPBCLK_CNTL, 0, 7, +}; + +int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL; + +static struct parm meson_vapb_1_div_parm = { + HHI_VAPBCLK_CNTL, 16, 7, +}; + +int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL; + +static ulong meson_div_get_rate(struct clk *clk, unsigned long id) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + unsigned int rate, parent_rate; + struct parm *parm; + int parent; + u32 reg; + + switch (id) { + case CLKID_VPU_0_DIV: + parm = &meson_vpu_0_div_parm; + parent = meson_vpu_0_div_parent; + break; + case CLKID_VPU_1_DIV: + parm = &meson_vpu_1_div_parm; + parent = meson_vpu_1_div_parent; + break; + case CLKID_VAPB_0_DIV: + parm = &meson_vapb_0_div_parm; + parent = meson_vapb_0_div_parent; + break; + case CLKID_VAPB_1_DIV: + parm = &meson_vapb_1_div_parm; + parent = meson_vapb_1_div_parent; + break; + default: + return -ENOENT; + } + + reg = readl(priv->addr + parm->reg_off); + reg = PARM_GET(parm->width, parm->shift, reg); + + debug("%s: div of %ld is %d\n", __func__, id, reg + 1); + + parent_rate = meson_clk_get_rate_by_id(clk, parent); + if (IS_ERR_VALUE(parent_rate)) + return parent_rate; + + debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate); + + rate = parent_rate / (reg + 1); + + debug("%s: rate of %ld is %d\n", __func__, id, rate); + + return rate; +} + +static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate, + ulong current_rate) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + unsigned int new_div = -EINVAL; + unsigned long parent_rate; + struct parm *parm; + int parent; + u32 reg; + int ret; + + if (current_rate == rate) + return 0; + + debug("%s: setting rate of %ld from %ld to %ld\n", + __func__, id, current_rate, rate); + + switch (id) { + case CLKID_VPU_0_DIV: + parm = &meson_vpu_0_div_parm; + parent = meson_vpu_0_div_parent; + break; + case CLKID_VPU_1_DIV: + parm = &meson_vpu_1_div_parm; + parent = meson_vpu_1_div_parent; + break; + case CLKID_VAPB_0_DIV: + parm = &meson_vapb_0_div_parm; + parent = meson_vapb_0_div_parent; + break; + case CLKID_VAPB_1_DIV: + parm = &meson_vapb_1_div_parm; + parent = meson_vapb_1_div_parent; + break; + default: + return -ENOENT; + } + + parent_rate = meson_clk_get_rate_by_id(clk, parent); + if (IS_ERR_VALUE(parent_rate)) + return parent_rate; + + debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate); + + /* If can't divide, set parent instead */ + if (!parent_rate || rate > parent_rate) + return meson_clk_set_rate_by_id(clk, parent, rate, + current_rate); + + new_div = DIV_ROUND_CLOSEST(parent_rate, rate); + + debug("%s: new div of %ld is %d\n", __func__, id, new_div); + + /* If overflow, try to set parent rate and retry */ + if (!new_div || new_div > (1 << parm->width)) { + ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate); + if (IS_ERR_VALUE(ret)) + return ret; + + parent_rate = meson_clk_get_rate_by_id(clk, parent); + if (IS_ERR_VALUE(parent_rate)) + return parent_rate; + + new_div = DIV_ROUND_CLOSEST(parent_rate, rate); + + debug("%s: new new div of %ld is %d\n", __func__, id, new_div); + + if (!new_div || new_div > (1 << parm->width)) + return -EINVAL; + } + + debug("%s: setting div of %ld to %d\n", __func__, id, new_div); + + reg = readl(priv->addr + parm->reg_off); + writel(PARM_SET(parm->width, parm->shift, reg, new_div - 1), + priv->addr + parm->reg_off); + + debug("%s: new rate of %ld is %ld\n", + __func__, id, meson_div_get_rate(clk, id)); + + return 0; +} + +static struct parm meson_vpu_mux_parm = { + HHI_VPU_CLK_CNTL, 31, 1, +}; + +int meson_vpu_mux_parents[] = { + CLKID_VPU_0, + CLKID_VPU_1, +}; + +static struct parm meson_vpu_0_mux_parm = { + HHI_VPU_CLK_CNTL, 9, 2, +}; + +static struct parm meson_vpu_1_mux_parm = { + HHI_VPU_CLK_CNTL, 25, 2, +}; + +static int meson_vpu_0_1_mux_parents[] = { + CLKID_FCLK_DIV4, + CLKID_FCLK_DIV3, + CLKID_FCLK_DIV5, + CLKID_FCLK_DIV7, +}; + +static struct parm meson_vapb_sel_mux_parm = { + HHI_VAPBCLK_CNTL, 31, 1, +}; + +int meson_vapb_sel_mux_parents[] = { + CLKID_VAPB_0, + CLKID_VAPB_1, +}; + +static struct parm meson_vapb_0_mux_parm = { + HHI_VAPBCLK_CNTL, 9, 2, +}; + +static struct parm meson_vapb_1_mux_parm = { + HHI_VAPBCLK_CNTL, 25, 2, +}; + +static int meson_vapb_0_1_mux_parents[] = { + CLKID_FCLK_DIV4, + CLKID_FCLK_DIV3, + CLKID_FCLK_DIV5, + CLKID_FCLK_DIV7, +}; + +static ulong meson_mux_get_parent(struct clk *clk, unsigned long id) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + struct parm *parm; + int *parents; + u32 reg; + + switch (id) { + case CLKID_VPU: + parm = &meson_vpu_mux_parm; + parents = meson_vpu_mux_parents; + break; + case CLKID_VPU_0_SEL: + parm = &meson_vpu_0_mux_parm; + parents = meson_vpu_0_1_mux_parents; + break; + case CLKID_VPU_1_SEL: + parm = &meson_vpu_1_mux_parm; + parents = meson_vpu_0_1_mux_parents; + break; + case CLKID_VAPB_SEL: + parm = &meson_vapb_sel_mux_parm; + parents = meson_vapb_sel_mux_parents; + break; + case CLKID_VAPB_0_SEL: + parm = &meson_vapb_0_mux_parm; + parents = meson_vapb_0_1_mux_parents; + break; + case CLKID_VAPB_1_SEL: + parm = &meson_vapb_1_mux_parm; + parents = meson_vapb_0_1_mux_parents; + break; + default: + return -ENOENT; + } + + reg = readl(priv->addr + parm->reg_off); + reg = PARM_GET(parm->width, parm->shift, reg); + + debug("%s: parent of %ld is %d (%d)\n", + __func__, id, parents[reg], reg); + + return parents[reg]; +} + +static ulong meson_mux_set_parent(struct clk *clk, unsigned long id, + unsigned long parent_id) +{ + unsigned long cur_parent = meson_mux_get_parent(clk, id); + struct meson_clk *priv = dev_get_priv(clk->dev); + unsigned int new_index = -EINVAL; + struct parm *parm; + int *parents; + u32 reg; + int i; + + if (IS_ERR_VALUE(cur_parent)) + return cur_parent; + + debug("%s: setting parent of %ld from %ld to %ld\n", + __func__, id, cur_parent, parent_id); + + if (cur_parent == parent_id) + return 0; + + switch (id) { + case CLKID_VPU: + parm = &meson_vpu_mux_parm; + parents = meson_vpu_mux_parents; + break; + case CLKID_VPU_0_SEL: + parm = &meson_vpu_0_mux_parm; + parents = meson_vpu_0_1_mux_parents; + break; + case CLKID_VPU_1_SEL: + parm = &meson_vpu_1_mux_parm; + parents = meson_vpu_0_1_mux_parents; + break; + case CLKID_VAPB_SEL: + parm = &meson_vapb_sel_mux_parm; + parents = meson_vapb_sel_mux_parents; + break; + case CLKID_VAPB_0_SEL: + parm = &meson_vapb_0_mux_parm; + parents = meson_vapb_0_1_mux_parents; + break; + case CLKID_VAPB_1_SEL: + parm = &meson_vapb_1_mux_parm; + parents = meson_vapb_0_1_mux_parents; + break; + default: + /* Not a mux */ + return -ENOENT; + } + + for (i = 0 ; i < (1 << parm->width) ; ++i) { + if (parents[i] == parent_id) + new_index = i; + } + + if (IS_ERR_VALUE(new_index)) + return new_index; + + debug("%s: new index of %ld is %d\n", __func__, id, new_index); + + reg = readl(priv->addr + parm->reg_off); + writel(PARM_SET(parm->width, parm->shift, reg, new_index), + priv->addr + parm->reg_off); + + debug("%s: new parent of %ld is %ld\n", + __func__, id, meson_mux_get_parent(clk, id)); + + return 0; +} + +static ulong meson_mux_get_rate(struct clk *clk, unsigned long id) +{ + int parent = meson_mux_get_parent(clk, id); + + if (IS_ERR_VALUE(parent)) + return parent; + + return meson_clk_get_rate_by_id(clk, parent); } static unsigned long meson_clk81_get_rate(struct clk *clk) @@ -342,6 +752,35 @@ static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id) case CLKID_CLK81: rate = meson_clk81_get_rate(clk); break; + case CLKID_VPU_0: + rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV); + break; + case CLKID_VPU_1: + rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV); + break; + case CLKID_VAPB: + rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL); + break; + case CLKID_VAPB_0: + rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV); + break; + case CLKID_VAPB_1: + rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV); + break; + case CLKID_VPU_0_DIV: + case CLKID_VPU_1_DIV: + case CLKID_VAPB_0_DIV: + case CLKID_VAPB_1_DIV: + rate = meson_div_get_rate(clk, id); + break; + case CLKID_VPU: + case CLKID_VPU_0_SEL: + case CLKID_VPU_1_SEL: + case CLKID_VAPB_SEL: + case CLKID_VAPB_0_SEL: + case CLKID_VAPB_1_SEL: + rate = meson_mux_get_rate(clk, id); + break; default: if (gates[id].reg != 0) { /* a clock gate */ @@ -360,6 +799,88 @@ static ulong meson_clk_get_rate(struct clk *clk) return meson_clk_get_rate_by_id(clk, clk->id); } +static int meson_clk_set_parent(struct clk *clk, struct clk *parent) +{ + return meson_mux_set_parent(clk, clk->id, parent->id); +} + +static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id, + ulong rate, ulong current_rate) +{ + if (current_rate == rate) + return 0; + + switch (id) { + /* Fixed clocks */ + case CLKID_FIXED_PLL: + case CLKID_SYS_PLL: + case CLKID_FCLK_DIV2: + case CLKID_FCLK_DIV3: + case CLKID_FCLK_DIV4: + case CLKID_FCLK_DIV5: + case CLKID_FCLK_DIV7: + case CLKID_MPLL0: + case CLKID_MPLL1: + case CLKID_MPLL2: + case CLKID_CLK81: + if (current_rate != rate) + return -EINVAL; + + return 0; + case CLKID_VPU: + return meson_clk_set_rate_by_id(clk, + meson_mux_get_parent(clk, CLKID_VPU), rate, + current_rate); + case CLKID_VAPB: + case CLKID_VAPB_SEL: + return meson_clk_set_rate_by_id(clk, + meson_mux_get_parent(clk, CLKID_VAPB_SEL), + rate, current_rate); + case CLKID_VPU_0: + return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate, + current_rate); + case CLKID_VPU_1: + return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate, + current_rate); + case CLKID_VAPB_0: + return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate, + current_rate); + case CLKID_VAPB_1: + return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate, + current_rate); + case CLKID_VPU_0_DIV: + case CLKID_VPU_1_DIV: + case CLKID_VAPB_0_DIV: + case CLKID_VAPB_1_DIV: + return meson_div_set_rate(clk, id, rate, current_rate); + default: + return -ENOENT; + } + + return -EINVAL; +} + +static ulong meson_clk_set_rate(struct clk *clk, ulong rate) +{ + ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id); + int ret; + + if (IS_ERR_VALUE(current_rate)) + return current_rate; + + debug("%s: setting rate of %ld from %ld to %ld\n", + __func__, clk->id, current_rate, rate); + + ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate); + if (IS_ERR_VALUE(ret)) + return ret; + + printf("clock %lu has new rate %lu\n", clk->id, + meson_clk_get_rate_by_id(clk, clk->id)); + + return 0; +} + static int meson_clk_probe(struct udevice *dev) { struct meson_clk *priv = dev_get_priv(dev); @@ -375,6 +896,8 @@ static struct clk_ops meson_clk_ops = { .disable = meson_clk_disable, .enable = meson_clk_enable, .get_rate = meson_clk_get_rate, + .set_parent = meson_clk_set_parent, + .set_rate = meson_clk_set_rate, }; static const struct udevice_id meson_clk_ids[] = { diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 4c32426e0e..cb73b70f5b 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -4,3 +4,16 @@ config FIRMWARE config ARM_PSCI_FW bool select FIRMWARE + +config TI_SCI_PROTOCOL + tristate "TI System Control Interface (TISCI) Message Protocol" + depends on K3_SEC_PROXY + select FIRMWARE + help + TI System Control Interface (TISCI) Message Protocol is used to manage + compute systems such as ARM, DSP etc with the system controller in + complex System on Chip (SoC) such as those found on certain K3 + generation SoC from TI. + + This protocol library is used by client drivers to use the features + provided by the system controller. diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index b208255368..1cdda14977 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FIRMWARE) += firmware-uclass.o obj-$(CONFIG_ARM_PSCI_FW) += psci.o +obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o diff --git a/drivers/firmware/firmware-uclass.c b/drivers/firmware/firmware-uclass.c index d09923595b..3d33b6deba 100644 --- a/drivers/firmware/firmware-uclass.c +++ b/drivers/firmware/firmware-uclass.c @@ -7,4 +7,7 @@ UCLASS_DRIVER(firmware) = { .id = UCLASS_FIRMWARE, .name = "firmware", +#if CONFIG_IS_ENABLED(OF_CONTROL) + .post_bind = dm_scan_fdt_dev, +#endif }; diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c new file mode 100644 index 0000000000..9148126041 --- /dev/null +++ b/drivers/firmware/ti_sci.c @@ -0,0 +1,2033 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments System Control Interface Protocol Driver + * Based on drivers/firmware/ti_sci.c from Linux. + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <mailbox.h> +#include <dm/device.h> +#include <linux/err.h> +#include <linux/soc/ti/k3-sec-proxy.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +#include "ti_sci.h" + +/* List of all TI SCI devices active in system */ +static LIST_HEAD(ti_sci_list); + +/** + * struct ti_sci_xfer - Structure representing a message flow + * @tx_message: Transmit message + * @rx_len: Receive message length + */ +struct ti_sci_xfer { + struct k3_sec_proxy_msg tx_message; + u8 rx_len; +}; + +/** + * struct ti_sci_desc - Description of SoC integration + * @host_id: Host identifier representing the compute entity + * @max_rx_timeout_us: Timeout for communication with SoC (in Microseconds) + * @max_msg_size: Maximum size of data per message that can be handled. + */ +struct ti_sci_desc { + u8 host_id; + int max_rx_timeout_us; + int max_msg_size; +}; + +/** + * struct ti_sci_info - Structure representing a TI SCI instance + * @dev: Device pointer + * @desc: SoC description for this instance + * @handle: Instance of TI SCI handle to send to clients. + * @chan_tx: Transmit mailbox channel + * @chan_rx: Receive mailbox channel + * @xfer: xfer info + * @list: list head + * @is_secure: Determines if the communication is through secure threads. + * @host_id: Host identifier representing the compute entity + * @seq: Seq id used for verification for tx and rx message. + */ +struct ti_sci_info { + struct udevice *dev; + const struct ti_sci_desc *desc; + struct ti_sci_handle handle; + struct mbox_chan chan_tx; + struct mbox_chan chan_rx; + struct mbox_chan chan_notify; + struct ti_sci_xfer xfer; + struct list_head list; + bool is_secure; + u8 host_id; + u8 seq; +}; + +#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle) + +/** + * ti_sci_setup_one_xfer() - Setup one message type + * @info: Pointer to SCI entity information + * @msg_type: Message type + * @msg_flags: Flag to set for the message + * @buf: Buffer to be send to mailbox channel + * @tx_message_size: transmit message size + * @rx_message_size: receive message size + * + * Helper function which is used by various command functions that are + * exposed to clients of this driver for allocating a message traffic event. + * + * Return: Corresponding ti_sci_xfer pointer if all went fine, + * else appropriate error pointer. + */ +static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info, + u16 msg_type, u32 msg_flags, + u32 *buf, + size_t tx_message_size, + size_t rx_message_size) +{ + struct ti_sci_xfer *xfer = &info->xfer; + struct ti_sci_msg_hdr *hdr; + + /* Ensure we have sane transfer sizes */ + if (rx_message_size > info->desc->max_msg_size || + tx_message_size > info->desc->max_msg_size || + rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr)) + return ERR_PTR(-ERANGE); + + info->seq = ~info->seq; + xfer->tx_message.buf = buf; + xfer->tx_message.len = tx_message_size; + xfer->rx_len = (u8)rx_message_size; + + hdr = (struct ti_sci_msg_hdr *)buf; + hdr->seq = info->seq; + hdr->type = msg_type; + hdr->host = info->host_id; + hdr->flags = msg_flags; + + return xfer; +} + +/** + * ti_sci_get_response() - Receive response from mailbox channel + * @info: Pointer to SCI entity information + * @xfer: Transfer to initiate and wait for response + * @chan: Channel to receive the response + * + * Return: -ETIMEDOUT in case of no response, if transmit error, + * return corresponding error, else if all goes well, + * return 0. + */ +static inline int ti_sci_get_response(struct ti_sci_info *info, + struct ti_sci_xfer *xfer, + struct mbox_chan *chan) +{ + struct k3_sec_proxy_msg *msg = &xfer->tx_message; + struct ti_sci_secure_msg_hdr *secure_hdr; + struct ti_sci_msg_hdr *hdr; + int ret; + + /* Receive the response */ + ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us); + if (ret) { + dev_err(info->dev, "%s: Message receive failed. ret = %d\n", + __func__, ret); + return ret; + } + + /* ToDo: Verify checksum */ + if (info->is_secure) { + secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf; + msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr)); + } + + /* msg is updated by mailbox driver */ + hdr = (struct ti_sci_msg_hdr *)msg->buf; + + /* Sanity check for message response */ + if (hdr->seq != info->seq) { + dev_dbg(info->dev, "%s: Message for %d is not expected\n", + __func__, hdr->seq); + return ret; + } + + if (msg->len > info->desc->max_msg_size) { + dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n", + __func__, msg->len, info->desc->max_msg_size); + return -EINVAL; + } + + if (msg->len < xfer->rx_len) { + dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n", + __func__, msg->len, xfer->rx_len); + } + + return ret; +} + +/** + * ti_sci_do_xfer() - Do one transfer + * @info: Pointer to SCI entity information + * @xfer: Transfer to initiate and wait for response + * + * Return: 0 if all went fine, else return appropriate error. + */ +static inline int ti_sci_do_xfer(struct ti_sci_info *info, + struct ti_sci_xfer *xfer) +{ + struct k3_sec_proxy_msg *msg = &xfer->tx_message; + u8 secure_buf[info->desc->max_msg_size]; + struct ti_sci_secure_msg_hdr secure_hdr; + int ret; + + if (info->is_secure) { + /* ToDo: get checksum of the entire message */ + secure_hdr.checksum = 0; + secure_hdr.reserved = 0; + memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf, + xfer->tx_message.len); + + xfer->tx_message.buf = (u32 *)secure_buf; + xfer->tx_message.len += sizeof(secure_hdr); + xfer->rx_len += sizeof(secure_hdr); + } + + /* Send the message */ + ret = mbox_send(&info->chan_tx, msg); + if (ret) { + dev_err(info->dev, "%s: Message sending failed. ret = %d\n", + __func__, ret); + return ret; + } + + return ti_sci_get_response(info, xfer, &info->chan_rx); +} + +/** + * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity + * @handle: pointer to TI SCI handle + * + * Updates the SCI information in the internal data structure. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle) +{ + struct ti_sci_msg_resp_version *rev_info; + struct ti_sci_version_info *ver; + struct ti_sci_msg_hdr hdr; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0, + (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr), + sizeof(*rev_info)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox communication fail %d\n", ret); + return ret; + } + + rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf; + + ver = &handle->version; + ver->abi_major = rev_info->abi_major; + ver->abi_minor = rev_info->abi_minor; + ver->firmware_revision = rev_info->firmware_revision; + strncpy(ver->firmware_description, rev_info->firmware_description, + sizeof(ver->firmware_description)); + + return 0; +} + +/** + * ti_sci_is_response_ack() - Generic ACK/NACK message checkup + * @r: pointer to response buffer + * + * Return: true if the response was an ACK, else returns false. + */ +static inline bool ti_sci_is_response_ack(void *r) +{ + struct ti_sci_msg_hdr *hdr = r; + + return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false; +} + +/** + * cmd_set_board_config_using_msg() - Common command to send board configuration + * message + * @handle: pointer to TI SCI handle + * @msg_type: One of the TISCI message types to set board configuration + * @addr: Address where the board config structure is located + * @size: Size of the board config structure + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle, + u16 msg_type, u64 addr, u32 size) +{ + struct ti_sci_msg_board_config req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, msg_type, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.boardcfgp_high = (addr >> 32) & 0xffffffff; + req.boardcfgp_low = addr & 0xffffffff; + req.boardcfg_size = size; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_set_board_config() - Command to send board configuration message + * @handle: pointer to TI SCI handle + * @addr: Address where the board config structure is located + * @size: Size of the board config structure + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle, + u64 addr, u32 size) +{ + return cmd_set_board_config_using_msg(handle, + TI_SCI_MSG_BOARD_CONFIG, + addr, size); +} + +/** + * ti_sci_cmd_set_board_config_rm() - Command to send board resource + * management configuration + * @handle: pointer to TI SCI handle + * @addr: Address where the board RM config structure is located + * @size: Size of the RM config structure + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static +int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle, + u64 addr, u32 size) +{ + return cmd_set_board_config_using_msg(handle, + TI_SCI_MSG_BOARD_CONFIG_RM, + addr, size); +} + +/** + * ti_sci_cmd_set_board_config_security() - Command to send board security + * configuration message + * @handle: pointer to TI SCI handle + * @addr: Address where the board security config structure is located + * @size: Size of the security config structure + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static +int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle, + u64 addr, u32 size) +{ + return cmd_set_board_config_using_msg(handle, + TI_SCI_MSG_BOARD_CONFIG_SECURITY, + addr, size); +} + +/** + * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock + * configuration message + * @handle: pointer to TI SCI handle + * @addr: Address where the board PM config structure is located + * @size: Size of the PM config structure + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle, + u64 addr, u32 size) +{ + return cmd_set_board_config_using_msg(handle, + TI_SCI_MSG_BOARD_CONFIG_PM, + addr, size); +} + +/** + * ti_sci_set_device_state() - Set device state helper + * @handle: pointer to TI SCI handle + * @id: Device identifier + * @flags: flags to setup for the device + * @state: State to move the device to + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_set_device_state(const struct ti_sci_handle *handle, + u32 id, u32 flags, u8 state) +{ + struct ti_sci_msg_req_set_device_state req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE, + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.id = id; + req.state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_get_device_state() - Get device state helper + * @handle: Handle to the device + * @id: Device Identifier + * @clcnt: Pointer to Context Loss Count + * @resets: pointer to resets + * @p_state: pointer to p_state + * @c_state: pointer to c_state + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_get_device_state(const struct ti_sci_handle *handle, + u32 id, u32 *clcnt, u32 *resets, + u8 *p_state, u8 *c_state) +{ + struct ti_sci_msg_resp_get_device_state *resp; + struct ti_sci_msg_req_get_device_state req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + if (!clcnt && !resets && !p_state && !c_state) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + /* Response is expected, so need of any flags */ + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, 0, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.id = id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf; + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + if (clcnt) + *clcnt = resp->context_loss_count; + if (resets) + *resets = resp->resets; + if (p_state) + *p_state = resp->programmed_state; + if (c_state) + *c_state = resp->current_state; + + return ret; +} + +/** + * ti_sci_cmd_get_device() - command to request for device managed by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * NOTE: The request is for exclusive access for the processor. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id) +{ + return ti_sci_set_device_state(handle, id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_ON); +} + +/** + * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id) +{ + return ti_sci_set_device_state(handle, id, + MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_RETENTION); +} + +/** + * ti_sci_cmd_put_device() - command to release a device managed by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id) +{ + return ti_sci_set_device_state(handle, id, + 0, MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +/** + * ti_sci_cmd_dev_is_valid() - Is the device valid + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * + * Return: 0 if all went fine and the device ID is valid, else return + * appropriate error. + */ +static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id) +{ + u8 unused; + + /* check the device state which will also tell us if the ID is valid */ + return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused); +} + +/** + * ti_sci_cmd_dev_get_clcnt() - Get context loss counter + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @count: Pointer to Context Loss counter to populate + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id, + u32 *count) +{ + return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL); +} + +/** + * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @r_state: true if requested to be idle + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id, + bool *r_state) +{ + int ret; + u8 state; + + if (!r_state) + return -EINVAL; + + ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL); + if (ret) + return ret; + + *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); + + return 0; +} + +/** + * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @r_state: true if requested to be stopped + * @curr_state: true if currently stopped. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id, + bool *r_state, bool *curr_state) +{ + int ret; + u8 p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = + ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); + + return 0; +} + +/** + * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @r_state: true if requested to be ON + * @curr_state: true if currently ON and active + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id, + bool *r_state, bool *curr_state) +{ + int ret; + u8 p_state, c_state; + + if (!r_state && !curr_state) + return -EINVAL; + + ret = + ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state); + if (ret) + return ret; + + if (r_state) + *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); + if (curr_state) + *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); + + return 0; +} + +/** + * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @curr_state: true if currently transitioning. + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id, + bool *curr_state) +{ + int ret; + u8 state; + + if (!curr_state) + return -EINVAL; + + ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state); + if (ret) + return ret; + + *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); + + return 0; +} + +/** + * ti_sci_cmd_set_device_resets() - command to set resets for device managed + * by TISCI + * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * @id: Device Identifier + * @reset_state: Device specific reset bit field + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle, + u32 id, u32 reset_state) +{ + struct ti_sci_msg_req_set_device_resets req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.id = id; + req.resets = reset_state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_get_device_resets() - Get reset state for device managed + * by TISCI + * @handle: Pointer to TISCI handle + * @id: Device Identifier + * @reset_state: Pointer to reset state to populate + * + * Return: 0 if all went fine, else return appropriate error. + */ +static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle, + u32 id, u32 *reset_state) +{ + return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL, + NULL); +} + +/** + * ti_sci_set_clock_state() - Set clock state helper + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @flags: Header flags as needed + * @state: State to request for the clock. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_set_clock_state(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, + u32 flags, u8 state) +{ + struct ti_sci_msg_req_set_clock_state req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE, + flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + req.request_state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_get_clock_state() - Get clock state helper + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @programmed_state: State requested for clock to move to + * @current_state: State that the clock is currently in + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, + u8 *programmed_state, u8 *current_state) +{ + struct ti_sci_msg_resp_get_clock_state *resp; + struct ti_sci_msg_req_get_clock_state req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + if (!programmed_state && !current_state) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + if (programmed_state) + *programmed_state = resp->programmed_state; + if (current_state) + *current_state = resp->current_state; + + return ret; +} + +/** + * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false' + * @can_change_freq: 'true' if frequency change is desired, else 'false' + * @enable_input_term: 'true' if input termination is desired, else 'false' + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id, + u8 clk_id, bool needs_ssc, bool can_change_freq, + bool enable_input_term) +{ + u32 flags = 0; + + flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; + flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; + flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; + + return ti_sci_set_clock_state(handle, dev_id, clk_id, flags, + MSG_CLOCK_SW_STATE_REQ); +} + +/** + * ti_sci_cmd_idle_clock() - Idle a clock which is in our control + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id) +{ + return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_UNREQ); +} + +/** + * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * + * NOTE: This clock must have been requested by get_clock previously. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id) +{ + return ti_sci_set_clock_state(handle, dev_id, clk_id, 0, + MSG_CLOCK_SW_STATE_AUTO); +} + +/** + * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is auto managed + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, bool *req_state) +{ + u8 state = 0; + int ret; + + if (!req_state) + return -EINVAL; + + ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL); + if (ret) + return ret; + + *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); + return 0; +} + +/** + * ti_sci_cmd_clk_is_on() - Is the clock ON + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and enabled + * @curr_state: state indicating if the clock is ready for operation + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id, + u8 clk_id, bool *req_state, bool *curr_state) +{ + u8 c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, + &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); + return 0; +} + +/** + * ti_sci_cmd_clk_is_off() - Is the clock OFF + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @req_state: state indicating if the clock is managed by us and disabled + * @curr_state: state indicating if the clock is NOT ready for operation + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id, + u8 clk_id, bool *req_state, bool *curr_state) +{ + u8 c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) + return -EINVAL; + + ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, + &r_state, &c_state); + if (ret) + return ret; + + if (req_state) + *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); + if (curr_state) + *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); + return 0; +} + +/** + * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Parent clock identifier to set + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u8 parent_id) +{ + struct ti_sci_msg_req_set_clock_parent req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + req.parent_id = parent_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_clk_get_parent() - Get current parent clock source + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: Current clock parent + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u8 *parent_id) +{ + struct ti_sci_msg_resp_get_clock_parent *resp; + struct ti_sci_msg_req_get_clock_parent req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !parent_id) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *parent_id = resp->parent_id; + + return ret; +} + +/** + * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @num_parents: Returns he number of parents to the current clock. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, + u8 *num_parents) +{ + struct ti_sci_msg_resp_get_clock_num_parents *resp; + struct ti_sci_msg_req_get_clock_num_parents req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !num_parents) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_get_clock_num_parents *) + xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *num_parents = resp->num_parents; + + return ret; +} + +/** + * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @match_freq: Frequency match in Hz response. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u64 min_freq, + u64 target_freq, u64 max_freq, + u64 *match_freq) +{ + struct ti_sci_msg_resp_query_clock_freq *resp; + struct ti_sci_msg_req_query_clock_freq req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !match_freq) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *match_freq = resp->freq_hz; + + return ret; +} + +/** + * ti_sci_cmd_clk_set_freq() - Set a frequency for clock + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * @max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u64 min_freq, + u64 target_freq, u64 max_freq) +{ + struct ti_sci_msg_req_set_clock_freq req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_clk_get_freq() - Get current frequency + * @handle: pointer to TI SCI handle + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @freq: Currently frequency in Hz + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle, + u32 dev_id, u8 clk_id, u64 *freq) +{ + struct ti_sci_msg_resp_get_clock_freq *resp; + struct ti_sci_msg_req_get_clock_freq req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle || !freq) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + else + *freq = resp->freq_hz; + + return ret; +} + +/** + * ti_sci_cmd_core_reboot() - Command to request system reset + * @handle: pointer to TI SCI handle + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) +{ + struct ti_sci_msg_req_reboot req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SYS_RESET, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_proc_request() - Command to request a physical processor control + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle, + u8 proc_id) +{ + struct ti_sci_msg_req_proc_request req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_REQUEST, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_proc_release() - Command to release a physical processor control + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle, + u8 proc_id) +{ + struct ti_sci_msg_req_proc_release req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_RELEASE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_proc_handover() - Command to handover a physical processor + * control to a host in the processor's access + * control list. + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @host_id: Host ID to get the control of the processor + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle, + u8 proc_id, u8 host_id) +{ + struct ti_sci_msg_req_proc_handover req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_HANDOVER, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + req.host_id = host_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_set_proc_boot_cfg() - Command to set the processor boot + * configuration flags + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @config_flags_set: Configuration flags to be set + * @config_flags_clear: Configuration flags to be cleared. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle *handle, + u8 proc_id, u64 bootvector, + u32 config_flags_set, + u32 config_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_config req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CONFIG, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; + req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + req.config_flags_set = config_flags_set; + req.config_flags_clear = config_flags_clear; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_set_proc_boot_ctrl() - Command to set the processor boot + * control flags + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @control_flags_set: Control flags to be set + * @control_flags_clear: Control flags to be cleared + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle, + u8 proc_id, u32 control_flags_set, + u32 control_flags_clear) +{ + struct ti_sci_msg_req_set_proc_boot_ctrl req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CTRL, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + req.control_flags_set = control_flags_set; + req.control_flags_clear = control_flags_clear; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the + * image and then set the processor configuration flags. + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * @cert_addr: Memory address at which payload image certificate is located. + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle, + u8 proc_id, u64 cert_addr) +{ + struct ti_sci_msg_req_proc_auth_boot_image req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMIAGE, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK; + req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >> + TISCI_ADDR_HIGH_SHIFT; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + + return ret; +} + +/** + * ti_sci_cmd_get_proc_boot_status() - Command to get the processor boot status + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle, + u8 proc_id, u64 *bv, u32 *cfg_flags, + u32 *ctrl_flags, u32 *sts_flags) +{ + struct ti_sci_msg_resp_get_proc_boot_status *resp; + struct ti_sci_msg_req_get_proc_boot_status req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_GET_PROC_BOOT_STATUS, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + (u32 *)&req, sizeof(req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; + } + + resp = (struct ti_sci_msg_resp_get_proc_boot_status *) + xfer->tx_message.buf; + + if (!ti_sci_is_response_ack(resp)) + return -ENODEV; + *bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) | + (((u64)resp->bootvector_high << + TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK); + *cfg_flags = resp->config_flags; + *ctrl_flags = resp->control_flags; + *sts_flags = resp->status_flags; + + return ret; +} + +/* + * ti_sci_setup_ops() - Setup the operations structures + * @info: pointer to TISCI pointer + */ +static void ti_sci_setup_ops(struct ti_sci_info *info) +{ + struct ti_sci_ops *ops = &info->handle.ops; + struct ti_sci_board_ops *bops = &ops->board_ops; + struct ti_sci_dev_ops *dops = &ops->dev_ops; + struct ti_sci_clk_ops *cops = &ops->clk_ops; + struct ti_sci_core_ops *core_ops = &ops->core_ops; + struct ti_sci_proc_ops *pops = &ops->proc_ops; + + bops->board_config = ti_sci_cmd_set_board_config; + bops->board_config_rm = ti_sci_cmd_set_board_config_rm; + bops->board_config_security = ti_sci_cmd_set_board_config_security; + bops->board_config_pm = ti_sci_cmd_set_board_config_pm; + + dops->get_device = ti_sci_cmd_get_device; + dops->idle_device = ti_sci_cmd_idle_device; + dops->put_device = ti_sci_cmd_put_device; + dops->is_valid = ti_sci_cmd_dev_is_valid; + dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt; + dops->is_idle = ti_sci_cmd_dev_is_idle; + dops->is_stop = ti_sci_cmd_dev_is_stop; + dops->is_on = ti_sci_cmd_dev_is_on; + dops->is_transitioning = ti_sci_cmd_dev_is_trans; + dops->set_device_resets = ti_sci_cmd_set_device_resets; + dops->get_device_resets = ti_sci_cmd_get_device_resets; + + cops->get_clock = ti_sci_cmd_get_clock; + cops->idle_clock = ti_sci_cmd_idle_clock; + cops->put_clock = ti_sci_cmd_put_clock; + cops->is_auto = ti_sci_cmd_clk_is_auto; + cops->is_on = ti_sci_cmd_clk_is_on; + cops->is_off = ti_sci_cmd_clk_is_off; + + cops->set_parent = ti_sci_cmd_clk_set_parent; + cops->get_parent = ti_sci_cmd_clk_get_parent; + cops->get_num_parents = ti_sci_cmd_clk_get_num_parents; + + cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; + cops->set_freq = ti_sci_cmd_clk_set_freq; + cops->get_freq = ti_sci_cmd_clk_get_freq; + + core_ops->reboot_device = ti_sci_cmd_core_reboot; + + pops->proc_request = ti_sci_cmd_proc_request; + pops->proc_release = ti_sci_cmd_proc_release; + pops->proc_handover = ti_sci_cmd_proc_handover; + pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg; + pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl; + pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image; + pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status; +} + +/** + * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW + * @dev: Pointer to the SYSFW device + * + * Return: pointer to handle if successful, else EINVAL if invalid conditions + * are encountered. + */ +const +struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev) +{ + if (!sci_dev) + return ERR_PTR(-EINVAL); + + struct ti_sci_info *info = dev_get_priv(sci_dev); + + if (!info) + return ERR_PTR(-EINVAL); + + struct ti_sci_handle *handle = &info->handle; + + if (!handle) + return ERR_PTR(-EINVAL); + + return handle; +} + +/** + * ti_sci_get_handle() - Get the TI SCI handle for a device + * @dev: Pointer to device for which we want SCI handle + * + * Return: pointer to handle if successful, else EINVAL if invalid conditions + * are encountered. + */ +const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev) +{ + if (!dev) + return ERR_PTR(-EINVAL); + + struct udevice *sci_dev = dev_get_parent(dev); + + return ti_sci_get_handle_from_sysfw(sci_dev); +} + +/** + * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle + * @dev: device node + * @propname: property name containing phandle on TISCI node + * + * Return: pointer to handle if successful, else appropriate error value. + */ +const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev, + const char *property) +{ + struct ti_sci_info *entry, *info = NULL; + u32 phandle, err; + ofnode node; + + err = ofnode_read_u32(dev_ofnode(dev), property, &phandle); + if (err) + return ERR_PTR(err); + + node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(node)) + return ERR_PTR(-EINVAL); + + list_for_each_entry(entry, &ti_sci_list, list) + if (ofnode_equal(dev_ofnode(entry->dev), node)) { + info = entry; + break; + } + + if (!info) + return ERR_PTR(-ENODEV); + + return &info->handle; +} + +/** + * ti_sci_of_to_info() - generate private data from device tree + * @dev: corresponding system controller interface device + * @info: pointer to driver specific private data + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info) +{ + int ret; + + ret = mbox_get_by_name(dev, "tx", &info->chan_tx); + if (ret) { + dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n", + __func__, ret); + return ret; + } + + ret = mbox_get_by_name(dev, "rx", &info->chan_rx); + if (ret) { + dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n", + __func__, ret); + return ret; + } + + /* Notify channel is optional. Enable only if populated */ + ret = mbox_get_by_name(dev, "notify", &info->chan_notify); + if (ret) { + dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n", + __func__, ret); + } + + info->host_id = dev_read_u32_default(dev, "ti,host-id", + info->desc->host_id); + + info->is_secure = dev_read_bool(dev, "ti,secure-host"); + + return 0; +} + +/** + * ti_sci_probe() - Basic probe + * @dev: corresponding system controller interface device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int ti_sci_probe(struct udevice *dev) +{ + struct ti_sci_info *info; + int ret; + + debug("%s(dev=%p)\n", __func__, dev); + + info = dev_get_priv(dev); + info->desc = (void *)dev_get_driver_data(dev); + + ret = ti_sci_of_to_info(dev, info); + if (ret) { + dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret); + return ret; + } + + info->dev = dev; + info->seq = 0xA; + + list_add_tail(&info->list, &ti_sci_list); + ti_sci_setup_ops(info); + + ret = ti_sci_cmd_get_revision(&info->handle); + + return ret; +} + +/* Description for AM654 */ +static const struct ti_sci_desc ti_sci_sysfw_am654_desc = { + .host_id = 4, + .max_rx_timeout_us = 1000000, + .max_msg_size = 60, +}; + +static const struct udevice_id ti_sci_ids[] = { + { + .compatible = "ti,k2g-sci", + .data = (ulong)&ti_sci_sysfw_am654_desc + }, + { /* Sentinel */ }, +}; + +U_BOOT_DRIVER(ti_sci) = { + .name = "ti_sci", + .id = UCLASS_FIRMWARE, + .of_match = ti_sci_ids, + .probe = ti_sci_probe, + .priv_auto_alloc_size = sizeof(struct ti_sci_info), +}; diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h new file mode 100644 index 0000000000..81591fb0c7 --- /dev/null +++ b/drivers/firmware/ti_sci.h @@ -0,0 +1,680 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Texas Instruments System Control Interface (TISCI) Protocol + * + * Communication protocol with TI SCI hardware + * The system works in a message response protocol + * See: http://processors.wiki.ti.com/index.php/TISCI for details + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Based on drivers/firmware/ti_sci.h from Linux. + * + */ + +#ifndef __TI_SCI_H +#define __TI_SCI_H + +/* Generic Messages */ +#define TI_SCI_MSG_ENABLE_WDT 0x0000 +#define TI_SCI_MSG_WAKE_RESET 0x0001 +#define TI_SCI_MSG_VERSION 0x0002 +#define TI_SCI_MSG_WAKE_REASON 0x0003 +#define TI_SCI_MSG_GOODBYE 0x0004 +#define TI_SCI_MSG_SYS_RESET 0x0005 +#define TI_SCI_MSG_BOARD_CONFIG 0x000b +#define TI_SCI_MSG_BOARD_CONFIG_RM 0x000c +#define TI_SCI_MSG_BOARD_CONFIG_SECURITY 0x000d +#define TI_SCI_MSG_BOARD_CONFIG_PM 0x000e + +/* Device requests */ +#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 +#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201 +#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202 + +/* Clock requests */ +#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 +#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101 +#define TI_SCI_MSG_SET_CLOCK_PARENT 0x0102 +#define TI_SCI_MSG_GET_CLOCK_PARENT 0x0103 +#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104 +#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c +#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d +#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e + +/* Processor Control Messages */ +#define TISCI_MSG_PROC_REQUEST 0xc000 +#define TISCI_MSG_PROC_RELEASE 0xc001 +#define TISCI_MSG_PROC_HANDOVER 0xc005 +#define TISCI_MSG_SET_PROC_BOOT_CONFIG 0xc100 +#define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101 +#define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120 +#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 + +/** + * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses + * @type: Type of messages: One of TI_SCI_MSG* values + * @host: Host of the message + * @seq: Message identifier indicating a transfer sequence + * @flags: Flag for the message + */ +struct ti_sci_msg_hdr { + u16 type; + u8 host; + u8 seq; +#define TI_SCI_MSG_FLAG(val) (1 << (val)) +#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 +#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0) +#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1) +#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0 +#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1) + /* Additional Flags */ + u32 flags; +} __packed; + +/** + * struct ti_sci_secure_msg_hdr - Header that prefixes all TISCI messages sent + * via secure transport. + * @checksum: crc16 checksum for the entire message + * @reserved: Reserved for future use. + */ +struct ti_sci_secure_msg_hdr { + u16 checksum; + u16 reserved; +} __packed; + +/** + * struct ti_sci_msg_resp_version - Response for a message + * @hdr: Generic header + * @firmware_description: String describing the firmware + * @firmware_revision: Firmware revision + * @abi_major: Major version of the ABI that firmware supports + * @abi_minor: Minor version of the ABI that firmware supports + * + * In general, ABI version changes follow the rule that minor version increments + * are backward compatible. Major revision changes in ABI may not be + * backward compatible. + * + * Response to a generic message with message type TI_SCI_MSG_VERSION + */ +struct ti_sci_msg_resp_version { + struct ti_sci_msg_hdr hdr; + char firmware_description[32]; + u16 firmware_revision; + u8 abi_major; + u8 abi_minor; +} __packed; + +/** + * struct ti_sci_msg_req_reboot - Reboot the SoC + * @hdr: Generic Header + * + * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_reboot { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msg_board_config - Board configuration message + * @hdr: Generic Header + * @boardcfgp_low: Lower 32 bit of the pointer pointing to the board + * configuration data + * @boardcfgp_high: Upper 32 bit of the pointer pointing to the board + * configuration data + * @boardcfg_size: Size of board configuration data object + * Request type is TI_SCI_MSG_BOARD_CONFIG, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_board_config { + struct ti_sci_msg_hdr hdr; + u32 boardcfgp_low; + u32 boardcfgp_high; + u16 boardcfg_size; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_state - Set the desired state of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @reserved: Reserved space in message, must be 0 for backward compatibility + * @state: The desired state of the device. + * + * Certain flags can also be set to alter the device state: + * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. + * The meaning of this flag will vary slightly from device to device and from + * SoC to SoC but it generally allows the device to wake the SoC out of deep + * suspend states. + * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. + * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. + * If another host already has this device set to STATE_RETENTION or STATE_ON, + * the message will fail. Once successful, other hosts attempting to set + * STATE_RETENTION or STATE_ON will fail. + * + * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + u32 id; + u32 reserved; + +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0 +#define MSG_DEVICE_SW_STATE_RETENTION 1 +#define MSG_DEVICE_SW_STATE_ON 2 + u8 state; +} __packed; + +/** + * struct ti_sci_msg_req_get_device_state - Request to get device. + * @hdr: Generic header + * @id: Device Identifier + * + * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state + * information + */ +struct ti_sci_msg_req_get_device_state { + struct ti_sci_msg_hdr hdr; + u32 id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_device_state - Response to get device request. + * @hdr: Generic header + * @context_loss_count: Indicates how many times the device has lost context. A + * driver can use this monotonic counter to determine if the device has + * lost context since the last time this message was exchanged. + * @resets: Programmed state of the reset lines. + * @programmed_state: The state as programmed by set_device. + * - Uses the MSG_DEVICE_SW_* macros + * @current_state: The actual state of the hardware. + * + * Response to request TI_SCI_MSG_GET_DEVICE_STATE. + */ +struct ti_sci_msg_resp_get_device_state { + struct ti_sci_msg_hdr hdr; + u32 context_loss_count; + u32 resets; + u8 programmed_state; +#define MSG_DEVICE_HW_STATE_OFF 0 +#define MSG_DEVICE_HW_STATE_ON 1 +#define MSG_DEVICE_HW_STATE_TRANS 2 + u8 current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_device_resets - Set the desired resets + * configuration of the device + * @hdr: Generic header + * @id: Indicates which device to modify + * @resets: A bit field of resets for the device. The meaning, behavior, + * and usage of the reset flags are device specific. 0 for a bit + * indicates releasing the reset represented by that bit while 1 + * indicates keeping it held. + * + * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_device_resets { + struct ti_sci_msg_hdr hdr; + u32 id; + u32 resets; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state + * @hdr: Generic Header, Certain flags can be set specific to the clocks: + * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified + * via spread spectrum clocking. + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's + * frequency to be changed while it is running so long as it + * is within the min/max limits. + * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this + * is only applicable to clock inputs on the SoC pseudo-device. + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @request_state: Request the state for the clock to be set to. + * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock, + * it can be disabled, regardless of the state of the device + * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to + * automatically manage the state of this clock. If the device + * is enabled, then the clock is enabled. If the device is set + * to off or retention, then the clock is internally set as not + * being required by the device.(default) + * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled, + * regardless of the state of the device. + * + * Normally, all required clocks are managed by TISCI entity, this is used + * only for specific control *IF* required. Auto managed state is + * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote + * will explicitly control. + * + * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic + * ACK or NACK message. + */ +struct ti_sci_msg_req_set_clock_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_CLOCK_ALLOW_SSC TI_SCI_MSG_FLAG(8) +#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TI_SCI_MSG_FLAG(9) +#define MSG_FLAG_CLOCK_INPUT_TERM TI_SCI_MSG_FLAG(10) + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +#define MSG_CLOCK_SW_STATE_UNREQ 0 +#define MSG_CLOCK_SW_STATE_AUTO 1 +#define MSG_CLOCK_SW_STATE_REQ 2 + u8 request_state; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_state - Request for clock state + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get state of. + * + * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state + * of the clock + */ +struct ti_sci_msg_req_get_clock_state { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_state - Response to get clock state + * @hdr: Generic Header + * @programmed_state: Any programmed state of the clock. This is one of + * MSG_CLOCK_SW_STATE* values. + * @current_state: Current state of the clock. This is one of: + * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready + * MSG_CLOCK_HW_STATE_READY: Clock is ready + * + * Response to TI_SCI_MSG_GET_CLOCK_STATE. + */ +struct ti_sci_msg_resp_get_clock_state { + struct ti_sci_msg_hdr hdr; + u8 programmed_state; +#define MSG_CLOCK_HW_STATE_NOT_READY 0 +#define MSG_CLOCK_HW_STATE_READY 1 + u8 current_state; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_parent - Set the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @parent_id: The new clock parent is selectable by an index via this + * parameter. + * + * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic + * ACK / NACK message. + */ +struct ti_sci_msg_req_set_clock_parent { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; + u8 parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_parent - Get the clock parent + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get the parent for. + * + * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information + */ +struct ti_sci_msg_req_get_clock_parent { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent + * @hdr: Generic Header + * @parent_id: The current clock parent + * + * Response to TI_SCI_MSG_GET_CLOCK_PARENT. + */ +struct ti_sci_msg_resp_get_clock_parent { + struct ti_sci_msg_hdr hdr; + u8 parent_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents + * @hdr: Generic header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * This request provides information about how many clock parent options + * are available for a given clock to a device. This is typically used + * for input clocks. + * + * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents + * @hdr: Generic header + * @num_parents: Number of clock parents + * + * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS + */ +struct ti_sci_msg_resp_get_clock_num_parents { + struct ti_sci_msg_hdr hdr; + u8 num_parents; +} __packed; + +/** + * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. A frequency will be found + * as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested frequency within provided range and responds with + * result message. + * + * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message, + * or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_query_clock_freq { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u64 min_freq_hz; + u64 target_freq_hz; + u64 max_freq_hz; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query + * @hdr: Generic Header + * @freq_hz: Frequency that is the best match in Hz. + * + * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request + * cannot be satisfied, the message will be of type NACK. + */ +struct ti_sci_msg_resp_query_clock_freq { + struct ti_sci_msg_hdr hdr; + u64 freq_hz; +} __packed; + +/** + * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @target_freq_hz: The target clock frequency. The clock will be programmed + * at a rate as close to this target frequency as possible. + * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested range and responds with success/failure message. + * + * This sets the desired frequency for a clock within an allowable + * range. This message will fail on an enabled clock unless + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, + * if other clocks have their frequency modified due to this message, + * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled. + * + * Calling set frequency on a clock input to the SoC pseudo-device will + * inform the PMMC of that clock's frequency. Setting a frequency of + * zero will indicate the clock is disabled. + * + * Calling set frequency on clock outputs from the SoC pseudo-device will + * function similarly to setting the clock frequency on a device. + * + * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_clock_freq { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u64 min_freq_hz; + u64 target_freq_hz; + u64 max_freq_hz; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency + * @hdr: Generic Header + * @dev_id: Device identifier this request is for + * @clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In some cases, clock frequencies are configured by host. + * + * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency + * that the clock is currently at. + */ +struct ti_sci_msg_req_get_clock_freq { + struct ti_sci_msg_hdr hdr; + u32 dev_id; + u8 clk_id; +} __packed; + +/** + * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request + * @hdr: Generic Header + * @freq_hz: Frequency that the clock is currently on, in Hz. + * + * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ. + */ +struct ti_sci_msg_resp_get_clock_freq { + struct ti_sci_msg_hdr hdr; + u64 freq_hz; +} __packed; + +#define TISCI_ADDR_LOW_MASK GENMASK_ULL(31, 0) +#define TISCI_ADDR_HIGH_MASK GENMASK_ULL(63, 32) +#define TISCI_ADDR_HIGH_SHIFT 32 + +/** + * struct ti_sci_msg_req_proc_request - Request a processor + * + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_REQUEST, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_request { + struct ti_sci_msg_hdr hdr; + u8 processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_release - Release a processor + * + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_RELEASE, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_release { + struct ti_sci_msg_hdr hdr; + u8 processor_id; +} __packed; + +/** + * struct ti_sci_msg_req_proc_handover - Handover a processor to a host + * + * @hdr: Generic Header + * @processor_id: ID of processor + * @host_id: New Host we want to give control to + * + * Request type is TISCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_proc_handover { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u8 host_id; +} __packed; + +/* A53 Config Flags */ +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPIDEN 0x00000004 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPNIDEN 0x00000008 +#define PROC_BOOT_CFG_FLAG_ARMV8_AARCH32 0x00000100 + +/* R5 Config Flags */ +#define PROC_BOOT_CFG_FLAG_R5_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100 +#define PROC_BOOT_CFG_FLAG_R5_TEINIT 0x00000200 +#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN 0x00000400 +#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE 0x00000800 +#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000 +#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 + +/** + * struct ti_sci_msg_req_set_proc_boot_config - Set Processor boot configuration + * @hdr: Generic Header + * @processor_id: ID of processor + * @bootvector_low: Lower 32bit (Little Endian) of boot vector + * @bootvector_high: Higher 32bit (Little Endian) of boot vector + * @config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies required bit sets to 1. + * @config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CONFIG, response is a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_set_proc_boot_config { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 bootvector_low; + u32 bootvector_high; + u32 config_flags_set; + u32 config_flags_clear; +} __packed; + +/* R5 Control Flags */ +#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 + +/** + * struct ti_sci_msg_req_set_proc_boot_ctrl - Set Processor boot control flags + * @hdr: Generic Header + * @processor_id: ID of processor + * @control_flags_set: Optional Processor specific Control Flags to set. + * Setting a bit here implies required bit sets to 1. + * @control_flags_clear:Optional Processor specific Control Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CTRL, response is a generic ACK/NACK + * message. + */ +struct ti_sci_msg_req_set_proc_boot_ctrl { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 control_flags_set; + u32 control_flags_clear; +} __packed; + +/** + * struct ti_sci_msg_req_proc_auth_start_image - Authenticate and start image + * @hdr: Generic Header + * @processor_id: ID of processor + * @cert_addr_low: Lower 32bit (Little Endian) of certificate + * @cert_addr_high: Higher 32bit (Little Endian) of certificate + * + * Request type is TISCI_MSG_PROC_AUTH_BOOT_IMAGE, response is a generic + * ACK/NACK message. + */ +struct ti_sci_msg_req_proc_auth_boot_image { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 cert_addr_low; + u32 cert_addr_high; +} __packed; + +/** + * struct ti_sci_msg_req_get_proc_boot_status - Get processor boot status + * @hdr: Generic Header + * @processor_id: ID of processor + * + * Request type is TISCI_MSG_GET_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_get_proc_boot_status { + struct ti_sci_msg_hdr hdr; + u8 processor_id; +} __packed; + +/* ARMv8 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFI 0x00000002 + +/* R5 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 +#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 +#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 + +/** + * struct ti_sci_msg_resp_get_proc_boot_status - Processor boot status response + * @hdr: Generic Header + * @processor_id: ID of processor + * @bootvector_low: Lower 32bit (Little Endian) of boot vector + * @bootvector_high: Higher 32bit (Little Endian) of boot vector + * @config_flags: Optional Processor specific Config Flags set. + * @control_flags: Optional Processor specific Control Flags. + * @status_flags: Optional Processor specific Status Flags set. + * + * Response to TISCI_MSG_GET_PROC_BOOT_STATUS. + */ +struct ti_sci_msg_resp_get_proc_boot_status { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u32 bootvector_low; + u32 bootvector_high; + u32 config_flags; + u32 control_flags; + u32 status_flags; +} __packed; + +#endif /* __TI_SCI_H */ diff --git a/drivers/gpio/stm32f7_gpio.c b/drivers/gpio/stm32f7_gpio.c index 5b08e7ee27..4c0786fff8 100644 --- a/drivers/gpio/stm32f7_gpio.c +++ b/drivers/gpio/stm32f7_gpio.c @@ -18,7 +18,7 @@ #define STM32_GPIOS_PER_BANK 16 #define MODE_BITS(gpio_pin) (gpio_pin * 2) #define MODE_BITS_MASK 3 -#define IN_OUT_BIT_INDEX(gpio_pin) (1UL << (gpio_pin)) +#define BSRR_BIT(gpio_pin, value) BIT(gpio_pin + (value ? 0 : 16)) static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset) { @@ -41,8 +41,8 @@ static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset, int mask = MODE_BITS_MASK << bits_index; clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_OUT << bits_index); - mask = IN_OUT_BIT_INDEX(offset); - clrsetbits_le32(®s->odr, mask, value ? mask : 0); + + writel(BSRR_BIT(offset, value), ®s->bsrr); return 0; } @@ -52,16 +52,15 @@ static int stm32_gpio_get_value(struct udevice *dev, unsigned offset) struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - return readl(®s->idr) & IN_OUT_BIT_INDEX(offset) ? 1 : 0; + return readl(®s->idr) & BIT(offset) ? 1 : 0; } static int stm32_gpio_set_value(struct udevice *dev, unsigned offset, int value) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; - int mask = IN_OUT_BIT_INDEX(offset); - clrsetbits_le32(®s->odr, mask, value ? mask : 0); + writel(BSRR_BIT(offset, value), ®s->bsrr); return 0; } diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index 9649b70589..2836ee4a7b 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -24,4 +24,14 @@ config TEGRA_HSP This enables support for the NVIDIA Tegra HSP Hw module, which implements doorbells, mailboxes, semaphores, and shared interrupts. +config K3_SEC_PROXY + bool "Texas Instruments K3 Secure Proxy Driver" + depends on DM_MAILBOX && ARCH_K3 + help + An implementation of Secure proxy slave driver for K3 SoCs from + Texas Instruments. Secure proxy is a communication entity mainly + used for communication between multiple processors with the SoC. + Select this driver if your platform has support for this hardware + block. + endmenu diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile index 155dbeb099..243ff6f3ce 100644 --- a/drivers/mailbox/Makefile +++ b/drivers/mailbox/Makefile @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_DM_MAILBOX) += mailbox-uclass.o +obj-$(CONFIG_$(SPL_)DM_MAILBOX) += mailbox-uclass.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-mbox-test.o obj-$(CONFIG_TEGRA_HSP) += tegra-hsp.o +obj-$(CONFIG_K3_SEC_PROXY) += k3-sec-proxy.o diff --git a/drivers/mailbox/k3-sec-proxy.c b/drivers/mailbox/k3-sec-proxy.c new file mode 100644 index 0000000000..b07b56cf97 --- /dev/null +++ b/drivers/mailbox/k3-sec-proxy.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments' K3 Secure proxy Driver + * + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/types.h> +#include <linux/bitops.h> +#include <linux/soc/ti/k3-sec-proxy.h> +#include <dm.h> +#include <mailbox-uclass.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* SEC PROXY RT THREAD STATUS */ +#define RT_THREAD_STATUS 0x0 +#define RT_THREAD_THRESHOLD 0x4 +#define RT_THREAD_STATUS_ERROR_SHIFT 31 +#define RT_THREAD_STATUS_ERROR_MASK BIT(31) +#define RT_THREAD_STATUS_CUR_CNT_SHIFT 0 +#define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK(7, 0) + +/* SEC PROXY SCFG THREAD CTRL */ +#define SCFG_THREAD_CTRL 0x1000 +#define SCFG_THREAD_CTRL_DIR_SHIFT 31 +#define SCFG_THREAD_CTRL_DIR_MASK BIT(31) + +#define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x))) +#define THREAD_IS_RX 1 +#define THREAD_IS_TX 0 + +/** + * struct k3_sec_proxy_desc - Description of secure proxy integration. + * @thread_count: Number of Threads. + * @max_msg_size: Message size in bytes. + * @data_start_offset: Offset of the First data register of the thread + * @data_end_offset: Offset of the Last data register of the thread + * @valid_threads: List of Valid threads that the processor can access + * @num_valid_threads: Number of valid threads. + */ +struct k3_sec_proxy_desc { + u16 thread_count; + u16 max_msg_size; + u16 data_start_offset; + u16 data_end_offset; + const u32 *valid_threads; + u32 num_valid_threads; +}; + +/** + * struct k3_sec_proxy_thread - Description of a secure proxy Thread + * @id: Thread ID + * @data: Thread Data path region for target + * @scfg: Secure Config Region for Thread + * @rt: RealTime Region for Thread + * @rx_buf: Receive buffer data, max message size. + */ +struct k3_sec_proxy_thread { + u32 id; + void __iomem *data; + void __iomem *scfg; + void __iomem *rt; + u32 *rx_buf; +}; + +/** + * struct k3_sec_proxy_mbox - Description of a Secure Proxy Instance + * @chan: Mailbox Channel + * @desc: Description of the SoC integration + * @chans: Array for valid thread instances + * @target_data: Secure Proxy region for Target Data + * @scfg: Secure Proxy Region for Secure configuration. + * @rt: Secure proxy Region for Real Time Region. + */ +struct k3_sec_proxy_mbox { + struct mbox_chan chan; + struct k3_sec_proxy_desc *desc; + struct k3_sec_proxy_thread *chans; + phys_addr_t target_data; + phys_addr_t scfg; + phys_addr_t rt; +}; + +static inline u32 sp_readl(void __iomem *addr, unsigned int offset) +{ + return readl(addr + offset); +} + +static inline void sp_writel(void __iomem *addr, unsigned int offset, u32 data) +{ + writel(data, addr + offset); +} + +/** + * k3_sec_proxy_of_xlate() - Translation of phandle to channel + * @chan: Mailbox channel + * @args: Phandle Pointer + * + * Translates the phandle args and fills up the Mailbox channel from client. + * Return: 0 if all goes good, else return corresponding error message. + */ +static int k3_sec_proxy_of_xlate(struct mbox_chan *chan, + struct ofnode_phandle_args *args) +{ + struct k3_sec_proxy_mbox *spm = dev_get_priv(chan->dev); + int ind, i; + + debug("%s(chan=%p)\n", __func__, chan); + + if (args->args_count != 1) { + debug("Invaild args_count: %d\n", args->args_count); + return -EINVAL; + } + ind = args->args[0]; + + for (i = 0; i < spm->desc->num_valid_threads; i++) + if (spm->chans[i].id == ind) { + chan->id = ind; + chan->con_priv = &spm->chans[i]; + return 0; + } + + dev_err(chan->dev, "%s: Invalid Thread ID %d\n", __func__, ind); + return -ENOENT; +} + +/** + * k3_sec_proxy_request() - Request for mailbox channel + * @chan: Channel Pointer + */ +static int k3_sec_proxy_request(struct mbox_chan *chan) +{ + debug("%s(chan=%p)\n", __func__, chan); + + return 0; +} + +/** + * k3_sec_proxy_free() - Free the mailbox channel + * @chan: Channel Pointer + */ +static int k3_sec_proxy_free(struct mbox_chan *chan) +{ + debug("%s(chan=%p)\n", __func__, chan); + + return 0; +} + +/** + * k3_sec_proxy_verify_thread() - Verify thread status before + * sending/receiving data. + * @spt: pointer to secure proxy thread description + * @dir: Direction of the thread + * + * Return: 0 if all goes good, else appropriate error message. + */ +static inline int k3_sec_proxy_verify_thread(struct k3_sec_proxy_thread *spt, + u8 dir) +{ + /* Check for any errors already available */ + if (sp_readl(spt->rt, RT_THREAD_STATUS) & + RT_THREAD_STATUS_ERROR_MASK) { + printf("%s: Thread %d is corrupted, cannot send data.\n", + __func__, spt->id); + return -EINVAL; + } + + /* Make sure thread is configured for right direction */ + if ((sp_readl(spt->scfg, SCFG_THREAD_CTRL) + & SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) { + if (dir) + printf("%s: Trying to receive data on tx Thread %d\n", + __func__, spt->id); + else + printf("%s: Trying to send data on rx Thread %d\n", + __func__, spt->id); + return -EINVAL; + } + + /* Check the message queue before sending/receiving data */ + if (!(sp_readl(spt->rt, RT_THREAD_STATUS) & + RT_THREAD_STATUS_CUR_CNT_MASK)) + return -ENODATA; + + return 0; +} + +/** + * k3_sec_proxy_send() - Send data via mailbox channel + * @chan: Channel Pointer + * @data: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_sec_proxy_send(struct mbox_chan *chan, const void *data) +{ + const struct k3_sec_proxy_msg *msg = (struct k3_sec_proxy_msg *)data; + struct k3_sec_proxy_mbox *spm = dev_get_priv(chan->dev); + struct k3_sec_proxy_thread *spt = chan->con_priv; + int num_words, trail_bytes, ret; + void __iomem *data_reg; + u32 *word_data; + + debug("%s(chan=%p, data=%p)\n", __func__, chan, data); + + ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_TX); + if (ret) { + dev_err(dev, "%s: Thread%d verification failed. ret = %d\n", + __func__, spt->id, ret); + return ret; + } + + /* Check the message size. */ + if (msg->len > spm->desc->max_msg_size) { + printf("%s: Thread %ld message length %zu > max msg size %d\n", + __func__, chan->id, msg->len, spm->desc->max_msg_size); + return -EINVAL; + } + + /* Send the message */ + data_reg = spt->data + spm->desc->data_start_offset; + for (num_words = msg->len / sizeof(u32), word_data = (u32 *)msg->buf; + num_words; + num_words--, data_reg += sizeof(u32), word_data++) + writel(*word_data, data_reg); + + trail_bytes = msg->len % sizeof(u32); + if (trail_bytes) { + u32 data_trail = *word_data; + + /* Ensure all unused data is 0 */ + data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes)); + writel(data_trail, data_reg); + data_reg++; + } + + /* + * 'data_reg' indicates next register to write. If we did not already + * write on tx complete reg(last reg), we must do so for transmit + */ + if (data_reg <= (spt->data + spm->desc->data_end_offset)) + sp_writel(spt->data, spm->desc->data_end_offset, 0); + + debug("%s: Message successfully sent on thread %ld\n", + __func__, chan->id); + + return 0; +} + +/** + * k3_sec_proxy_recv() - Receive data via mailbox channel + * @chan: Channel Pointer + * @data: Pointer to k3_sec_proxy_msg + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_sec_proxy_recv(struct mbox_chan *chan, void *data) +{ + struct k3_sec_proxy_mbox *spm = dev_get_priv(chan->dev); + struct k3_sec_proxy_thread *spt = chan->con_priv; + struct k3_sec_proxy_msg *msg = data; + void __iomem *data_reg; + int num_words, ret; + u32 *word_data; + + debug("%s(chan=%p, data=%p)\n", __func__, chan, data); + + ret = k3_sec_proxy_verify_thread(spt, THREAD_IS_RX); + if (ret) + return ret; + + msg->len = spm->desc->max_msg_size; + msg->buf = spt->rx_buf; + data_reg = spt->data + spm->desc->data_start_offset; + word_data = spt->rx_buf; + for (num_words = spm->desc->max_msg_size / sizeof(u32); + num_words; + num_words--, data_reg += sizeof(u32), word_data++) + *word_data = readl(data_reg); + + debug("%s: Message successfully received from thread %ld\n", + __func__, chan->id); + + return 0; +} + +struct mbox_ops k3_sec_proxy_mbox_ops = { + .of_xlate = k3_sec_proxy_of_xlate, + .request = k3_sec_proxy_request, + .free = k3_sec_proxy_free, + .send = k3_sec_proxy_send, + .recv = k3_sec_proxy_recv, +}; + +/** + * k3_sec_proxy_of_to_priv() - generate private data from device tree + * @dev: corresponding k3 secure proxy device + * @spm: pointer to driver specific private data + * + * Return: 0 if all went ok, else corresponding error message. + */ +static int k3_sec_proxy_of_to_priv(struct udevice *dev, + struct k3_sec_proxy_mbox *spm) +{ + const void *blob = gd->fdt_blob; + + if (!blob) { + debug("'%s' no dt?\n", dev->name); + return -ENODEV; + } + + spm->target_data = devfdt_get_addr_name(dev, "target_data"); + if (spm->target_data == FDT_ADDR_T_NONE) { + dev_err(dev, "No reg property for target data base\n"); + return -EINVAL; + } + + spm->scfg = devfdt_get_addr_name(dev, "scfg"); + if (spm->rt == FDT_ADDR_T_NONE) { + dev_err(dev, "No reg property for Secure Cfg base\n"); + return -EINVAL; + } + + spm->rt = devfdt_get_addr_name(dev, "rt"); + if (spm->rt == FDT_ADDR_T_NONE) { + dev_err(dev, "No reg property for Real Time Cfg base\n"); + return -EINVAL; + } + + return 0; +} + +/** + * k3_sec_proxy_thread_setup - Initialize the parameters for all valid threads + * @spm: Mailbox instance for which threads needs to be initialized + * + * Return: 0 if all went ok, else corresponding error message + */ +static int k3_sec_proxy_thread_setup(struct k3_sec_proxy_mbox *spm) +{ + struct k3_sec_proxy_thread *spt; + int i, ind; + + for (i = 0; i < spm->desc->num_valid_threads; i++) { + spt = &spm->chans[i]; + ind = spm->desc->valid_threads[i]; + spt->id = ind; + spt->data = (void *)SEC_PROXY_THREAD(spm->target_data, ind); + spt->scfg = (void *)SEC_PROXY_THREAD(spm->scfg, ind); + spt->rt = (void *)SEC_PROXY_THREAD(spm->rt, ind); + spt->rx_buf = calloc(1, spm->desc->max_msg_size); + if (!spt->rx_buf) + return -ENOMEM; + } + + return 0; +} + +/** + * k3_sec_proxy_probe() - Basic probe + * @dev: corresponding mailbox device + * + * Return: 0 if all went ok, else corresponding error message + */ +static int k3_sec_proxy_probe(struct udevice *dev) +{ + struct k3_sec_proxy_mbox *spm = dev_get_priv(dev); + int ret; + + debug("%s(dev=%p)\n", __func__, dev); + + ret = k3_sec_proxy_of_to_priv(dev, spm); + if (ret) + return ret; + + spm->desc = (void *)dev_get_driver_data(dev); + spm->chans = calloc(spm->desc->num_valid_threads, + sizeof(struct k3_sec_proxy_thread)); + if (!spm->chans) + return -ENOMEM; + + ret = k3_sec_proxy_thread_setup(spm); + if (ret) { + debug("%s: secure proxy thread setup failed\n", __func__); + return ret; + } + + return 0; +} + +static int k3_sec_proxy_remove(struct udevice *dev) +{ + struct k3_sec_proxy_mbox *spm = dev_get_priv(dev); + + debug("%s(dev=%p)\n", __func__, dev); + + free(spm->chans); + + return 0; +} + +/* + * Thread ID #4: ROM request + * Thread ID #5: ROM response, SYSFW notify + * Thread ID #6: SYSFW request response + * Thread ID #7: SYSFW request high priority + * Thread ID #8: SYSFW request low priority + * Thread ID #9: SYSFW notify response + */ +static const u32 am6x_valid_threads[] = { 4, 5, 6, 7, 8, 9, 11, 13 }; + +static const struct k3_sec_proxy_desc am654_desc = { + .thread_count = 90, + .max_msg_size = 60, + .data_start_offset = 0x4, + .data_end_offset = 0x3C, + .valid_threads = am6x_valid_threads, + .num_valid_threads = ARRAY_SIZE(am6x_valid_threads), +}; + +static const struct udevice_id k3_sec_proxy_ids[] = { + { .compatible = "ti,am654-secure-proxy", .data = (ulong)&am654_desc}, + { } +}; + +U_BOOT_DRIVER(k3_sec_proxy) = { + .name = "k3-secure-proxy", + .id = UCLASS_MAILBOX, + .of_match = k3_sec_proxy_ids, + .probe = k3_sec_proxy_probe, + .remove = k3_sec_proxy_remove, + .priv_auto_alloc_size = sizeof(struct k3_sec_proxy_mbox), + .ops = &k3_sec_proxy_mbox_ops, +}; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 377b1c4b3b..0a0d4aaf6c 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -111,6 +111,19 @@ config SPL_MMC_UHS_SUPPORT cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus frequency can go up to 208MHz (SDR104) +config MMC_HS400_SUPPORT + bool "enable HS400 support" + select MMC_HS200_SUPPORT + help + The HS400 mode is support by some eMMC. The bus frequency is up to + 200MHz. This mode requires tuning the IO. + +config SPL_MMC_HS400_SUPPORT + bool "enable HS400 support in SPL" + help + The HS400 mode is support by some eMMC. The bus frequency is up to + 200MHz. This mode requires tuning the IO. + config MMC_HS200_SUPPORT bool "enable HS200 support" help @@ -402,6 +415,15 @@ config MMC_SDHCI_CADENCE If unsure, say N. +config MMC_SDHCI_K3_ARASAN + bool "Arasan SDHCI controller for TI's K3 based SoCs" + depends on ARCH_K3 + depends on MMC_SDHCI + depends on DM_MMC && OF_CONTROL && BLK + help + Support for Arasan SDHCI host controller on Texas Instruments' + K3 family based SoC platforms + config MMC_SDHCI_KONA bool "SDHCI support on Broadcom KONA platform" depends on MMC_SDHCI diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index f6191862d6..23c5b0daef 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o +obj-$(CONFIG_MMC_SDHCI_K3_ARASAN) += k3_arsan_sdhci.o obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o obj-$(CONFIG_MMC_SDHCI_MSM) += msm_sdhci.o obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 4528345c67..03c6743ae8 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -662,6 +662,7 @@ static int esdhc_change_pinstate(struct udevice *dev) break; case UHS_SDR104: case MMC_HS_200: + case MMC_HS_400: ret = pinctrl_select_state(dev, "state_200mhz"); break; default: @@ -689,6 +690,33 @@ static void esdhc_reset_tuning(struct mmc *mmc) } } +static void esdhc_set_strobe_dll(struct mmc *mmc) +{ + struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); + struct fsl_esdhc *regs = priv->esdhc_regs; + u32 val; + + if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) { + writel(ESDHC_STROBE_DLL_CTRL_RESET, ®s->strobe_dllctrl); + + /* + * enable strobe dll ctrl and adjust the delay target + * for the uSDHC loopback read clock + */ + val = ESDHC_STROBE_DLL_CTRL_ENABLE | + (priv->strobe_dll_delay_target << + ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); + writel(val, ®s->strobe_dllctrl); + /* wait 1us to make sure strobe dll status register stable */ + mdelay(1); + val = readl(®s->strobe_dllstat); + if (!(val & ESDHC_STROBE_DLL_STS_REF_LOCK)) + pr_warn("HS400 strobe DLL status REF not lock!\n"); + if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK)) + pr_warn("HS400 strobe DLL status SLV not lock!\n"); + } +} + static int esdhc_set_timing(struct mmc *mmc) { struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); @@ -702,6 +730,12 @@ static int esdhc_set_timing(struct mmc *mmc) case MMC_LEGACY: case SD_LEGACY: esdhc_reset_tuning(mmc); + writel(mixctrl, ®s->mixctrl); + break; + case MMC_HS_400: + mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN; + writel(mixctrl, ®s->mixctrl); + esdhc_set_strobe_dll(mmc); break; case MMC_HS: case MMC_HS_52: @@ -1438,7 +1472,7 @@ static int fsl_esdhc_probe(struct udevice *dev) #endif if (fdt_get_property(fdt, node, "no-1-8-v", NULL)) - priv->caps &= ~(UHS_CAPS | MMC_MODE_HS200); + priv->caps &= ~(UHS_CAPS | MMC_MODE_HS200 | MMC_MODE_HS400); /* * TODO: diff --git a/drivers/mmc/k3_arsan_sdhci.c b/drivers/mmc/k3_arsan_sdhci.c new file mode 100644 index 0000000000..d5f2857382 --- /dev/null +++ b/drivers/mmc/k3_arsan_sdhci.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * Texas Instruments' K3 SD Host Controller Interface + */ + +#include <clk.h> +#include <common.h> +#include <dm.h> +#include <malloc.h> +#include <power-domain.h> +#include <sdhci.h> + +#define K3_ARASAN_SDHCI_MIN_FREQ 0 + +struct k3_arasan_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; + unsigned int f_max; +}; + +static int k3_arasan_sdhci_probe(struct udevice *dev) +{ + struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct sdhci_host *host = dev_get_priv(dev); + struct power_domain sdhci_pwrdmn; + struct clk clk; + unsigned long clock; + int ret; + + ret = power_domain_get_by_index(dev, &sdhci_pwrdmn, 0); + if (ret) { + dev_err(dev, "failed to get power domain\n"); + return ret; + } + + ret = power_domain_on(&sdhci_pwrdmn); + if (ret) { + dev_err(dev, "Power domain on failed\n"); + return ret; + } + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) { + dev_err(dev, "failed to get clock\n"); + return ret; + } + + clock = clk_get_rate(&clk); + if (IS_ERR_VALUE(clock)) { + dev_err(dev, "failed to get rate\n"); + return clock; + } + + host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | + SDHCI_QUIRK_BROKEN_R1B; + + host->max_clk = clock; + + ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, + K3_ARASAN_SDHCI_MIN_FREQ); + host->mmc = &plat->mmc; + if (ret) + return ret; + host->mmc->priv = host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + return sdhci_probe(dev); +} + +static int k3_arasan_sdhci_ofdata_to_platdata(struct udevice *dev) +{ + struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev); + struct sdhci_host *host = dev_get_priv(dev); + + host->name = dev->name; + host->ioaddr = (void *)dev_read_addr(dev); + host->bus_width = dev_read_u32_default(dev, "bus-width", 4); + plat->f_max = dev_read_u32_default(dev, "max-frequency", 0); + + return 0; +} + +static int k3_arasan_sdhci_bind(struct udevice *dev) +{ + struct k3_arasan_sdhci_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id k3_arasan_sdhci_ids[] = { + { .compatible = "arasan,sdhci-5.1" }, + { } +}; + +U_BOOT_DRIVER(k3_arasan_sdhci_drv) = { + .name = "k3_arasan_sdhci", + .id = UCLASS_MMC, + .of_match = k3_arasan_sdhci_ids, + .ofdata_to_platdata = k3_arasan_sdhci_ofdata_to_platdata, + .ops = &sdhci_ops, + .bind = k3_arasan_sdhci_bind, + .probe = k3_arasan_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct sdhci_host), + .platdata_auto_alloc_size = sizeof(struct k3_arasan_sdhci_plat), +}; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ad429f49c9..585951cd78 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -147,6 +147,7 @@ const char *mmc_mode_name(enum bus_mode mode) [MMC_HS_52] = "MMC High Speed (52MHz)", [MMC_DDR_52] = "MMC DDR52 (52MHz)", [MMC_HS_200] = "HS200 (200MHz)", + [MMC_HS_400] = "HS400 (200MHz)", }; if (mode >= MMC_MODES_END) @@ -171,6 +172,7 @@ static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode) [UHS_DDR50] = 50000000, [UHS_SDR104] = 208000000, [MMC_HS_200] = 200000000, + [MMC_HS_400] = 200000000, }; if (mode == MMC_LEGACY) @@ -770,6 +772,11 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) speed_bits = EXT_CSD_TIMING_HS200; break; #endif +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + case MMC_HS_400: + speed_bits = EXT_CSD_TIMING_HS400; + break; +#endif case MMC_LEGACY: speed_bits = EXT_CSD_TIMING_LEGACY; break; @@ -816,7 +823,7 @@ static int mmc_get_capabilities(struct mmc *mmc) mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; - cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f; + cardtype = ext_csd[EXT_CSD_CARD_TYPE]; mmc->cardtype = cardtype; #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) @@ -825,6 +832,12 @@ static int mmc_get_capabilities(struct mmc *mmc) mmc->card_caps |= MMC_MODE_HS200; } #endif +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V | + EXT_CSD_CARD_TYPE_HS400_1_8V)) { + mmc->card_caps |= MMC_MODE_HS400; + } +#endif if (cardtype & EXT_CSD_CARD_TYPE_52) { if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) mmc->card_caps |= MMC_MODE_DDR_52MHz; @@ -1734,10 +1747,13 @@ static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, u32 card_mask = 0; switch (mode) { + case MMC_HS_400: case MMC_HS_200: - if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V) + if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V | + EXT_CSD_CARD_TYPE_HS400_1_8V)) card_mask |= MMC_SIGNAL_VOLTAGE_180; - if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V) + if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V | + EXT_CSD_CARD_TYPE_HS400_1_2V)) card_mask |= MMC_SIGNAL_VOLTAGE_120; break; case MMC_DDR_52: @@ -1773,6 +1789,13 @@ static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, #endif static const struct mode_width_tuning mmc_modes_by_pref[] = { +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + { + .mode = MMC_HS_400, + .widths = MMC_MODE_8BIT, + .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200 + }, +#endif #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) { .mode = MMC_HS_200, @@ -1816,6 +1839,54 @@ static const struct ext_csd_bus_width { {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1}, }; +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) +static int mmc_select_hs400(struct mmc *mmc) +{ + int err; + + /* Set timing to HS200 for tuning */ + err = mmc_set_card_speed(mmc, MMC_HS_200); + if (err) + return err; + + /* configure the bus mode (host) */ + mmc_select_mode(mmc, MMC_HS_200); + mmc_set_clock(mmc, mmc->tran_speed, false); + + /* execute tuning if needed */ + err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200); + if (err) { + debug("tuning failed\n"); + return err; + } + + /* Set back to HS */ + mmc_set_card_speed(mmc, MMC_HS); + mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false); + + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, + EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG); + if (err) + return err; + + err = mmc_set_card_speed(mmc, MMC_HS_400); + if (err) + return err; + + mmc_select_mode(mmc, MMC_HS_400); + err = mmc_set_clock(mmc, mmc->tran_speed, false); + if (err) + return err; + + return 0; +} +#else +static int mmc_select_hs400(struct mmc *mmc) +{ + return -ENOTSUPP; +} +#endif + #define for_each_supported_width(caps, ddr, ecbv) \ for (ecbv = ext_csd_bus_width;\ ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\ @@ -1869,37 +1940,49 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) goto error; mmc_set_bus_width(mmc, bus_width(ecbw->cap)); - /* configure the bus speed (card) */ - err = mmc_set_card_speed(mmc, mwt->mode); - if (err) - goto error; - - /* - * configure the bus width AND the ddr mode (card) - * The host side will be taken care of in the next step - */ - if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) { - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - ecbw->ext_csd_bits); + if (mwt->mode == MMC_HS_400) { + err = mmc_select_hs400(mmc); + if (err) { + printf("Select HS400 failed %d\n", err); + goto error; + } + } else { + /* configure the bus speed (card) */ + err = mmc_set_card_speed(mmc, mwt->mode); if (err) goto error; - } - /* configure the bus mode (host) */ - mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); + /* + * configure the bus width AND the ddr mode + * (card). The host side will be taken care + * of in the next step + */ + if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) { + err = mmc_switch(mmc, + EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, + ecbw->ext_csd_bits); + if (err) + goto error; + } + + /* configure the bus mode (host) */ + mmc_select_mode(mmc, mwt->mode); + mmc_set_clock(mmc, mmc->tran_speed, + MMC_CLK_ENABLE); #ifdef MMC_SUPPORTS_TUNING - /* execute tuning if needed */ - if (mwt->tuning) { - err = mmc_execute_tuning(mmc, mwt->tuning); - if (err) { - pr_debug("tuning failed\n"); - goto error; + /* execute tuning if needed */ + if (mwt->tuning) { + err = mmc_execute_tuning(mmc, + mwt->tuning); + if (err) { + pr_debug("tuning failed\n"); + goto error; + } } - } #endif + } /* do a transfer to check the configuration */ err = mmc_read_and_compare_ext_csd(mmc); diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index e9671d9b76..eb118f3496 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -7,7 +7,6 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <inttypes.h> #include <pci.h> #include <asm/io.h> #include <dm/device-internal.h> @@ -854,9 +853,8 @@ static void decode_regions(struct pci_controller *hose, ofnode parent_node, prop += addr_cells; size = fdtdec_get_number(prop, size_cells); prop += size_cells; - debug("%s: region %d, pci_addr=%" PRIx64 ", addr=%" PRIx64 - ", size=%" PRIx64 ", space_code=%d\n", __func__, - hose->region_count, pci_addr, addr, size, space_code); + debug("%s: region %d, pci_addr=%llx, addr=%llx, size=%llx, space_code=%d\n", + __func__, hose->region_count, pci_addr, addr, size, space_code); if (space_code & 2) { type = flags & (1U << 30) ? PCI_REGION_PREFETCH : PCI_REGION_MEM; diff --git a/drivers/pci/pci_sandbox.c b/drivers/pci/pci_sandbox.c index 119a98d061..2af2b79c05 100644 --- a/drivers/pci/pci_sandbox.c +++ b/drivers/pci/pci_sandbox.c @@ -7,7 +7,6 @@ #include <common.h> #include <dm.h> #include <fdtdec.h> -#include <inttypes.h> #include <pci.h> #define FDT_DEV_INFO_CELLS 4 diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 296eb63cc4..d80c6eda70 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -43,13 +43,13 @@ static int single_configure_pins(struct udevice *dev, { struct single_pdata *pdata = dev->platdata; int count = size / sizeof(struct single_fdt_pin_cfg); - int n, reg; + phys_addr_t n, reg; u32 val; for (n = 0; n < count; n++, pins++) { reg = fdt32_to_cpu(pins->reg); if ((reg < 0) || (reg > pdata->offset)) { - dev_dbg(dev, " invalid register offset 0x%08x\n", reg); + dev_dbg(dev, " invalid register offset 0x%pa\n", ®); continue; } reg += pdata->base; @@ -66,7 +66,7 @@ static int single_configure_pins(struct udevice *dev, pdata->width); continue; } - dev_dbg(dev, " reg/val 0x%08x/0x%08x\n",reg, val); + dev_dbg(dev, " reg/val 0x%pa/0x%08x\n", ®, val); } return 0; } diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 7cfa761498..2c344888ca 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -16,6 +16,13 @@ config BCM6328_POWER_DOMAIN Enable support for manipulating BCM6345 power domains via MMIO mapped registers. +config MESON_GX_VPU_POWER_DOMAIN + bool "Enable Amlogic Meson GX VPU power domain driver" + depends on ARCH_MESON + help + Enable support for manipulating Amlogic Meson GX Video Processing + Unit power domain. + config SANDBOX_POWER_DOMAIN bool "Enable the sandbox power domain test driver" depends on POWER_DOMAIN && SANDBOX @@ -31,4 +38,11 @@ config TEGRA186_POWER_DOMAIN Enable support for manipulating Tegra's on-SoC power domains via IPC requests to the BPMP (Boot and Power Management Processor). +config TI_SCI_POWER_DOMAIN + bool "Enable the TI SCI-based power domain driver" + depends on POWER_DOMAIN && TI_SCI_PROTOCOL + help + Generic power domain implementation for TI devices implementing the + TI SCI protocol. + endmenu diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index 020eee2378..6bdaa175e9 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_$(SPL_)POWER_DOMAIN) += power-domain-uclass.o obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o +obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o +obj-$(CONFIG_TI_SCI_POWER_DOMAIN) += ti-sci-power-domain.o diff --git a/drivers/power/domain/meson-gx-pwrc-vpu.c b/drivers/power/domain/meson-gx-pwrc-vpu.c new file mode 100644 index 0000000000..d631d3e6ff --- /dev/null +++ b/drivers/power/domain/meson-gx-pwrc-vpu.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Amlogic Meson VPU Power Domain Controller driver + * + * Copyright (c) 2018 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + */ + +#include <common.h> +#include <dm.h> +#include <power-domain-uclass.h> +#include <regmap.h> +#include <syscon.h> +#include <reset.h> +#include <clk.h> + +/* AO Offsets */ + +#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2) + +#define GEN_PWR_VPU_HDMI BIT(8) +#define GEN_PWR_VPU_HDMI_ISO BIT(9) + +/* HHI Offsets */ + +#define HHI_MEM_PD_REG0 (0x40 << 2) +#define HHI_VPU_MEM_PD_REG0 (0x41 << 2) +#define HHI_VPU_MEM_PD_REG1 (0x42 << 2) + +struct meson_gx_pwrc_vpu_priv { + struct regmap *regmap_ao; + struct regmap *regmap_hhi; + struct reset_ctl_bulk resets; + struct clk_bulk clks; +}; + +static int meson_gx_pwrc_vpu_request(struct power_domain *power_domain) +{ + return 0; +} + +static int meson_gx_pwrc_vpu_free(struct power_domain *power_domain) +{ + return 0; +} + +static int meson_gx_pwrc_vpu_on(struct power_domain *power_domain) +{ + struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev); + int i, ret; + + regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, + GEN_PWR_VPU_HDMI, 0); + udelay(20); + + /* Power Up Memories */ + for (i = 0; i < 32; i += 2) { + regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0, + 0x3 << i, 0); + udelay(5); + } + + for (i = 0; i < 32; i += 2) { + regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1, + 0x3 << i, 0); + udelay(5); + } + + for (i = 8; i < 16; i++) { + regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0, + BIT(i), 0); + udelay(5); + } + udelay(20); + + ret = reset_assert_bulk(&priv->resets); + if (ret) + return ret; + + regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, + GEN_PWR_VPU_HDMI_ISO, 0); + + ret = reset_deassert_bulk(&priv->resets); + if (ret) + return ret; + + ret = clk_enable_bulk(&priv->clks); + if (ret) + return ret; + + return 0; +} + +static int meson_gx_pwrc_vpu_off(struct power_domain *power_domain) +{ + struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(power_domain->dev); + int i; + + regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, + GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO); + udelay(20); + + /* Power Down Memories */ + for (i = 0; i < 32; i += 2) { + regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG0, + 0x3 << i, 0x3 << i); + udelay(5); + } + for (i = 0; i < 32; i += 2) { + regmap_update_bits(priv->regmap_hhi, HHI_VPU_MEM_PD_REG1, + 0x3 << i, 0x3 << i); + udelay(5); + } + for (i = 8; i < 16; i++) { + regmap_update_bits(priv->regmap_hhi, HHI_MEM_PD_REG0, + BIT(i), BIT(i)); + udelay(5); + } + udelay(20); + + regmap_update_bits(priv->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, + GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI); + mdelay(20); + + clk_disable_bulk(&priv->clks); + + return 0; +} + +static int meson_gx_pwrc_vpu_of_xlate(struct power_domain *power_domain, + struct ofnode_phandle_args *args) +{ + /* #power-domain-cells is 0 */ + + if (args->args_count != 0) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + return 0; +} + +struct power_domain_ops meson_gx_pwrc_vpu_ops = { + .free = meson_gx_pwrc_vpu_free, + .off = meson_gx_pwrc_vpu_off, + .on = meson_gx_pwrc_vpu_on, + .request = meson_gx_pwrc_vpu_request, + .of_xlate = meson_gx_pwrc_vpu_of_xlate, +}; + +static const struct udevice_id meson_gx_pwrc_vpu_ids[] = { + { .compatible = "amlogic,meson-gx-pwrc-vpu" }, + { } +}; + +static int meson_gx_pwrc_vpu_probe(struct udevice *dev) +{ + struct meson_gx_pwrc_vpu_priv *priv = dev_get_priv(dev); + u32 hhi_phandle; + ofnode hhi_node; + int ret; + + priv->regmap_ao = syscon_node_to_regmap(dev_get_parent(dev)->node); + if (IS_ERR(priv->regmap_ao)) + return PTR_ERR(priv->regmap_ao); + + ret = ofnode_read_u32(dev->node, "amlogic,hhi-sysctrl", + &hhi_phandle); + if (ret) + return ret; + + hhi_node = ofnode_get_by_phandle(hhi_phandle); + if (!ofnode_valid(hhi_node)) + return -EINVAL; + + priv->regmap_hhi = syscon_node_to_regmap(hhi_node); + if (IS_ERR(priv->regmap_hhi)) + return PTR_ERR(priv->regmap_hhi); + + ret = reset_get_bulk(dev, &priv->resets); + if (ret) + return ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret) + return ret; + + return 0; +} + +U_BOOT_DRIVER(meson_gx_pwrc_vpu) = { + .name = "meson_gx_pwrc_vpu", + .id = UCLASS_POWER_DOMAIN, + .of_match = meson_gx_pwrc_vpu_ids, + .probe = meson_gx_pwrc_vpu_probe, + .ops = &meson_gx_pwrc_vpu_ops, + .priv_auto_alloc_size = sizeof(struct meson_gx_pwrc_vpu_priv), +}; diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c index 9e9ec4f419..2ea0ff24c7 100644 --- a/drivers/power/domain/power-domain-uclass.c +++ b/drivers/power/domain/power-domain-uclass.c @@ -28,7 +28,8 @@ static int power_domain_of_xlate_default(struct power_domain *power_domain, return 0; } -int power_domain_get(struct udevice *dev, struct power_domain *power_domain) +int power_domain_get_by_index(struct udevice *dev, + struct power_domain *power_domain, int index) { struct ofnode_phandle_args args; int ret; @@ -38,7 +39,8 @@ int power_domain_get(struct udevice *dev, struct power_domain *power_domain) debug("%s(dev=%p, power_domain=%p)\n", __func__, dev, power_domain); ret = dev_read_phandle_with_args(dev, "power-domains", - "#power-domain-cells", 0, 0, &args); + "#power-domain-cells", 0, index, + &args); if (ret) { debug("%s: dev_read_phandle_with_args failed: %d\n", __func__, ret); @@ -73,6 +75,11 @@ int power_domain_get(struct udevice *dev, struct power_domain *power_domain) return 0; } +int power_domain_get(struct udevice *dev, struct power_domain *power_domain) +{ + return power_domain_get_by_index(dev, power_domain, 0); +} + int power_domain_free(struct power_domain *power_domain) { struct power_domain_ops *ops = power_domain_dev_ops(power_domain->dev); diff --git a/drivers/power/domain/ti-sci-power-domain.c b/drivers/power/domain/ti-sci-power-domain.c new file mode 100644 index 0000000000..aafde62cbf --- /dev/null +++ b/drivers/power/domain/ti-sci-power-domain.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments System Control Interface (TI SCI) power domain driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg <dannenberg@ti.com> + * + * Loosely based on Linux kernel ti_sci_pm_domains.c... + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <power-domain-uclass.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +/** + * struct ti_sci_power_domain_data - pm domain controller information structure + * @sci: TI SCI handle used for communication with system controller + */ +struct ti_sci_power_domain_data { + const struct ti_sci_handle *sci; +}; + +static int ti_sci_power_domain_probe(struct udevice *dev) +{ + struct ti_sci_power_domain_data *data = dev_get_priv(dev); + + debug("%s(dev=%p)\n", __func__, dev); + + if (!data) + return -ENOMEM; + + /* Store handle for communication with the system controller */ + data->sci = ti_sci_get_handle(dev); + if (IS_ERR(data->sci)) + return PTR_ERR(data->sci); + + return 0; +} + +static int ti_sci_power_domain_request(struct power_domain *pd) +{ + debug("%s(pd=%p)\n", __func__, pd); + return 0; +} + +static int ti_sci_power_domain_free(struct power_domain *pd) +{ + debug("%s(pd=%p)\n", __func__, pd); + return 0; +} + +static int ti_sci_power_domain_on(struct power_domain *pd) +{ + struct ti_sci_power_domain_data *data = dev_get_priv(pd->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops; + int ret; + + debug("%s(pd=%p)\n", __func__, pd); + + ret = dops->get_device(sci, pd->id); + if (ret) + dev_err(power_domain->dev, "%s: get_device failed (%d)\n", + __func__, ret); + + return ret; +} + +static int ti_sci_power_domain_off(struct power_domain *pd) +{ + struct ti_sci_power_domain_data *data = dev_get_priv(pd->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops; + int ret; + + debug("%s(pd=%p)\n", __func__, pd); + + ret = dops->put_device(sci, pd->id); + if (ret) + dev_err(power_domain->dev, "%s: put_device failed (%d)\n", + __func__, ret); + + return ret; +} + +static const struct udevice_id ti_sci_power_domain_of_match[] = { + { .compatible = "ti,sci-pm-domain" }, + { /* sentinel */ } +}; + +static struct power_domain_ops ti_sci_power_domain_ops = { + .request = ti_sci_power_domain_request, + .free = ti_sci_power_domain_free, + .on = ti_sci_power_domain_on, + .off = ti_sci_power_domain_off, +}; + +U_BOOT_DRIVER(ti_sci_pm_domains) = { + .name = "ti-sci-pm-domains", + .id = UCLASS_POWER_DOMAIN, + .of_match = ti_sci_power_domain_of_match, + .probe = ti_sci_power_domain_probe, + .priv_auto_alloc_size = sizeof(struct ti_sci_power_domain_data), + .ops = &ti_sci_power_domain_ops, +}; diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index becae5f85d..9eb532bc7a 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -13,6 +13,24 @@ config REMOTEPROC depends on DM # Please keep the configuration alphabetically sorted. +config K3_SYSTEM_CONTROLLER + bool "Support for TI' K3 System Controller" + select REMOTEPROC + depends on DM + depends on ARCH_K3 + depends on OF_CONTROL + help + Say 'y' here to add support for TI' K3 System Controller. + +config REMOTEPROC_K3 + bool "Support for TI's K3 based remoteproc driver" + select REMOTEPROC + depends on DM + depends on ARCH_K3 + depends on OF_CONTROL + help + Say 'y' here to add support for TI' K3 remoteproc driver. + config REMOTEPROC_SANDBOX bool "Support for Test processor for Sandbox" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index bda995e21b..77eb708523 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -4,8 +4,10 @@ # Texas Instruments Incorporated - http://www.ti.com/ # -obj-$(CONFIG_REMOTEPROC) += rproc-uclass.o +obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o # Remote proc drivers - Please keep this list alphabetically sorted. +obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o +obj-$(CONFIG_REMOTEPROC_K3) += k3_rproc.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o diff --git a/drivers/remoteproc/k3_rproc.c b/drivers/remoteproc/k3_rproc.c new file mode 100644 index 0000000000..3c29d925ce --- /dev/null +++ b/drivers/remoteproc/k3_rproc.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments' K3 Remoteproc driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + * + */ + +#include <common.h> +#include <dm.h> +#include <remoteproc.h> +#include <errno.h> +#include <clk.h> +#include <reset.h> +#include <asm/io.h> +#include <power-domain.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +#define INVALID_ID 0xffff + +#define GTC_CNTCR_REG 0x0 +#define GTC_CNTR_EN 0x3 + +/** + * struct k3_rproc_privdata - Structure representing Remote processor data. + * @rproc_pwrdmn: rproc power domain data + * @rproc_rst: rproc reset control data + * @sci: Pointer to TISCI handle + * @gtc_base: Timer base address. + * @proc_id: TISCI processor ID + * @host_id: TISCI host id to which the processor gets assigned to. + */ +struct k3_rproc_privdata { + struct power_domain rproc_pwrdmn; + struct power_domain gtc_pwrdmn; + struct reset_ctl rproc_rst; + const struct ti_sci_handle *sci; + void *gtc_base; + u16 proc_id; + u16 host_id; +}; + +/** + * k3_rproc_load() - Load up the Remote processor image + * @dev: rproc device pointer + * @addr: Address at which image is available + * @size: size of the image + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_rproc_load(struct udevice *dev, ulong addr, ulong size) +{ + struct k3_rproc_privdata *rproc = dev_get_priv(dev); + const struct ti_sci_proc_ops *pops = &rproc->sci->ops.proc_ops; + int ret; + + dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size); + + /* request for the processor */ + ret = pops->proc_request(rproc->sci, rproc->proc_id); + if (ret) { + dev_err(dev, "Requesting processor failed %d\n", ret); + return ret; + } + + ret = pops->set_proc_boot_cfg(rproc->sci, rproc->proc_id, addr, 0, 0); + if (ret) { + dev_err(dev, "set_proc_boot_cfg failed %d\n", ret); + return ret; + } + + dev_dbg(dev, "%s: rproc successfully loaded\n", __func__); + + return 0; +} + +/** + * k3_rproc_start() - Start the remote processor + * @dev: rproc device pointer + * + * Return: 0 if all went ok, else return appropriate error + */ +static int k3_rproc_start(struct udevice *dev) +{ + struct k3_rproc_privdata *rproc = dev_get_priv(dev); + const struct ti_sci_proc_ops *pops = &rproc->sci->ops.proc_ops; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = power_domain_on(&rproc->gtc_pwrdmn); + if (ret) { + dev_err(dev, "power_domain_on() failed: %d\n", ret); + return ret; + } + + /* Enable the timer before starting remote core */ + writel(GTC_CNTR_EN, rproc->gtc_base + GTC_CNTCR_REG); + + /* + * Setting the right clock frequency would have taken care by + * assigned-clock-rates during the device probe. So no need to + * set the frequency again here. + */ + ret = power_domain_on(&rproc->rproc_pwrdmn); + if (ret) { + dev_err(dev, "power_domain_on() failed: %d\n", ret); + return ret; + } + + if (rproc->host_id != INVALID_ID) { + ret = pops->proc_handover(rproc->sci, rproc->proc_id, + rproc->host_id); + if (ret) { + dev_err(dev, "Handover processor failed %d\n", ret); + return ret; + } + } else { + ret = pops->proc_release(rproc->sci, rproc->proc_id); + if (ret) { + dev_err(dev, "Processor release failed %d\n", ret); + return ret; + } + } + + dev_dbg(dev, "%s: rproc successfully started\n", __func__); + + return 0; +} + +/** + * k3_rproc_init() - Initialize the remote processor + * @dev: rproc device pointer + * + * Return: 0 if all went ok, else return appropriate error + */ +static int k3_rproc_init(struct udevice *dev) +{ + dev_dbg(dev, "%s\n", __func__); + + /* Enable the module */ + dev_dbg(dev, "%s: rproc successfully initialized\n", __func__); + + return 0; +} + +static const struct dm_rproc_ops k3_rproc_ops = { + .init = k3_rproc_init, + .load = k3_rproc_load, + .start = k3_rproc_start, +}; + +/** + * k3_of_to_priv() - generate private data from device tree + * @dev: corresponding k3 remote processor device + * @priv: pointer to driver specific private data + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_rproc_of_to_priv(struct udevice *dev, + struct k3_rproc_privdata *rproc) +{ + int ret; + + dev_dbg(dev, "%s\n", __func__); + + ret = power_domain_get_by_index(dev, &rproc->rproc_pwrdmn, 1); + if (ret) { + dev_err(dev, "power_domain_get() failed: %d\n", ret); + return ret; + } + + ret = power_domain_get_by_index(dev, &rproc->gtc_pwrdmn, 0); + if (ret) { + dev_err(dev, "power_domain_get() failed: %d\n", ret); + return ret; + } + + ret = reset_get_by_index(dev, 0, &rproc->rproc_rst); + if (ret) { + dev_err(dev, "reset_get() failed: %d\n", ret); + return ret; + } + + rproc->sci = ti_sci_get_by_phandle(dev, "ti,sci"); + if (IS_ERR(rproc->sci)) { + dev_err(dev, "ti_sci get failed: %d\n", ret); + return PTR_ERR(rproc->sci); + } + + rproc->gtc_base = dev_read_addr_ptr(dev); + if (!rproc->gtc_base) { + dev_err(dev, "Get address failed\n"); + return -ENODEV; + } + + rproc->proc_id = dev_read_u32_default(dev, "ti,sci-proc-id", + INVALID_ID); + rproc->host_id = dev_read_u32_default(dev, "ti,sci-host-id", + INVALID_ID); + + return 0; +} + +/** + * k3_rproc_probe() - Basic probe + * @dev: corresponding k3 remote processor device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_rproc_probe(struct udevice *dev) +{ + struct k3_rproc_privdata *priv; + int ret; + + dev_dbg(dev, "%s\n", __func__); + + priv = dev_get_priv(dev); + + ret = k3_rproc_of_to_priv(dev, priv); + if (ret) { + dev_dbg(dev, "%s: Probe failed with error %d\n", __func__, ret); + return ret; + } + + dev_dbg(dev, "Remoteproc successfully probed\n"); + + return 0; +} + +static const struct udevice_id k3_rproc_ids[] = { + { .compatible = "ti,am654-rproc"}, + {} +}; + +U_BOOT_DRIVER(k3_rproc) = { + .name = "k3_rproc", + .of_match = k3_rproc_ids, + .id = UCLASS_REMOTEPROC, + .ops = &k3_rproc_ops, + .probe = k3_rproc_probe, + .priv_auto_alloc_size = sizeof(struct k3_rproc_privdata), +}; diff --git a/drivers/remoteproc/k3_system_controller.c b/drivers/remoteproc/k3_system_controller.c new file mode 100644 index 0000000000..214ea18d8a --- /dev/null +++ b/drivers/remoteproc/k3_system_controller.c @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments' K3 System Controller Driver + * + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <remoteproc.h> +#include <errno.h> +#include <mailbox.h> +#include <linux/soc/ti/k3-sec-proxy.h> + +#define K3_MSG_R5_TO_M3_M3FW 0x8105 +#define K3_MSG_M3_TO_R5_CERT_RESULT 0x8805 +#define K3_MSG_M3_TO_R5_BOOT_NOTIFICATION 0x000A + +#define K3_FLAGS_MSG_CERT_AUTH_PASS 0x555555 +#define K3_FLAGS_MSG_CERT_AUTH_FAIL 0xffffff + +/** + * struct k3_sysctrler_msg_hdr - Generic Header for Messages and responses. + * @cmd_id: Message ID. One of K3_MSG_* + * @host_id: Host ID of the message + * @seq_ne: Message identifier indicating a transfer sequence. + * @flags: Flags for the message. + */ +struct k3_sysctrler_msg_hdr { + u16 cmd_id; + u8 host_id; + u8 seq_nr; + u32 flags; +} __packed; + +/** + * struct k3_sysctrler_load_msg - Message format for Firmware loading + * @hdr: Generic message hdr + * @buffer_address: Address at which firmware is located. + * @buffer_size: Size of the firmware. + */ +struct k3_sysctrler_load_msg { + struct k3_sysctrler_msg_hdr hdr; + u32 buffer_address; + u32 buffer_size; +} __packed; + +/** + * struct k3_sysctrler_boot_notification_msg - Message format for boot + * notification + * @checksum: Checksum for the entire message + * @reserved: Reserved for future use. + * @hdr: Generic message hdr + */ +struct k3_sysctrler_boot_notification_msg { + u16 checksum; + u16 reserved; + struct k3_sysctrler_msg_hdr hdr; +} __packed; + +/** + * struct k3_sysctrler_desc - Description of SoC integration. + * @host_id: Host identifier representing the compute entity + * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds) + * @max_msg_size: Maximum size of data per message that can be handled. + */ +struct k3_sysctrler_desc { + u8 host_id; + int max_rx_timeout_us; + int max_msg_size; +}; + +/** + * struct k3_sysctrler_privdata - Structure representing System Controller data. + * @chan_tx: Transmit mailbox channel + * @chan_rx: Receive mailbox channel + * @desc: SoC description for this instance + * @seq_nr: Counter for number of messages sent. + */ +struct k3_sysctrler_privdata { + struct mbox_chan chan_tx; + struct mbox_chan chan_rx; + struct k3_sysctrler_desc *desc; + u32 seq_nr; +}; + +static inline +void k3_sysctrler_load_msg_setup(struct k3_sysctrler_load_msg *fw, + struct k3_sysctrler_privdata *priv, + ulong addr, ulong size) +{ + fw->hdr.cmd_id = K3_MSG_R5_TO_M3_M3FW; + fw->hdr.host_id = priv->desc->host_id; + fw->hdr.seq_nr = priv->seq_nr++; + fw->hdr.flags = 0x0; + fw->buffer_address = addr; + fw->buffer_size = size; +} + +static int k3_sysctrler_load_response(u32 *buf) +{ + struct k3_sysctrler_load_msg *fw; + + fw = (struct k3_sysctrler_load_msg *)buf; + + /* Check for proper response ID */ + if (fw->hdr.cmd_id != K3_MSG_M3_TO_R5_CERT_RESULT) { + dev_err(dev, "%s: Command expected 0x%x, but received 0x%x\n", + __func__, K3_MSG_M3_TO_R5_CERT_RESULT, fw->hdr.cmd_id); + return -EINVAL; + } + + /* Check for certificate authentication result */ + if (fw->hdr.flags == K3_FLAGS_MSG_CERT_AUTH_FAIL) { + dev_err(dev, "%s: Firmware certificate authentication failed\n", + __func__); + return -EINVAL; + } else if (fw->hdr.flags != K3_FLAGS_MSG_CERT_AUTH_PASS) { + dev_err(dev, "%s: Firmware Load response Invalid %d\n", + __func__, fw->hdr.flags); + return -EINVAL; + } + + debug("%s: Firmware authentication passed\n", __func__); + + return 0; +} + +static int k3_sysctrler_boot_notification_response(u32 *buf) +{ + struct k3_sysctrler_boot_notification_msg *boot; + + boot = (struct k3_sysctrler_boot_notification_msg *)buf; + + /* ToDo: Verify checksum */ + + /* Check for proper response ID */ + if (boot->hdr.cmd_id != K3_MSG_M3_TO_R5_BOOT_NOTIFICATION) { + dev_err(dev, "%s: Command expected 0x%x, but received 0x%x\n", + __func__, K3_MSG_M3_TO_R5_BOOT_NOTIFICATION, + boot->hdr.cmd_id); + return -EINVAL; + } + + debug("%s: Boot notification received\n", __func__); + + return 0; +} + +/** + * k3_sysctrler_load() - Loadup the K3 remote processor + * @dev: corresponding K3 remote processor device + * @addr: Address in memory where image binary is stored + * @size: Size in bytes of the image binary + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_sysctrler_load(struct udevice *dev, ulong addr, ulong size) +{ + struct k3_sysctrler_privdata *priv = dev_get_priv(dev); + struct k3_sysctrler_load_msg firmware; + struct k3_sec_proxy_msg msg; + int ret; + + debug("%s: Loading binary from 0x%08lX, size 0x%08lX\n", + __func__, addr, size); + + memset(&firmware, 0, sizeof(firmware)); + memset(&msg, 0, sizeof(msg)); + + /* Setup the message */ + k3_sysctrler_load_msg_setup(&firmware, priv, addr, size); + msg.len = sizeof(firmware); + msg.buf = (u32 *)&firmware; + + /* Send the message */ + ret = mbox_send(&priv->chan_tx, &msg); + if (ret) { + dev_err(dev, "%s: Firmware Loading failed. ret = %d\n", + __func__, ret); + return ret; + } + + /* Receive the response */ + ret = mbox_recv(&priv->chan_rx, &msg, priv->desc->max_rx_timeout_us); + if (ret) { + dev_err(dev, "%s: Firmware Load response failed. ret = %d\n", + __func__, ret); + return ret; + } + + /* Process the response */ + ret = k3_sysctrler_load_response(msg.buf); + if (ret) + return ret; + + debug("%s: Firmware Loaded successfully on dev %s\n", + __func__, dev->name); + + return 0; +} + +/** + * k3_sysctrler_start() - Start the remote processor + * Note that while technically the K3 system controller starts up + * automatically after its firmware got loaded we still want to + * utilize the rproc start operation for other startup-related + * tasks. + * @dev: device to operate upon + * + * Return: 0 if all went ok, else return appropriate error + */ +static int k3_sysctrler_start(struct udevice *dev) +{ + struct k3_sysctrler_privdata *priv = dev_get_priv(dev); + struct k3_sec_proxy_msg msg; + int ret; + + debug("%s(dev=%p)\n", __func__, dev); + + /* Receive the boot notification. Note that it is sent only once. */ + ret = mbox_recv(&priv->chan_rx, &msg, priv->desc->max_rx_timeout_us); + if (ret) { + dev_err(dev, "%s: Boot Notification response failed. ret = %d\n", + __func__, ret); + return ret; + } + + /* Process the response */ + ret = k3_sysctrler_boot_notification_response(msg.buf); + if (ret) + return ret; + + debug("%s: Boot notification received successfully on dev %s\n", + __func__, dev->name); + + return 0; +} + +static const struct dm_rproc_ops k3_sysctrler_ops = { + .load = k3_sysctrler_load, + .start = k3_sysctrler_start, +}; + +/** + * k3_of_to_priv() - generate private data from device tree + * @dev: corresponding k3 remote processor device + * @priv: pointer to driver specific private data + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_of_to_priv(struct udevice *dev, + struct k3_sysctrler_privdata *priv) +{ + int ret; + + ret = mbox_get_by_name(dev, "tx", &priv->chan_tx); + if (ret) { + dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n", + __func__, ret); + return ret; + } + + ret = mbox_get_by_name(dev, "rx", &priv->chan_rx); + if (ret) { + dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n", + __func__, ret); + return ret; + } + + return 0; +} + +/** + * k3_sysctrler_probe() - Basic probe + * @dev: corresponding k3 remote processor device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int k3_sysctrler_probe(struct udevice *dev) +{ + struct k3_sysctrler_privdata *priv; + int ret; + + debug("%s(dev=%p)\n", __func__, dev); + + priv = dev_get_priv(dev); + + ret = k3_of_to_priv(dev, priv); + if (ret) { + dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret); + return ret; + } + + priv->desc = (void *)dev_get_driver_data(dev); + priv->seq_nr = 0; + + return 0; +} + +static const struct k3_sysctrler_desc k3_sysctrler_am654_desc = { + .host_id = 4, /* HOST_ID_R5_1 */ + .max_rx_timeout_us = 400000, + .max_msg_size = 60, +}; + +static const struct udevice_id k3_sysctrler_ids[] = { + { + .compatible = "ti,am654-system-controller", + .data = (ulong)&k3_sysctrler_am654_desc, + }, + {} +}; + +U_BOOT_DRIVER(k3_sysctrler) = { + .name = "k3_system_controller", + .of_match = k3_sysctrler_ids, + .id = UCLASS_REMOTEPROC, + .ops = &k3_sysctrler_ops, + .probe = k3_sysctrler_probe, + .priv_auto_alloc_size = sizeof(struct k3_sysctrler_privdata), +}; diff --git a/drivers/remoteproc/rproc-uclass.c b/drivers/remoteproc/rproc-uclass.c index 1fc3d424b3..c8a41a6332 100644 --- a/drivers/remoteproc/rproc-uclass.c +++ b/drivers/remoteproc/rproc-uclass.c @@ -272,6 +272,25 @@ int rproc_init(void) return ret; } +int rproc_dev_init(int id) +{ + struct udevice *dev = NULL; + int ret; + + ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, id, &dev); + if (ret) { + debug("Unknown remote processor id '%d' requested(%d)\n", + id, ret); + return ret; + } + + ret = device_probe(dev); + if (ret) + debug("%s: Failed to initialize - %d\n", dev->name, ret); + + return ret; +} + int rproc_load(int id, ulong addr, ulong size) { struct udevice *dev = NULL; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 33c39b7fb6..9c5208b7da 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -49,6 +49,14 @@ config TEGRA186_RESET Enable support for manipulating Tegra's on-SoC reset signals via IPC requests to the BPMP (Boot and Power Management Processor). +config RESET_TI_SCI + bool "TI System Control Interface (TI SCI) reset driver" + depends on DM_RESET && TI_SCI_PROTOCOL + help + This enables the reset driver support over TI System Control Interface + available on some new TI's SoCs. If you wish to use reset resources + managed by the TI System Controller, say Y here. Otherwise, say N. + config RESET_BCM6345 bool "Reset controller driver for BCM6345" depends on DM_RESET && ARCH_BMIPS diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index ad08be4c8c..abdfa0c663 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_STI_RESET) += sti-reset.o obj-$(CONFIG_STM32_RESET) += stm32-reset.o obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o +obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o diff --git a/drivers/reset/reset-ti-sci.c b/drivers/reset/reset-ti-sci.c new file mode 100644 index 0000000000..c8a76dfb04 --- /dev/null +++ b/drivers/reset/reset-ti-sci.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments System Control Interface (TI SCI) reset driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg <dannenberg@ti.com> + * + * Loosely based on Linux kernel reset-ti-sci.c... + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <reset-uclass.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +/** + * struct ti_sci_reset_data - reset controller information structure + * @sci: TI SCI handle used for communication with system controller + */ +struct ti_sci_reset_data { + const struct ti_sci_handle *sci; +}; + +static int ti_sci_reset_probe(struct udevice *dev) +{ + struct ti_sci_reset_data *data = dev_get_priv(dev); + + debug("%s(dev=%p)\n", __func__, dev); + + if (!data) + return -ENOMEM; + + /* Store handle for communication with the system controller */ + data->sci = ti_sci_get_handle(dev); + if (IS_ERR(data->sci)) + return PTR_ERR(data->sci); + + return 0; +} + +static int ti_sci_reset_of_xlate(struct reset_ctl *rst, + struct ofnode_phandle_args *args) +{ + debug("%s(rst=%p, args_count=%d)\n", __func__, rst, args->args_count); + + if (args->args_count != 2) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + /* + * On TI SCI-based devices, the reset provider id field is used as a + * device ID, and the data field is used as the associated reset mask. + */ + rst->id = args->args[0]; + rst->data = args->args[1]; + + return 0; +} + +static int ti_sci_reset_request(struct reset_ctl *rst) +{ + debug("%s(rst=%p)\n", __func__, rst); + return 0; +} + +static int ti_sci_reset_free(struct reset_ctl *rst) +{ + debug("%s(rst=%p)\n", __func__, rst); + return 0; +} + +/** + * ti_sci_reset_set() - program a device's reset + * @rst: Handle to a single reset signal + * @assert: boolean flag to indicate assert or deassert + * + * This is a common internal function used to assert or deassert a device's + * reset using the TI SCI protocol. The device's reset is asserted if the + * @assert argument is true, or deasserted if @assert argument is false. + * The mechanism itself is a read-modify-write procedure, the current device + * reset register is read using a TI SCI device operation, the new value is + * set or un-set using the reset's mask, and the new reset value written by + * using another TI SCI device operation. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int ti_sci_reset_set(struct reset_ctl *rst, bool assert) +{ + struct ti_sci_reset_data *data = dev_get_priv(rst->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops; + u32 reset_state; + int ret; + + ret = dops->get_device_resets(sci, rst->id, &reset_state); + if (ret) { + dev_err(rst->dev, "%s: get_device_resets failed (%d)\n", + __func__, ret); + return ret; + } + + if (assert) + reset_state |= rst->data; + else + reset_state &= ~rst->data; + + ret = dops->set_device_resets(sci, rst->id, reset_state); + if (ret) { + dev_err(rst->dev, "%s: set_device_resets failed (%d)\n", + __func__, ret); + return ret; + } + + return 0; +} + +/** + * ti_sci_reset_assert() - assert device reset + * @rst: Handle to a single reset signal + * + * This function implements the reset driver op to assert a device's reset + * using the TI SCI protocol. This invokes the function ti_sci_reset_set() + * with the corresponding parameters as passed in, but with the @assert + * argument set to true for asserting the reset. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int ti_sci_reset_assert(struct reset_ctl *rst) +{ + debug("%s(rst=%p)\n", __func__, rst); + return ti_sci_reset_set(rst, true); +} + +/** + * ti_sci_reset_deassert() - deassert device reset + * @rst: Handle to a single reset signal + * + * This function implements the reset driver op to deassert a device's reset + * using the TI SCI protocol. This invokes the function ti_sci_reset_set() + * with the corresponding parameters as passed in, but with the @assert + * argument set to false for deasserting the reset. + * + * Return: 0 for successful request, else a corresponding error value + */ +static int ti_sci_reset_deassert(struct reset_ctl *rst) +{ + debug("%s(rst=%p)\n", __func__, rst); + return ti_sci_reset_set(rst, false); +} + +/** + * ti_sci_reset_status() - check device reset status + * @rst: Handle to a single reset signal + * + * This function implements the reset driver op to return the status of a + * device's reset using the TI SCI protocol. The reset register value is read + * by invoking the TI SCI device operation .get_device_resets(), and the + * status of the specific reset is extracted and returned using this reset's + * reset mask. + * + * Return: 0 if reset is deasserted, or a non-zero value if reset is asserted + */ +static int ti_sci_reset_status(struct reset_ctl *rst) +{ + struct ti_sci_reset_data *data = dev_get_priv(rst->dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops; + u32 reset_state; + int ret; + + debug("%s(rst=%p)\n", __func__, rst); + + ret = dops->get_device_resets(sci, rst->id, &reset_state); + if (ret) { + dev_err(rst->dev, "%s: get_device_resets failed (%d)\n", + __func__, ret); + return ret; + } + + return reset_state & rst->data; +} + +static const struct udevice_id ti_sci_reset_of_match[] = { + { .compatible = "ti,sci-reset", }, + { /* sentinel */ }, +}; + +static struct reset_ops ti_sci_reset_ops = { + .of_xlate = ti_sci_reset_of_xlate, + .request = ti_sci_reset_request, + .free = ti_sci_reset_free, + .rst_assert = ti_sci_reset_assert, + .rst_deassert = ti_sci_reset_deassert, + .rst_status = ti_sci_reset_status, +}; + +U_BOOT_DRIVER(ti_sci_reset) = { + .name = "ti-sci-reset", + .id = UCLASS_RESET, + .of_match = ti_sci_reset_of_match, + .probe = ti_sci_reset_probe, + .priv_auto_alloc_size = sizeof(struct ti_sci_reset_data), + .ops = &ti_sci_reset_ops, +}; diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index 3899537635..89e39c6b5a 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -192,6 +192,15 @@ int reset_deassert_bulk(struct reset_ctl_bulk *bulk) return 0; } +int reset_status(struct reset_ctl *reset_ctl) +{ + struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); + + debug("%s(reset_ctl=%p)\n", __func__, reset_ctl); + + return ops->rst_status(reset_ctl); +} + int reset_release_all(struct reset_ctl *reset_ctl, int count) { int i, ret; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 16246bec2b..bc6ac8cd32 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -6,7 +6,6 @@ #include <common.h> #include <dm.h> -#include <inttypes.h> #include <pci.h> #include <scsi.h> #include <dm/device-internal.h> @@ -196,7 +195,7 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, blks = 0; } debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", + ", blccnt %x buffer %lX\n", start, smallblks, buf_addr); if (scsi_exec(bdev, pccb)) { scsi_print_error(pccb); @@ -206,7 +205,7 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, buf_addr += pccb->datalen; } while (blks != 0); debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + ", blccnt %x buffer %lX\n", start, smallblks, buf_addr); return blkcnt; } @@ -260,7 +259,7 @@ static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, start += blks; blks = 0; } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + debug("%s: startblk " LBAF ", blccnt %x buffer %lx\n", __func__, start, smallblks, buf_addr); if (scsi_exec(bdev, pccb)) { scsi_print_error(pccb); @@ -269,7 +268,7 @@ static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, } buf_addr += pccb->datalen; } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + debug("%s: end startblk " LBAF ", blccnt %x buffer %lX\n", __func__, start, smallblks, buf_addr); return blkcnt; } diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 766e5ced03..5fa27254e3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -625,6 +625,15 @@ config MSM_SERIAL for example APQ8016 and MSM8916. Single baudrate is supported in current implementation (115200). +config OMAP_SERIAL + bool "Support for OMAP specific UART" + depends on DM_SERIAL + default y if (ARCH_OMAP2PLUS || ARCH_K3) + select SYS_NS16550 + help + If you have an TI based SoC and want to use the on-chip serial + port, say Y to this option. If unsure say N. + config OWL_SERIAL bool "Actions Semi OWL UART" depends on DM_SERIAL && ARCH_OWL diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 9fa81d855d..03dc29ee2e 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o obj-$(CONFIG_OWL_SERIAL) += serial_owl.o +obj-$(CONFIG_OMAP_SERIAL) += serial_omap.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/arm_dcc.c b/drivers/serial/arm_dcc.c index c83a3fe8ee..43e8691a93 100644 --- a/drivers/serial/arm_dcc.c +++ b/drivers/serial/arm_dcc.c @@ -19,7 +19,7 @@ #include <dm.h> #include <serial.h> -#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7A) +#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7A) || defined(CONFIG_CPU_V7R) /* * ARMV6 & ARMV7 */ diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 9c80090aa7..f9041aa626 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -175,7 +175,7 @@ void NS16550_init(NS16550_t com_port, int baud_divisor) ; serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); -#if defined(CONFIG_ARCH_OMAP2PLUS) +#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_OMAP_SERIAL) serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/ #endif @@ -183,7 +183,8 @@ void NS16550_init(NS16550_t com_port, int baud_divisor) serial_out(ns16550_getfcr(com_port), &com_port->fcr); if (baud_divisor != -1) NS16550_setbrg(com_port, baud_divisor); -#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_SOC_DA8XX) +#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_SOC_DA8XX) || \ + defined(CONFIG_OMAP_SERIAL) /* /16 is proper to hit 115200 with 48MHz */ serial_out(0, &com_port->mdr1); #endif @@ -279,42 +280,6 @@ DEBUG_UART_FUNCS #endif -#ifdef CONFIG_DEBUG_UART_OMAP - -#include <debug_uart.h> - -static inline void _debug_uart_init(void) -{ - struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; - int baud_divisor; - - baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, - CONFIG_BAUDRATE); - serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER); - serial_dout(&com_port->mdr1, 0x7); - serial_dout(&com_port->mcr, UART_MCRVAL); - serial_dout(&com_port->fcr, UART_FCR_DEFVAL); - - serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); - serial_dout(&com_port->dll, baud_divisor & 0xff); - serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff); - serial_dout(&com_port->lcr, UART_LCRVAL); - serial_dout(&com_port->mdr1, 0x0); -} - -static inline void _debug_uart_putc(int ch) -{ - struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; - - while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) - ; - serial_dout(&com_port->thr, ch); -} - -DEBUG_UART_FUNCS - -#endif - #ifdef CONFIG_DM_SERIAL static int ns16550_serial_putc(struct udevice *dev, const char ch) { @@ -489,12 +454,6 @@ static const struct udevice_id ns16550_serial_ids[] = { { .compatible = "ingenic,jz4780-uart", .data = PORT_JZ4780 }, { .compatible = "nvidia,tegra20-uart", .data = PORT_NS16550 }, { .compatible = "snps,dw-apb-uart", .data = PORT_NS16550 }, - { .compatible = "ti,omap2-uart", .data = PORT_NS16550 }, - { .compatible = "ti,omap3-uart", .data = PORT_NS16550 }, - { .compatible = "ti,omap4-uart", .data = PORT_NS16550 }, - { .compatible = "ti,am3352-uart", .data = PORT_NS16550 }, - { .compatible = "ti,am4372-uart", .data = PORT_NS16550 }, - { .compatible = "ti,dra742-uart", .data = PORT_NS16550 }, {} }; #endif /* OF_CONTROL && !OF_PLATDATA */ diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index a60dabe588..94b4fdfb17 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -143,6 +143,19 @@ static int sandbox_serial_getc(struct udevice *dev) return result; } +static int sandbox_serial_setconfig(struct udevice *dev, uint serial_config) +{ + u8 parity = SERIAL_GET_PARITY(serial_config); + u8 bits = SERIAL_GET_BITS(serial_config); + u8 stop = SERIAL_GET_STOP(serial_config); + + if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP || + parity != SERIAL_PAR_NONE) + return -ENOTSUPP; /* not supported in driver*/ + + return 0; +} + static const char * const ansi_colour[] = { "black", "red", "green", "yellow", "blue", "megenta", "cyan", "white", @@ -173,6 +186,7 @@ static const struct dm_serial_ops sandbox_serial_ops = { .putc = sandbox_serial_putc, .pending = sandbox_serial_pending, .getc = sandbox_serial_getc, + .setconfig = sandbox_serial_setconfig, }; static const struct udevice_id sandbox_serial_ids[] = { diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 321d23ee93..ffdcae0931 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -228,6 +228,9 @@ static int _serial_getc(struct udevice *dev) struct serial_dev_priv *upriv = dev_get_uclass_priv(dev); char val; + if (upriv->rd_ptr == upriv->wr_ptr) + return __serial_getc(dev); + val = upriv->buf[upriv->rd_ptr++]; upriv->rd_ptr %= CONFIG_SERIAL_RX_BUFFER_SIZE; @@ -287,6 +290,20 @@ void serial_setbrg(void) ops->setbrg(gd->cur_serial_dev, gd->baudrate); } +int serial_setconfig(uint config) +{ + struct dm_serial_ops *ops; + + if (!gd->cur_serial_dev) + return 0; + + ops = serial_get_ops(gd->cur_serial_dev); + if (ops->setconfig) + return ops->setconfig(gd->cur_serial_dev, config); + + return 0; +} + void serial_stdio_init(void) { } @@ -398,6 +415,8 @@ static int serial_post_probe(struct udevice *dev) ops->pending += gd->reloc_off; if (ops->clear) ops->clear += gd->reloc_off; + if (ops->setconfig) + ops->setconfig += gd->reloc_off; #if CONFIG_POST & CONFIG_SYS_POST_UART if (ops->loop) ops->loop += gd->reloc_off diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c new file mode 100644 index 0000000000..d8a047bb71 --- /dev/null +++ b/drivers/serial/serial_omap.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments' OMAP serial driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#include <common.h> +#include <debug_uart.h> +#include <dm.h> +#include <dt-structs.h> +#include <ns16550.h> +#include <serial.h> +#include <clk.h> + +#ifndef CONFIG_SYS_NS16550_CLK +#define CONFIG_SYS_NS16550_CLK 0 +#endif + +#ifdef CONFIG_DEBUG_UART_OMAP + +#include <debug_uart.h> + +static inline void _debug_uart_init(void) +{ + struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; + int baud_divisor; + + baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); + serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER); + serial_dout(&com_port->mdr1, 0x7); + serial_dout(&com_port->mcr, UART_MCRVAL); + serial_dout(&com_port->fcr, UART_FCR_DEFVAL); + + serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); + serial_dout(&com_port->dll, baud_divisor & 0xff); + serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff); + serial_dout(&com_port->lcr, UART_LCRVAL); + serial_dout(&com_port->mdr1, 0x0); +} + +static inline void _debug_uart_putc(int ch) +{ + struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; + + while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) + ; + serial_dout(&com_port->thr, ch); +} + +DEBUG_UART_FUNCS + +#endif + +#if CONFIG_IS_ENABLED(DM_SERIAL) + +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) +static int omap_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct ns16550_platdata *plat = dev->platdata; + fdt_addr_t addr; + struct clk clk; + int err; + + /* try Processor Local Bus device first */ + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE); + + plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0); + plat->reg_shift = 2; + + err = clk_get_by_index(dev, 0, &clk); + if (!err) { + err = clk_get_rate(&clk); + if (!IS_ERR_VALUE(err)) + plat->clock = err; + } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) { + debug("omap serial failed to get clock\n"); + return err; + } + + if (!plat->clock) + plat->clock = dev_read_u32_default(dev, "clock-frequency", + CONFIG_SYS_NS16550_CLK); + if (!plat->clock) { + debug("omap serial clock not defined\n"); + return -EINVAL; + } + + plat->fcr = UART_FCR_DEFVAL; + + return 0; +} + +static const struct udevice_id omap_serial_ids[] = { + { .compatible = "ti,omap2-uart", }, + { .compatible = "ti,omap3-uart", }, + { .compatible = "ti,omap4-uart", }, + { .compatible = "ti,am3352-uart", }, + { .compatible = "ti,am4372-uart", }, + { .compatible = "ti,dra742-uart", }, + {} +}; +#endif /* OF_CONTROL && !OF_PLATDATA */ + +#if CONFIG_IS_ENABLED(SERIAL_PRESENT) +U_BOOT_DRIVER(omap_serial) = { + .name = "omap_serial", + .id = UCLASS_SERIAL, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .of_match = omap_serial_ids, + .ofdata_to_platdata = omap_serial_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), +#endif + .priv_auto_alloc_size = sizeof(struct NS16550), + .probe = ns16550_serial_probe, + .ops = &ns16550_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; +#endif +#endif /* DM_SERIAL */ diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index f26234549c..66e02d5689 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -47,20 +47,28 @@ static int stm32_serial_setbrg(struct udevice *dev, int baudrate) return 0; } -static int stm32_serial_setparity(struct udevice *dev, enum serial_par parity) +static int stm32_serial_setconfig(struct udevice *dev, uint serial_config) { struct stm32x7_serial_platdata *plat = dev_get_platdata(dev); bool stm32f4 = plat->uart_info->stm32f4; u8 uart_enable_bit = plat->uart_info->uart_enable_bit; u32 cr1 = plat->base + CR1_OFFSET(stm32f4); u32 config = 0; - - if (stm32f4) - return -EINVAL; /* not supported in driver*/ + uint parity = SERIAL_GET_PARITY(serial_config); + uint bits = SERIAL_GET_BITS(serial_config); + uint stop = SERIAL_GET_STOP(serial_config); + + /* + * only parity config is implemented, check if other serial settings + * are the default one. + * (STM32F4 serial IP didn't support parity setting) + */ + if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP || stm32f4) + return -ENOTSUPP; /* not supported in driver*/ clrbits_le32(cr1, USART_CR1_RE | USART_CR1_TE | BIT(uart_enable_bit)); /* update usart configuration (uart need to be disable) - * PCE: parity check control + * PCE: parity check enable * PS : '0' : Even / '1' : Odd * M[1:0] = '00' : 8 Data bits * M[1:0] = '01' : 9 Data bits with parity @@ -77,6 +85,7 @@ static int stm32_serial_setparity(struct udevice *dev, enum serial_par parity) config = USART_CR1_PCE | USART_CR1_M0; break; } + clrsetbits_le32(cr1, USART_CR1_PCE | USART_CR1_PS | USART_CR1_M1 | USART_CR1_M0, @@ -210,7 +219,7 @@ static const struct dm_serial_ops stm32_serial_ops = { .pending = stm32_serial_pending, .getc = stm32_serial_getc, .setbrg = stm32_serial_setbrg, - .setparity = stm32_serial_setparity + .setconfig = stm32_serial_setconfig }; U_BOOT_DRIVER(serial_stm32) = { diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 9b2fda4d25..ed1d437fb0 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -36,6 +36,13 @@ config SYSRESET_PSCI Enable PSCI SYSTEM_RESET function call. To use this, PSCI firmware must be running on your system. +config SYSRESET_TI_SCI + bool "TI System Control Interface (TI SCI) system reset driver" + depends on TI_SCI_PROTOCOL + help + This enables the system reset driver support over TI System Control + Interface available on some new TI's SoCs. + endif config SYSRESET_SYSCON diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index 707f1d7469..02ee1df6b0 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SYSRESET) += sysreset-uclass.o obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o +obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o obj-$(CONFIG_SYSRESET_X86) += sysreset_x86.o diff --git a/drivers/sysreset/sysreset-ti-sci.c b/drivers/sysreset/sysreset-ti-sci.c new file mode 100644 index 0000000000..890a607c4b --- /dev/null +++ b/drivers/sysreset/sysreset-ti-sci.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments System Control Interface (TI SCI) system reset driver + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Andreas Dannenberg <dannenberg@ti.com> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <sysreset.h> +#include <linux/soc/ti/ti_sci_protocol.h> + +/** + * struct ti_sci_sysreset_data - sysreset controller information structure + * @sci: TI SCI handle used for communication with system controller + */ +struct ti_sci_sysreset_data { + const struct ti_sci_handle *sci; +}; + +static int ti_sci_sysreset_probe(struct udevice *dev) +{ + struct ti_sci_sysreset_data *data = dev_get_priv(dev); + + debug("%s(dev=%p)\n", __func__, dev); + + if (!data) + return -ENOMEM; + + /* Store handle for communication with the system controller */ + data->sci = ti_sci_get_handle(dev); + if (IS_ERR(data->sci)) + return PTR_ERR(data->sci); + + return 0; +} + +static int ti_sci_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + struct ti_sci_sysreset_data *data = dev_get_priv(dev); + const struct ti_sci_handle *sci = data->sci; + const struct ti_sci_core_ops *cops = &sci->ops.core_ops; + int ret; + + debug("%s(dev=%p, type=%d)\n", __func__, dev, type); + + ret = cops->reboot_device(sci); + if (ret) + dev_err(rst->dev, "%s: reboot_device failed (%d)\n", + __func__, ret); + + return ret; +} + +static struct sysreset_ops ti_sci_sysreset_ops = { + .request = ti_sci_sysreset_request, +}; + +static const struct udevice_id ti_sci_sysreset_of_match[] = { + { .compatible = "ti,sci-sysreset", }, + { /* sentinel */ }, +}; + +U_BOOT_DRIVER(ti_sci_sysreset) = { + .name = "ti-sci-sysreset", + .id = UCLASS_SYSRESET, + .of_match = ti_sci_sysreset_of_match, + .probe = ti_sci_sysreset_probe, + .priv_auto_alloc_size = sizeof(struct ti_sci_sysreset_data), + .ops = &ti_sci_sysreset_ops, +}; diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c index 3f847984cb..f10df69092 100644 --- a/drivers/timer/omap-timer.c +++ b/drivers/timer/omap-timer.c @@ -51,7 +51,7 @@ static int omap_timer_get_count(struct udevice *dev, u64 *count) { struct omap_timer_priv *priv = dev_get_priv(dev); - *count = readl(&priv->regs->tcrr); + *count = timer_conv_64(readl(&priv->regs->tcrr)); return 0; } @@ -61,10 +61,12 @@ static int omap_timer_probe(struct udevice *dev) struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct omap_timer_priv *priv = dev_get_priv(dev); - uc_priv->clock_rate = TIMER_CLOCK; + if (!uc_priv->clock_rate) + uc_priv->clock_rate = TIMER_CLOCK; /* start the counter ticking up, reload value on overflow */ writel(0, &priv->regs->tldr); + writel(0, &priv->regs->tcrr); /* enable timer */ writel((CONFIG_SYS_PTV << 2) | TCLR_PRE_EN | TCLR_AUTO_RELOAD | TCLR_START, &priv->regs->tclr); diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 672fead815..67e2471bd3 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -21,7 +21,6 @@ #include <common.h> #include <ext_common.h> #include <ext4fs.h> -#include <inttypes.h> #include <malloc.h> #include <memalign.h> #include <stddef.h> @@ -210,7 +209,7 @@ void put_ext4(uint64_t off, void *buf, uint32_t size) if ((startblock + (size >> log2blksz)) > (part_offset + fs->total_sect)) { printf("part_offset is " LBAFU "\n", part_offset); - printf("total_sector is %" PRIu64 "\n", fs->total_sect); + printf("total_sector is %llu\n", fs->total_sect); printf("error: overflow occurs\n"); return; } diff --git a/include/asm-generic/int-ll64.h b/include/asm-generic/int-ll64.h new file mode 100644 index 0000000000..7451718a61 --- /dev/null +++ b/include/asm-generic/int-ll64.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * asm-generic/int-ll64.h + * + * Integer declarations for architectures which use "long long" + * for 64-bit types. + */ + +#ifndef _ASM_GENERIC_INT_LL64_H +#define _ASM_GENERIC_INT_LL64_H + +#ifndef __ASSEMBLY__ +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#ifdef __GNUC__ +__extension__ typedef __signed__ long long __s64; +__extension__ typedef unsigned long long __u64; +#else +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +typedef __s8 s8; +typedef __u8 u8; +typedef __s16 s16; +typedef __u16 u16; +typedef __s32 s32; +typedef __u32 u32; +typedef __s64 s64; +typedef __u64 u64; + +#endif /* __ASSEMBLY__ */ + + +#endif /* _ASM_GENERIC_INT_LL64_H */ diff --git a/include/asm-generic/types.h b/include/asm-generic/types.h new file mode 100644 index 0000000000..7c076c56ce --- /dev/null +++ b/include/asm-generic/types.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_TYPES_H +#define _ASM_GENERIC_TYPES_H +/* + * int-ll64 is used everywhere now. + */ +#include <asm-generic/int-ll64.h> + +#endif /* _ASM_GENERIC_TYPES_H */ diff --git a/include/clk.h b/include/clk.h index f6d1cc53a1..c0a20cd47a 100644 --- a/include/clk.h +++ b/include/clk.h @@ -40,10 +40,12 @@ struct udevice; * * @dev: The device which implements the clock signal. * @id: The clock signal ID within the provider. + * @data: An optional data field for scenarios where a single integer ID is not + * sufficient. If used, it can be populated through an .of_xlate op and + * processed during the various clock ops. * - * Currently, the clock API assumes that a single integer ID is enough to - * identify and configure any clock signal for any clock provider. If this - * assumption becomes invalid in the future, the struct could be expanded to + * Should additional information to identify and configure any clock signal + * for any provider be required in the future, the struct could be expanded to * either (a) add more fields to allow clock providers to store additional * information, or (b) replace the id field with an opaque pointer, which the * provider would dynamically allocated during its .of_xlate op, and process @@ -53,10 +55,10 @@ struct udevice; struct clk { struct udevice *dev; /* - * Written by of_xlate. We assume a single id is enough for now. In the - * future, we might add more fields here. + * Written by of_xlate. In the future, we might add more fields here. */ unsigned long id; + unsigned long data; }; /** diff --git a/include/common.h b/include/common.h index 940161f175..83b3bdc58d 100644 --- a/include/common.h +++ b/include/common.h @@ -37,9 +37,6 @@ typedef volatile unsigned char vu_char; #include <flash.h> #include <image.h> -/* Bring in printf format macros if inttypes.h is included */ -#define __STDC_FORMAT_MACROS - #ifdef __LP64__ #define CONFIG_SYS_SUPPORT_64BIT_DATA #endif @@ -359,6 +356,7 @@ void serial_putc_raw(const char); void serial_puts (const char *); int serial_getc (void); int serial_tstc (void); +int serial_setconfig(uint config); /* $(CPU)/speed.c */ int get_clocks (void); diff --git a/include/compiler.h b/include/compiler.h index 957f4b5d49..29507f9840 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -120,13 +120,8 @@ typedef unsigned int uint; #else /* !USE_HOSTCC */ -#ifdef CONFIG_USE_STDINT -/* Provided by gcc. */ -#include <stdint.h> -#else /* Type for `void *' pointers. */ typedef unsigned long int uintptr_t; -#endif #include <linux/string.h> #include <linux/types.h> diff --git a/include/configs/am65x_evm.h b/include/configs/am65x_evm.h new file mode 100644 index 0000000000..65015df131 --- /dev/null +++ b/include/configs/am65x_evm.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Configuration header file for K3 AM654 EVM + * + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#ifndef __CONFIG_AM654_EVM_H +#define __CONFIG_AM654_EVM_H + +#include <linux/sizes.h> +#include <config_distro_bootcmd.h> +#include <environment/ti/mmc.h> + +#define CONFIG_ENV_SIZE (128 << 10) + +/* DDR Configuration */ +#define CONFIG_SYS_SDRAM_BASE1 0x880000000 + +/* SPL Loader Configuration */ +#ifdef CONFIG_TARGET_AM654_A53_EVM +#define CONFIG_SPL_TEXT_BASE 0x80080000 +#endif + +#define CONFIG_SKIP_LOWLEVEL_INIT + +#define CONFIG_SPL_MAX_SIZE CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \ + CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE - 4) + +/* U-Boot general configuration */ +#define EXTRA_ENV_AM65X_BOARD_SETTINGS \ + "findfdt=" \ + "if test $board_name = am65x; then " \ + "setenv name_fdt k3-am654-base-board.dtb; " \ + "else if test $name_fdt = undefined; then " \ + "echo WARNING: Could not determine device tree to use;"\ + "fi; fi; " \ + "setenv fdtfile ${name_fdt}\0" \ + "loadaddr=0x80080000\0" \ + "fdtaddr=0x82000000\0" \ + "name_kern=Image\0" \ + "console=ttyS2,115200n8\0" \ + "args_all=setenv optargs earlycon=ns16550a,mmio32,0x02800000\0" \ + "run_kern=booti ${loadaddr} ${rd_spec} ${fdtaddr}\0" + +/* U-Boot MMC-specific configuration */ +#define EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC \ + "boot=mmc\0" \ + "mmcdev=1\0" \ + "bootpart=1:2\0" \ + "bootdir=/boot\0" \ + "rd_spec=-\0" \ + "init_mmc=run args_all args_mmc\0" \ + "get_fdt_mmc=load mmc ${bootpart} ${fdtaddr} ${bootdir}/${name_fdt}\0" \ + "get_kern_mmc=load mmc ${bootpart} ${loadaddr} " \ + "${bootdir}/${name_kern}\0" + +/* Incorporate settings into the U-Boot environment */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + DEFAULT_MMC_TI_ARGS \ + EXTRA_ENV_AM65X_BOARD_SETTINGS \ + EXTRA_ENV_AM65X_BOARD_SETTINGS_MMC + +/* Now for the remaining common defines */ +#include <configs/ti_armv7_common.h> + +#endif /* __CONFIG_AM654_EVM_H */ diff --git a/include/configs/bcm7260.h b/include/configs/bcm7260.h new file mode 100644 index 0000000000..a2d7f614ce --- /dev/null +++ b/include/configs/bcm7260.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2018 Cisco Systems, Inc. + * + * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org> + * + * Configuration settings for the Broadcom BCM7260 SoC family. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_SYS_NS16550_COM1 0xf040c000 + +#define CONFIG_SYS_TEXT_BASE 0x10100000 +#define CONFIG_SYS_INIT_RAM_ADDR 0x10200000 + +#define CONFIG_SYS_MALLOC_LEN ((40 * 1024) << 10) /* 40 MiB */ + +#include "bcmstb.h" + +#define BCMSTB_SDHCI_BASE 0xf0200300 +#define BCMSTB_TIMER_LOW 0xf0412008 +#define BCMSTB_TIMER_HIGH 0xf041200c +#define BCMSTB_TIMER_FREQUENCY 0xf0412020 +#define BCMSTB_HIF_MSPI_BASE 0xf0203c00 +#define BCMSTB_BSPI_BASE 0xf0203a00 +#define BCMSTB_HIF_SPI_INTR2 0xf0201a00 +#define BCMSTB_CS_REG 0xf0200920 + +/* + * Environment configuration for eMMC. + */ +#define CONFIG_ENV_OFFSET (0x000040a4 * 512) +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_SYS_MMC_ENV_PART 0 + +#define CONFIG_CMD_GPT + +#endif /* __CONFIG_H */ diff --git a/include/configs/bcm7445.h b/include/configs/bcm7445.h index f34cf2d03b..8c675f7733 100644 --- a/include/configs/bcm7445.h +++ b/include/configs/bcm7445.h @@ -10,7 +10,7 @@ #ifndef __CONFIG_H #define __CONFIG_H -#define CONFIG_SYS_NS16550_COM3 0xf040ab00 +#define CONFIG_SYS_NS16550_COM1 0xf040ab00 #define CONFIG_SYS_TEXT_BASE 0x80100000 #define CONFIG_SYS_INIT_RAM_ADDR 0x80200000 @@ -28,7 +28,12 @@ #define BCMSTB_HIF_SPI_INTR2 0xf03e1a00 #define BCMSTB_CS_REG 0xf03e0920 -#define CONFIG_ENV_IS_IN_SPI_FLASH 1 +/* + * Environment configuration for SPI flash. + */ +#define CONFIG_ENV_OFFSET 0x1e0000 +#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE + #define CONFIG_DM_SPI 1 #define CONFIG_SYS_MAX_FLASH_BANKS 1 #define CONFIG_CMD_SF diff --git a/include/configs/bcmstb.h b/include/configs/bcmstb.h index e755383e72..cc289244ff 100644 --- a/include/configs/bcmstb.h +++ b/include/configs/bcmstb.h @@ -114,7 +114,6 @@ extern phys_addr_t prior_stage_fdt_address; /* * Serial console configuration. */ - #define CONFIG_BAUDRATE 115200 #define CONFIG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600, \ 115200} @@ -151,10 +150,7 @@ extern phys_addr_t prior_stage_fdt_address; * Environment configuration. */ #define CONFIG_SYS_REDUNDAND_ENVIRONMENT - -#define CONFIG_ENV_OFFSET 0x1e0000 #define CONFIG_ENV_SIZE (64 << 10) /* 64 KiB */ -#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE #define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) #define CONFIG_ENV_OVERWRITE diff --git a/include/configs/omap3_pandora.h b/include/configs/omap3_pandora.h index 5a82cbee71..82c66c4b8c 100644 --- a/include/configs/omap3_pandora.h +++ b/include/configs/omap3_pandora.h @@ -20,23 +20,6 @@ #define CONFIG_SYS_DEVICE_NULLDEV 1 /* - * Hardware drivers - */ - -/* TWL4030 LED */ - -/* - * NS16550 Configuration - */ -#undef CONFIG_SYS_NS16550_CLK -#define CONFIG_SYS_NS16550_SERIAL -#define CONFIG_SYS_NS16550_REG_SIZE (-4) -#define CONFIG_SYS_NS16550_CLK V_NS16550_CLK -#define CONFIG_SYS_NS16550_COM3 OMAP34XX_UART3 - -/* commands to include */ - -/* * Board NAND Info. */ #define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_SW diff --git a/include/dt-bindings/pinctrl/k3-am65.h b/include/dt-bindings/pinctrl/k3-am65.h new file mode 100644 index 0000000000..c86c9fd4ce --- /dev/null +++ b/include/dt-bindings/pinctrl/k3-am65.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides constants for TI K3-AM65 pinctrl bindings. + * + * Copyright (C) 2018 Texas Instruments + */ +#ifndef _DT_BINDINGS_PINCTRL_TI_K3_AM65_H +#define _DT_BINDINGS_PINCTRL_TI_K3_AM65_H + +/* K3 mux mode options for each pin. See TRM for options */ +#define MUX_MODE0 0 +#define MUX_MODE1 1 +#define MUX_MODE2 2 +#define MUX_MODE3 3 +#define MUX_MODE4 4 +#define MUX_MODE5 5 +#define MUX_MODE6 6 +#define MUX_MODE7 7 +#define MUX_MODE15 15 + +#define PULL_DISABLE (1 << 16) +#define PULL_UP (1 << 17) +#define INPUT_EN (1 << 18) +#define SLEWCTRL_200MHZ 0 +#define SLEWCTRL_150MHZ (1 << 19) +#define SLEWCTRL_100MHZ (2 << 19) +#define SLEWCTRL_50MHZ (3 << 19) +#define TX_DIS (1 << 21) +#define ISO_OVR (1 << 22) +#define ISO_BYPASS (1 << 23) +#define DS_EN (1 << 24) +#define DS_INPUT (1 << 25) +#define DS_FORCE_OUT_HIGH (1 << 26) +#define DS_PULL_UP_DOWN_EN 0 +#define DS_PULL_UP_DOWN_DIS (1 << 27) +#define DS_PULL_UP_SEL (1 << 28) +#define WAKEUP_ENABLE (1 << 29) + +#define PIN_OUTPUT (PULL_DISABLE) +#define PIN_OUTPUT_PULLUP (PULL_UP) +#define PIN_OUTPUT_PULLDOWN 0 +#define PIN_INPUT (INPUT_EN | PULL_DISABLE) +#define PIN_INPUT_PULLUP (INPUT_EN | PULL_UP) +#define PIN_INPUT_PULLDOWN (INPUT_EN) + +#define AM65X_IOPAD(pa, val) (((pa) & 0x1fff)) (val) +#define AM65X_WKUP_IOPAD(pa, val) (((pa) & 0x1fff)) (val) + +#endif diff --git a/include/inttypes.h b/include/inttypes.h deleted file mode 100644 index ea731ec868..0000000000 --- a/include/inttypes.h +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 1997-2001, 2004, 2007 Free Software Foundation, Inc. - * - * This file is taken from the GNU C Library v2.15, with the unimplemented - * functions removed and a few style fixes. - */ - -/* - * ISO C99: 7.8 Format conversion of integer types <inttypes.h> - */ - -#ifndef _INTTYPES_H -#define _INTTYPES_H 1 - -#include <linux/compiler.h> - -/* Get a definition for wchar_t. But we must not define wchar_t itself. */ -#ifndef ____gwchar_t_defined -# ifdef __cplusplus -# define __gwchar_t wchar_t -# elif defined __WCHAR_TYPE__ -typedef __WCHAR_TYPE__ __gwchar_t; -# else -# define __need_wchar_t -# include <stddef.h> -typedef wchar_t __gwchar_t; -# endif -# define ____gwchar_t_defined 1 -#endif - - -/* The ISO C99 standard specifies that these macros must only be - defined if explicitly requested. */ -#if !defined __cplusplus || defined __STDC_FORMAT_MACROS - -#ifdef CONFIG_USE_STDINT -# if __WORDSIZE == 64 -# define __PRI64_PREFIX "l" -# define __PRIPTR_PREFIX "l" -# else -# define __PRI64_PREFIX "ll" -# define __PRIPTR_PREFIX -# endif -#else -/* linux/types.h always uses long long for 64-bit and long for uintptr_t */ -# define __PRI64_PREFIX "ll" -# define __PRIPTR_PREFIX "l" -#endif - -/* Macros for printing format specifiers. */ - -/* Decimal notation. */ -# define PRId8 "d" -# define PRId16 "d" -# define PRId32 "d" -# define PRId64 __PRI64_PREFIX "d" - -# define PRIdLEAST8 "d" -# define PRIdLEAST16 "d" -# define PRIdLEAST32 "d" -# define PRIdLEAST64 __PRI64_PREFIX "d" - -# define PRIdFAST8 "d" -# define PRIdFAST16 __PRIPTR_PREFIX "d" -# define PRIdFAST32 __PRIPTR_PREFIX "d" -# define PRIdFAST64 __PRI64_PREFIX "d" - - -# define PRIi8 "i" -# define PRIi16 "i" -# define PRIi32 "i" -# define PRIi64 __PRI64_PREFIX "i" - -# define PRIiLEAST8 "i" -# define PRIiLEAST16 "i" -# define PRIiLEAST32 "i" -# define PRIiLEAST64 __PRI64_PREFIX "i" - -# define PRIiFAST8 "i" -# define PRIiFAST16 __PRIPTR_PREFIX "i" -# define PRIiFAST32 __PRIPTR_PREFIX "i" -# define PRIiFAST64 __PRI64_PREFIX "i" - -/* Octal notation. */ -# define PRIo8 "o" -# define PRIo16 "o" -# define PRIo32 "o" -# define PRIo64 __PRI64_PREFIX "o" - -# define PRIoLEAST8 "o" -# define PRIoLEAST16 "o" -# define PRIoLEAST32 "o" -# define PRIoLEAST64 __PRI64_PREFIX "o" - -# define PRIoFAST8 "o" -# define PRIoFAST16 __PRIPTR_PREFIX "o" -# define PRIoFAST32 __PRIPTR_PREFIX "o" -# define PRIoFAST64 __PRI64_PREFIX "o" - -/* Unsigned integers. */ -# define PRIu8 "u" -# define PRIu16 "u" -# define PRIu32 "u" -# define PRIu64 __PRI64_PREFIX "u" - -# define PRIuLEAST8 "u" -# define PRIuLEAST16 "u" -# define PRIuLEAST32 "u" -# define PRIuLEAST64 __PRI64_PREFIX "u" - -# define PRIuFAST8 "u" -# define PRIuFAST16 __PRIPTR_PREFIX "u" -# define PRIuFAST32 __PRIPTR_PREFIX "u" -# define PRIuFAST64 __PRI64_PREFIX "u" - -/* lowercase hexadecimal notation. */ -# define PRIx8 "x" -# define PRIx16 "x" -# define PRIx32 "x" -# define PRIx64 __PRI64_PREFIX "x" - -# define PRIxLEAST8 "x" -# define PRIxLEAST16 "x" -# define PRIxLEAST32 "x" -# define PRIxLEAST64 __PRI64_PREFIX "x" - -# define PRIxFAST8 "x" -# define PRIxFAST16 __PRIPTR_PREFIX "x" -# define PRIxFAST32 __PRIPTR_PREFIX "x" -# define PRIxFAST64 __PRI64_PREFIX "x" - -/* UPPERCASE hexadecimal notation. */ -# define PRIX8 "X" -# define PRIX16 "X" -# define PRIX32 "X" -# define PRIX64 __PRI64_PREFIX "X" - -# define PRIXLEAST8 "X" -# define PRIXLEAST16 "X" -# define PRIXLEAST32 "X" -# define PRIXLEAST64 __PRI64_PREFIX "X" - -# define PRIXFAST8 "X" -# define PRIXFAST16 __PRIPTR_PREFIX "X" -# define PRIXFAST32 __PRIPTR_PREFIX "X" -# define PRIXFAST64 __PRI64_PREFIX "X" - - -/* Macros for printing `intmax_t' and `uintmax_t'. */ -# define PRIdMAX __PRI64_PREFIX "d" -# define PRIiMAX __PRI64_PREFIX "i" -# define PRIoMAX __PRI64_PREFIX "o" -# define PRIuMAX __PRI64_PREFIX "u" -# define PRIxMAX __PRI64_PREFIX "x" -# define PRIXMAX __PRI64_PREFIX "X" - - -/* Macros for printing `intptr_t' and `uintptr_t'. */ -# define PRIdPTR __PRIPTR_PREFIX "d" -# define PRIiPTR __PRIPTR_PREFIX "i" -# define PRIoPTR __PRIPTR_PREFIX "o" -# define PRIuPTR __PRIPTR_PREFIX "u" -# define PRIxPTR __PRIPTR_PREFIX "x" -# define PRIXPTR __PRIPTR_PREFIX "X" - - -/* Macros for scanning format specifiers. */ - -/* Signed decimal notation. */ -# define SCNd8 "hhd" -# define SCNd16 "hd" -# define SCNd32 "d" -# define SCNd64 __PRI64_PREFIX "d" - -# define SCNdLEAST8 "hhd" -# define SCNdLEAST16 "hd" -# define SCNdLEAST32 "d" -# define SCNdLEAST64 __PRI64_PREFIX "d" - -# define SCNdFAST8 "hhd" -# define SCNdFAST16 __PRIPTR_PREFIX "d" -# define SCNdFAST32 __PRIPTR_PREFIX "d" -# define SCNdFAST64 __PRI64_PREFIX "d" - -/* Signed decimal notation. */ -# define SCNi8 "hhi" -# define SCNi16 "hi" -# define SCNi32 "i" -# define SCNi64 __PRI64_PREFIX "i" - -# define SCNiLEAST8 "hhi" -# define SCNiLEAST16 "hi" -# define SCNiLEAST32 "i" -# define SCNiLEAST64 __PRI64_PREFIX "i" - -# define SCNiFAST8 "hhi" -# define SCNiFAST16 __PRIPTR_PREFIX "i" -# define SCNiFAST32 __PRIPTR_PREFIX "i" -# define SCNiFAST64 __PRI64_PREFIX "i" - -/* Unsigned decimal notation. */ -# define SCNu8 "hhu" -# define SCNu16 "hu" -# define SCNu32 "u" -# define SCNu64 __PRI64_PREFIX "u" - -# define SCNuLEAST8 "hhu" -# define SCNuLEAST16 "hu" -# define SCNuLEAST32 "u" -# define SCNuLEAST64 __PRI64_PREFIX "u" - -# define SCNuFAST8 "hhu" -# define SCNuFAST16 __PRIPTR_PREFIX "u" -# define SCNuFAST32 __PRIPTR_PREFIX "u" -# define SCNuFAST64 __PRI64_PREFIX "u" - -/* Octal notation. */ -# define SCNo8 "hho" -# define SCNo16 "ho" -# define SCNo32 "o" -# define SCNo64 __PRI64_PREFIX "o" - -# define SCNoLEAST8 "hho" -# define SCNoLEAST16 "ho" -# define SCNoLEAST32 "o" -# define SCNoLEAST64 __PRI64_PREFIX "o" - -# define SCNoFAST8 "hho" -# define SCNoFAST16 __PRIPTR_PREFIX "o" -# define SCNoFAST32 __PRIPTR_PREFIX "o" -# define SCNoFAST64 __PRI64_PREFIX "o" - -/* Hexadecimal notation. */ -# define SCNx8 "hhx" -# define SCNx16 "hx" -# define SCNx32 "x" -# define SCNx64 __PRI64_PREFIX "x" - -# define SCNxLEAST8 "hhx" -# define SCNxLEAST16 "hx" -# define SCNxLEAST32 "x" -# define SCNxLEAST64 __PRI64_PREFIX "x" - -# define SCNxFAST8 "hhx" -# define SCNxFAST16 __PRIPTR_PREFIX "x" -# define SCNxFAST32 __PRIPTR_PREFIX "x" -# define SCNxFAST64 __PRI64_PREFIX "x" - - -/* Macros for scanning `intmax_t' and `uintmax_t'. */ -# define SCNdMAX __PRI64_PREFIX "d" -# define SCNiMAX __PRI64_PREFIX "i" -# define SCNoMAX __PRI64_PREFIX "o" -# define SCNuMAX __PRI64_PREFIX "u" -# define SCNxMAX __PRI64_PREFIX "x" - -/* Macros for scaning `intptr_t' and `uintptr_t'. */ -# define SCNdPTR __PRIPTR_PREFIX "d" -# define SCNiPTR __PRIPTR_PREFIX "i" -# define SCNoPTR __PRIPTR_PREFIX "o" -# define SCNuPTR __PRIPTR_PREFIX "u" -# define SCNxPTR __PRIPTR_PREFIX "x" - -#endif /* C++ && format macros */ - - -#if __WORDSIZE == 64 - -/* We have to define the `uintmax_t' type using `ldiv_t'. */ -typedef struct { - long int quot; /* Quotient. */ - long int rem; /* Remainder. */ -} imaxdiv_t; - -#else - -/* We have to define the `uintmax_t' type using `lldiv_t'. */ -typedef struct { - long long int quot; /* Quotient. */ - long long int rem; /* Remainder. */ -} imaxdiv_t; - -#endif - -#endif /* inttypes.h */ diff --git a/include/linux/soc/ti/k3-sec-proxy.h b/include/linux/soc/ti/k3-sec-proxy.h new file mode 100644 index 0000000000..f34854ceeb --- /dev/null +++ b/include/linux/soc/ti/k3-sec-proxy.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Texas Instruments' K3 Secure proxy + * + * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + * + */ + +#ifndef K3_SEC_PROXY_H +#define K3_SEC_PROXY_H + +/** + * struct k3_sec_proxy_msg - Secure proxy message structure + * @len: Length of data in the Buffer + * @buf: Buffer pointer + * + * This is the structure for data used in mbox_send() and mbox_recv(). + */ +struct k3_sec_proxy_msg { + size_t len; + u32 *buf; +}; + +#endif /* K3_SEC_PROXY_H */ diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h new file mode 100644 index 0000000000..90d5053636 --- /dev/null +++ b/include/linux/soc/ti/ti_sci_protocol.h @@ -0,0 +1,314 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Texas Instruments System Control Interface Protocol + * Based on include/linux/soc/ti/ti_sci_protocol.h from Linux. + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * Nishanth Menon + * Lokesh Vutla <lokeshvutla@ti.com> + */ + +#ifndef __TISCI_PROTOCOL_H +#define __TISCI_PROTOCOL_H + +/** + * struct ti_sci_version_info - version information structure + * @abi_major: Major ABI version. Change here implies risk of backward + * compatibility break. + * @abi_minor: Minor ABI version. Change here implies new feature addition, + * or compatible change in ABI. + * @firmware_revision: Firmware revision (not usually used). + * @firmware_description: Firmware description (not usually used). + */ +struct ti_sci_version_info { + u8 abi_major; + u8 abi_minor; + u16 firmware_revision; + char firmware_description[32]; +}; + +struct ti_sci_handle; + +/** + * struct ti_sci_board_ops - Board config operations + * @board_config: Command to set the board configuration + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @board_config_rm: Command to set the board resource management + * configuration + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @board_config_security: Command to set the board security configuration + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @board_config_pm: Command to trigger and set the board power and clock + * management related configuration + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + */ +struct ti_sci_board_ops { + int (*board_config)(const struct ti_sci_handle *handle, + u64 addr, u32 size); + int (*board_config_rm)(const struct ti_sci_handle *handle, + u64 addr, u32 size); + int (*board_config_security)(const struct ti_sci_handle *handle, + u64 addr, u32 size); + int (*board_config_pm)(const struct ti_sci_handle *handle, + u64 addr, u32 size); +}; + +/** + * struct ti_sci_dev_ops - Device control operations + * @get_device: Command to request for device managed by TISCI + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @idle_device: Command to idle a device managed by TISCI + * Returns 0 for successful exclusive request, else returns + * corresponding error message. + * @put_device: Command to release a device managed by TISCI + * Returns 0 for successful release, else returns corresponding + * error message. + * @is_valid: Check if the device ID is a valid ID. + * Returns 0 if the ID is valid, else returns corresponding error. + * @get_context_loss_count: Command to retrieve context loss counter - this + * increments every time the device looses context. Overflow + * is possible. + * - count: pointer to u32 which will retrieve counter + * Returns 0 for successful information request and count has + * proper data, else returns corresponding error message. + * @is_idle: Reports back about device idle state + * - req_state: Returns requested idle state + * Returns 0 for successful information request and req_state and + * current_state has proper data, else returns corresponding error + * message. + * @is_stop: Reports back about device stop state + * - req_state: Returns requested stop state + * - current_state: Returns current stop state + * Returns 0 for successful information request and req_state and + * current_state has proper data, else returns corresponding error + * message. + * @is_on: Reports back about device ON(or active) state + * - req_state: Returns requested ON state + * - current_state: Returns current ON state + * Returns 0 for successful information request and req_state and + * current_state has proper data, else returns corresponding error + * message. + * @is_transitioning: Reports back if the device is in the middle of transition + * of state. + * -current_state: Returns 'true' if currently transitioning. + * @set_device_resets: Command to configure resets for device managed by TISCI. + * -reset_state: Device specific reset bit field + * Returns 0 for successful request, else returns + * corresponding error message. + * @get_device_resets: Command to read state of resets for device managed + * by TISCI. + * -reset_state: pointer to u32 which will retrieve resets + * Returns 0 for successful request, else returns + * corresponding error message. + * + * NOTE: for all these functions, the following parameters are generic in + * nature: + * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * -id: Device Identifier + * + * Request for the device - NOTE: the client MUST maintain integrity of + * usage count by balancing get_device with put_device. No refcounting is + * managed by driver for that purpose. + */ +struct ti_sci_dev_ops { + int (*get_device)(const struct ti_sci_handle *handle, u32 id); + int (*idle_device)(const struct ti_sci_handle *handle, u32 id); + int (*put_device)(const struct ti_sci_handle *handle, u32 id); + int (*is_valid)(const struct ti_sci_handle *handle, u32 id); + int (*get_context_loss_count)(const struct ti_sci_handle *handle, + u32 id, u32 *count); + int (*is_idle)(const struct ti_sci_handle *handle, u32 id, + bool *requested_state); + int (*is_stop)(const struct ti_sci_handle *handle, u32 id, + bool *req_state, bool *current_state); + int (*is_on)(const struct ti_sci_handle *handle, u32 id, + bool *req_state, bool *current_state); + int (*is_transitioning)(const struct ti_sci_handle *handle, u32 id, + bool *current_state); + int (*set_device_resets)(const struct ti_sci_handle *handle, u32 id, + u32 reset_state); + int (*get_device_resets)(const struct ti_sci_handle *handle, u32 id, + u32 *reset_state); +}; + +/** + * struct ti_sci_clk_ops - Clock control operations + * @get_clock: Request for activation of clock and manage by processor + * - needs_ssc: 'true' if Spread Spectrum clock is desired. + * - can_change_freq: 'true' if frequency change is desired. + * - enable_input_term: 'true' if input termination is desired. + * @idle_clock: Request for Idling a clock managed by processor + * @put_clock: Release the clock to be auto managed by TISCI + * @is_auto: Is the clock being auto managed + * - req_state: state indicating if the clock is auto managed + * @is_on: Is the clock ON + * - req_state: if the clock is requested to be forced ON + * - current_state: if the clock is currently ON + * @is_off: Is the clock OFF + * - req_state: if the clock is requested to be forced OFF + * - current_state: if the clock is currently Gated + * @set_parent: Set the clock source of a specific device clock + * - parent_id: Parent clock identifier to set. + * @get_parent: Get the current clock source of a specific device clock + * - parent_id: Parent clock identifier which is the parent. + * @get_num_parents: Get the number of parents of the current clock source + * - num_parents: returns the number of parent clocks. + * @get_best_match_freq: Find a best matching frequency for a frequency + * range. + * - match_freq: Best matching frequency in Hz. + * @set_freq: Set the Clock frequency + * @get_freq: Get the Clock frequency + * - current_freq: Frequency in Hz that the clock is at. + * + * NOTE: for all these functions, the following parameters are generic in + * nature: + * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * -did: Device identifier this request is for + * -cid: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * -min_freq: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * -target_freq: The target clock frequency in Hz. A frequency will be + * processed as close to this target frequency as possible. + * -max_freq: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * + * Request for the clock - NOTE: the client MUST maintain integrity of + * usage count by balancing get_clock with put_clock. No refcounting is + * managed by driver for that purpose. + */ +struct ti_sci_clk_ops { + int (*get_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool needs_ssc, bool can_change_freq, + bool enable_input_term); + int (*idle_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid); + int (*put_clock)(const struct ti_sci_handle *handle, u32 did, u8 cid); + int (*is_auto)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool *req_state); + int (*is_on)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool *req_state, bool *current_state); + int (*is_off)(const struct ti_sci_handle *handle, u32 did, u8 cid, + bool *req_state, bool *current_state); + int (*set_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u8 parent_id); + int (*get_parent)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u8 *parent_id); + int (*get_num_parents)(const struct ti_sci_handle *handle, u32 did, + u8 cid, u8 *num_parents); + int (*get_best_match_freq)(const struct ti_sci_handle *handle, u32 did, + u8 cid, u64 min_freq, u64 target_freq, + u64 max_freq, u64 *match_freq); + int (*set_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u64 min_freq, u64 target_freq, u64 max_freq); + int (*get_freq)(const struct ti_sci_handle *handle, u32 did, u8 cid, + u64 *current_freq); +}; + +/** + * struct ti_sci_core_ops - SoC Core Operations + * @reboot_device: Reboot the SoC + * Returns 0 for successful request(ideally should never return), + * else returns corresponding error value. + */ +struct ti_sci_core_ops { + int (*reboot_device)(const struct ti_sci_handle *handle); +}; + +/** + * struct ti_sci_proc_ops - Processor specific operations. + * + * @proc_request: Request for controlling a physical processor. + * The requesting host should be in the processor access list. + * @proc_release: Relinquish a physical processor control + * @proc_handover: Handover a physical processor control to another host + * in the permitted list. + * @set_proc_boot_cfg: Base configuration of the processor + * @set_proc_boot_ctrl: Setup limited control flags in specific cases. + * @proc_auth_boot_image: + * @get_proc_boot_status: Get the state of physical processor + * + * NOTE: for all these functions, the following parameters are generic in + * nature: + * -handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle + * -pid: Processor ID + * + */ +struct ti_sci_proc_ops { + int (*proc_request)(const struct ti_sci_handle *handle, u8 pid); + int (*proc_release)(const struct ti_sci_handle *handle, u8 pid); + int (*proc_handover)(const struct ti_sci_handle *handle, u8 pid, + u8 hid); + int (*set_proc_boot_cfg)(const struct ti_sci_handle *handle, u8 pid, + u64 bv, u32 cfg_set, u32 cfg_clr); + int (*set_proc_boot_ctrl)(const struct ti_sci_handle *handle, u8 pid, + u32 ctrl_set, u32 ctrl_clr); + int (*proc_auth_boot_image)(const struct ti_sci_handle *handle, u8 pid, + u64 caddr); + int (*get_proc_boot_status)(const struct ti_sci_handle *handle, u8 pid, + u64 *bv, u32 *cfg_flags, u32 *ctrl_flags, + u32 *sts_flags); +}; + +/** + * struct ti_sci_ops - Function support for TI SCI + * @board_ops: Miscellaneous operations + * @dev_ops: Device specific operations + * @clk_ops: Clock specific operations + * @core_ops: Core specific operations + * @proc_ops: Processor specific operations + */ +struct ti_sci_ops { + struct ti_sci_board_ops board_ops; + struct ti_sci_dev_ops dev_ops; + struct ti_sci_clk_ops clk_ops; + struct ti_sci_core_ops core_ops; + struct ti_sci_proc_ops proc_ops; +}; + +/** + * struct ti_sci_handle - Handle returned to TI SCI clients for usage. + * @ops: operations that are made available to TI SCI clients + * @version: structure containing version information + */ +struct ti_sci_handle { + struct ti_sci_ops ops; + struct ti_sci_version_info version; +}; + +#if IS_ENABLED(CONFIG_TI_SCI_PROTOCOL) + +const struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *dev); +const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev); +const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev, + const char *property); + +#else /* CONFIG_TI_SCI_PROTOCOL */ + +static inline +const struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *dev) +{ + return ERR_PTR(-EINVAL); +} + +static inline const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev) +{ + return ERR_PTR(-EINVAL); +} + +static inline +const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev, + const char *property) +{ + return ERR_PTR(-EINVAL); +} +#endif /* CONFIG_TI_SCI_PROTOCOL */ + +#endif /* __TISCI_PROTOCOL_H */ diff --git a/include/linux/types.h b/include/linux/types.h index 7c33e7adbc..1f3cd63b8f 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -106,8 +106,7 @@ typedef __u8 uint8_t; typedef __u16 uint16_t; typedef __u32 uint32_t; -#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && \ - (!defined(CONFIG_USE_STDINT) || !defined(__INT64_TYPE__)) +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) typedef __u64 uint64_t; typedef __u64 u_int64_t; typedef __s64 int64_t; @@ -120,12 +119,6 @@ typedef __s64 int64_t; #define aligned_be64 __be64 __aligned(8) #define aligned_le64 __le64 __aligned(8) -#if defined(CONFIG_USE_STDINT) && defined(__INT64_TYPE__) -typedef __UINT64_TYPE__ uint64_t; -typedef __UINT64_TYPE__ u_int64_t; -typedef __INT64_TYPE__ int64_t; -#endif - #ifdef __KERNEL__ typedef phys_addr_t resource_size_t; #endif diff --git a/include/mailbox.h b/include/mailbox.h index c64951b2f7..93f4715e16 100644 --- a/include/mailbox.h +++ b/include/mailbox.h @@ -44,6 +44,7 @@ struct udevice; * * @dev: The device which implements the mailbox. * @id: The mailbox channel ID within the provider. + * @con_priv: Hook for controller driver to attach private data * * Currently, the mailbox API assumes that a single integer ID is enough to * identify and configure any mailbox channel for any mailbox provider. If this @@ -56,11 +57,9 @@ struct udevice; */ struct mbox_chan { struct udevice *dev; - /* - * Written by of_xlate. We assume a single id is enough for now. In the - * future, we might add more fields here. - */ + /* Written by of_xlate.*/ unsigned long id; + void *con_priv; }; /** diff --git a/include/mmc.h b/include/mmc.h index df4255b828..9b9cbedadc 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -64,6 +64,7 @@ #define MMC_MODE_HS_52MHz MMC_CAP(MMC_HS_52) #define MMC_MODE_DDR_52MHz MMC_CAP(MMC_DDR_52) #define MMC_MODE_HS200 MMC_CAP(MMC_HS_200) +#define MMC_MODE_HS400 MMC_CAP(MMC_HS_400) #define MMC_MODE_8BIT BIT(30) #define MMC_MODE_4BIT BIT(29) @@ -248,6 +249,10 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) /* SDR mode @1.2V I/O */ #define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \ EXT_CSD_CARD_TYPE_HS200_1_2V) +#define EXT_CSD_CARD_TYPE_HS400_1_8V BIT(6) +#define EXT_CSD_CARD_TYPE_HS400_1_2V BIT(7) +#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \ + EXT_CSD_CARD_TYPE_HS400_1_2V) #define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ @@ -259,6 +264,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) #define EXT_CSD_TIMING_LEGACY 0 /* no high speed */ #define EXT_CSD_TIMING_HS 1 /* HS */ #define EXT_CSD_TIMING_HS200 2 /* HS200 */ +#define EXT_CSD_TIMING_HS400 3 /* HS400 */ #define EXT_CSD_BOOT_ACK_ENABLE (1 << 6) #define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3) @@ -519,6 +525,7 @@ enum bus_mode { UHS_DDR50, UHS_SDR104, MMC_HS_200, + MMC_HS_400, MMC_MODES_END }; @@ -533,6 +540,10 @@ static inline bool mmc_is_mode_ddr(enum bus_mode mode) else if (mode == UHS_DDR50) return true; #endif +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + else if (mode == MMC_HS_400) + return true; +#endif else return false; } diff --git a/include/power-domain.h b/include/power-domain.h index a558fbbdb2..00996057b0 100644 --- a/include/power-domain.h +++ b/include/power-domain.h @@ -98,6 +98,27 @@ int power_domain_get(struct udevice *dev, struct power_domain *power_domain) #endif /** + * power_domain_get_by_index - Get the indexed power domain for a device. + * + * @dev: The client device. + * @power_domain: A pointer to a power domain struct to initialize. + * @index: Power domain index to be powered on. + * + * @return 0 if OK, or a negative error code. + */ +#if CONFIG_IS_ENABLED(POWER_DOMAIN) +int power_domain_get_by_index(struct udevice *dev, + struct power_domain *power_domain, int index); +#else +static inline +int power_domain_get_by_index(struct udevice *dev, + struct power_domain *power_domain, int index) +{ + return -ENOSYS; +} +#endif + +/** * power_domain_free - Free a previously requested power domain. * * @power_domain: A power domain struct that was previously successfully diff --git a/include/remoteproc.h b/include/remoteproc.h index c3c3f46a1a..a59dba8481 100644 --- a/include/remoteproc.h +++ b/include/remoteproc.h @@ -86,6 +86,14 @@ struct dm_rproc_ops { int rproc_init(void); /** + * rproc_dev_init() - Initialize a remote proc device based on id + * @id: id of the remote processor + * + * Return: 0 if all ok, else appropriate error value. + */ +int rproc_dev_init(int id); + +/** * rproc_is_initialized() - check to see if remoteproc devices are initialized * * Return: 0 if all devices are initialized, else appropriate error value. @@ -150,6 +158,7 @@ int rproc_ping(int id); int rproc_is_running(int id); #else static inline int rproc_init(void) { return -ENOSYS; } +static inline int rproc_dev_init(int id) { return -ENOSYS; } static inline bool rproc_is_initialized(void) { return false; } static inline int rproc_load(int id, ulong addr, ulong size) { return -ENOSYS; } static inline int rproc_start(int id) { return -ENOSYS; } diff --git a/include/reset-uclass.h b/include/reset-uclass.h index c17d738b31..7b5cc3cb3b 100644 --- a/include/reset-uclass.h +++ b/include/reset-uclass.h @@ -76,6 +76,14 @@ struct reset_ops { * @return 0 if OK, or a negative error code. */ int (*rst_deassert)(struct reset_ctl *reset_ctl); + /** + * rst_status - Check reset signal status. + * + * @reset_ctl: The reset signal to check. + * @return 0 if deasserted, positive if asserted, or a negative + * error code. + */ + int (*rst_status)(struct reset_ctl *reset_ctl); }; #endif diff --git a/include/reset.h b/include/reset.h index a7bbc1c331..bc495a90c2 100644 --- a/include/reset.h +++ b/include/reset.h @@ -40,10 +40,12 @@ struct udevice; * * @dev: The device which implements the reset signal. * @id: The reset signal ID within the provider. + * @data: An optional data field for scenarios where a single integer ID is not + * sufficient. If used, it can be populated through an .of_xlate op and + * processed during the various reset ops. * - * Currently, the reset API assumes that a single integer ID is enough to - * identify and configure any reset signal for any reset provider. If this - * assumption becomes invalid in the future, the struct could be expanded to + * Should additional information to identify and configure any reset signal + * for any provider be required in the future, the struct could be expanded to * either (a) add more fields to allow reset providers to store additional * information, or (b) replace the id field with an opaque pointer, which the * provider would dynamically allocated during its .of_xlate op, and process @@ -53,10 +55,10 @@ struct udevice; struct reset_ctl { struct udevice *dev; /* - * Written by of_xlate. We assume a single id is enough for now. In the - * future, we might add more fields here. + * Written by of_xlate. In the future, we might add more fields here. */ unsigned long id; + unsigned long data; }; /** @@ -207,6 +209,15 @@ int reset_deassert(struct reset_ctl *reset_ctl); int reset_deassert_bulk(struct reset_ctl_bulk *bulk); /** + * rst_status - Check reset signal status. + * + * @reset_ctl: The reset signal to check. + * @return 0 if deasserted, positive if asserted, or a negative + * error code. + */ +int reset_status(struct reset_ctl *reset_ctl); + +/** * reset_release_all - Assert/Free an array of previously requested resets. * * For each reset contained in the reset array, this function will check if @@ -279,6 +290,11 @@ static inline int reset_deassert_bulk(struct reset_ctl_bulk *bulk) return 0; } +static inline int reset_status(struct reset_ctl *reset_ctl) +{ + return -ENOTSUPP; +} + static inline int reset_release_all(struct reset_ctl *reset_ctl, int count) { return 0; diff --git a/include/serial.h b/include/serial.h index 9cd6f10703..020cd392e8 100644 --- a/include/serial.h +++ b/include/serial.h @@ -73,6 +73,44 @@ enum serial_par { SERIAL_PAR_EVEN }; +#define SERIAL_PAR_SHIFT 0 +#define SERIAL_PAR_MASK (0x03 << SERIAL_PAR_SHIFT) +#define SERIAL_GET_PARITY(config) \ + ((config & SERIAL_PAR_MASK) >> SERIAL_PAR_SHIFT) + +enum serial_bits { + SERIAL_5_BITS, + SERIAL_6_BITS, + SERIAL_7_BITS, + SERIAL_8_BITS +}; + +#define SERIAL_BITS_SHIFT 2 +#define SERIAL_BITS_MASK (0x3 << SERIAL_BITS_SHIFT) +#define SERIAL_GET_BITS(config) \ + ((config & SERIAL_BITS_MASK) >> SERIAL_BITS_SHIFT) + +enum serial_stop { + SERIAL_HALF_STOP, /* 0.5 stop bit */ + SERIAL_ONE_STOP, /* 1 stop bit */ + SERIAL_ONE_HALF_STOP, /* 1.5 stop bit */ + SERIAL_TWO_STOP /* 2 stop bit */ +}; + +#define SERIAL_STOP_SHIFT 4 +#define SERIAL_STOP_MASK (0x3 << SERIAL_STOP_SHIFT) +#define SERIAL_GET_STOP(config) \ + ((config & SERIAL_STOP_MASK) >> SERIAL_STOP_SHIFT) + +#define SERIAL_CONFIG(par, bits, stop) \ + (par << SERIAL_PAR_SHIFT | \ + bits << SERIAL_BITS_SHIFT | \ + stop << SERIAL_STOP_SHIFT) + +#define SERIAL_DEFAULT_CONFIG SERIAL_PAR_NONE << SERIAL_PAR_SHIFT | \ + SERIAL_8_BITS << SERIAL_BITS_SHIFT | \ + SERIAL_ONE_STOP << SERIAL_STOP_SHIFT + /** * struct struct dm_serial_ops - Driver model serial operations * @@ -149,16 +187,20 @@ struct dm_serial_ops { */ int (*loop)(struct udevice *dev, int on); #endif + /** - * setparity() - Set up the parity + * setconfig() - Set up the uart configuration + * (parity, 5/6/7/8 bits word length, stop bits) * - * Set up a new parity for this device. + * Set up a new config for this device. * * @dev: Device pointer * @parity: parity to use + * @bits: bits number to use + * @stop: stop bits number to use * @return 0 if OK, -ve on error */ - int (*setparity)(struct udevice *dev, enum serial_par parity); + int (*setconfig)(struct udevice *dev, uint serial_config); }; /** diff --git a/lib/display_options.c b/lib/display_options.c index f1c930463e..32849821f4 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -7,7 +7,6 @@ #include <common.h> #include <console.h> #include <div64.h> -#include <inttypes.h> #include <version.h> #include <linux/ctype.h> #include <asm/io.h> @@ -65,7 +64,7 @@ void print_freq(uint64_t freq, const char *s) } if (!c) { - printf("%" PRIu64 " Hz%s", freq, s); + printf("%llu Hz%s", freq, s); return; } @@ -105,7 +104,7 @@ void print_size(uint64_t size, const char *s) } if (!c) { - printf("%" PRIu64 " Bytes%s", size, s); + printf("%llu Bytes%s", size, s); return; } diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 3935e4f1ce..ca61e1ad41 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -13,7 +13,6 @@ #include <linux/libfdt_env.h> #include <u-boot/crc.h> #include <bootm.h> -#include <inttypes.h> #include <watchdog.h> DECLARE_GLOBAL_DATA_PTR; @@ -338,7 +337,7 @@ static efi_status_t EFIAPI efi_free_pages_ext(uint64_t memory, { efi_status_t r; - EFI_ENTRY("%" PRIx64 ", 0x%zx", memory, pages); + EFI_ENTRY("%llx, 0x%zx", memory, pages); r = efi_free_pages(memory, pages); return EFI_EXIT(r); } @@ -789,7 +788,7 @@ static efi_status_t EFIAPI efi_set_timer_ext(struct efi_event *event, enum efi_timer_delay type, uint64_t trigger_time) { - EFI_ENTRY("%p, %d, %" PRIx64, event, type, trigger_time); + EFI_ENTRY("%p, %d, %llx", event, type, trigger_time); return EFI_EXIT(efi_set_timer(event, type, trigger_time)); } @@ -1961,7 +1960,7 @@ static efi_status_t EFIAPI efi_set_watchdog_timer(unsigned long timeout, unsigned long data_size, uint16_t *watchdog_data) { - EFI_ENTRY("%ld, 0x%" PRIx64 ", %ld, %p", timeout, watchdog_code, + EFI_ENTRY("%ld, 0x%llx, %ld, %p", timeout, watchdog_code, data_size, watchdog_data); return EFI_EXIT(efi_set_watchdog(timeout)); } diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 6040bcff19..9d776a6d99 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -13,7 +13,6 @@ #include <usb.h> #include <mmc.h> #include <efi_loader.h> -#include <inttypes.h> #include <part.h> /* template END node: */ diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 5c6ec5258c..13fcc1b471 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -9,7 +9,6 @@ #include <blk.h> #include <dm.h> #include <efi_loader.h> -#include <inttypes.h> #include <part.h> #include <malloc.h> @@ -66,7 +65,7 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this, blocks = buffer_size / blksz; lba += diskobj->offset; - debug("EFI: %s:%d blocks=%x lba=%"PRIx64" blksz=%x dir=%d\n", __func__, + debug("EFI: %s:%d blocks=%x lba=%llx blksz=%x dir=%d\n", __func__, __LINE__, blocks, lba, blksz, direction); /* We only support full block access */ @@ -111,7 +110,7 @@ static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this, real_buffer = efi_bounce_buffer; #endif - EFI_ENTRY("%p, %x, %" PRIx64 ", %zx, %p", this, media_id, lba, + EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba, buffer_size, buffer); r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer, @@ -146,7 +145,7 @@ static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this, real_buffer = efi_bounce_buffer; #endif - EFI_ENTRY("%p, %x, %" PRIx64 ", %zx, %p", this, media_id, lba, + EFI_ENTRY("%p, %x, %llx, %zx, %p", this, media_id, lba, buffer_size, buffer); /* Populate bounce buffer if necessary */ diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 3a36bbcbfa..a4aa9bcf61 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -8,7 +8,6 @@ #include <common.h> #include <dm.h> #include <efi_loader.h> -#include <inttypes.h> #include <lcd.h> #include <malloc.h> #include <video.h> diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index e2b40aa85b..0ac4ff554b 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -7,7 +7,6 @@ #include <common.h> #include <efi_loader.h> -#include <inttypes.h> #include <malloc.h> #include <mapmem.h> #include <watchdog.h> @@ -159,7 +158,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, bool carve_again; uint64_t carved_pages = 0; - debug("%s: 0x%" PRIx64 " 0x%" PRIx64 " %d %s\n", __func__, + debug("%s: 0x%llx 0x%llx %d %s\n", __func__, start, pages, memory_type, overlap_only_ram ? "yes" : "no"); if (memory_type >= EFI_MAX_MEMORY_TYPE) diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 5a3d7be86c..034d0d2ed0 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -7,7 +7,6 @@ #include <common.h> #include <efi_loader.h> -#include <inttypes.h> #include <lcd.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 932f7582ec..38e42fa243 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -7,7 +7,6 @@ #include <common.h> #include <efi_loader.h> -#include <inttypes.h> #include <smbios.h> static const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index b2ec12e9b5..bf5e0f6a57 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -11,7 +11,6 @@ #include <errno.h> #include <fdtdec.h> #include <fdt_support.h> -#include <inttypes.h> #include <linux/libfdt.h> #include <serial.h> #include <asm/sections.h> @@ -1448,13 +1447,12 @@ int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, if (auto_size) { u64 new_size; - debug("Auto-sizing %" PRIx64 ", size %" PRIx64 ": ", - addr, size); + debug("Auto-sizing %llx, size %llx: ", addr, size); new_size = get_ram_size((long *)(uintptr_t)addr, size); if (new_size == size) { debug("OK\n"); } else { - debug("sized to %" PRIx64 "\n", new_size); + debug("sized to %llx\n", new_size); size = new_size; } } @@ -1464,7 +1462,7 @@ int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, total_size += size; } - debug("Memory size %" PRIu64 "\n", total_size); + debug("Memory size %llu\n", total_size); if (sizep) *sizep = (phys_size_t)total_size; diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 252f13826d..e494d185e4 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -144,6 +144,10 @@ quiet_cmd_mkimage = MKIMAGE $@ cmd_mkimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -d $< $@ \ >$(MKIMAGEOUTPUT) $(if $(KBUILD_VERBOSE:0=), && cat $(MKIMAGEOUTPUT)) +quiet_cmd_mkfitimage = MKIMAGE $@ +cmd_mkfitimage = $(objtree)/tools/mkimage $(MKIMAGEFLAGS_$(@F)) -f $(SPL_ITS) -E $@ \ + $(if $(KBUILD_VERBOSE:1=), MKIMAGEOUTPUT) + MKIMAGEFLAGS_MLO = -T omapimage -a $(CONFIG_SPL_TEXT_BASE) MKIMAGEFLAGS_MLO.byteswap = -T omapimage -n byteswap -a $(CONFIG_SPL_TEXT_BASE) @@ -407,3 +411,8 @@ $(obj)/$(SPL_BIN).multidtb.fit.gz: $(obj)/$(SPL_BIN).multidtb.fit $(obj)/$(SPL_BIN).multidtb.fit.lzo: $(obj)/$(SPL_BIN).multidtb.fit @lzop -f9 $< > $@ + +ifdef CONFIG_ARCH_K3 +tispl.bin: $(obj)/u-boot-spl-nodtb.bin $(SHRUNK_ARCH_DTB) $(SPL_ITS) FORCE + $(call if_changed,mkfitimage) +endif diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index fc37099cbe..30c79a643e 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -4633,7 +4633,6 @@ CONFIG_USE_INTERRUPT CONFIG_USE_NOR CONFIG_USE_ONENAND_BOARD_INIT CONFIG_USE_SPIFLASH -CONFIG_USE_STDINT CONFIG_UTBIPAR_INIT_TBIPA CONFIG_U_BOOT_HDR_ADDR CONFIG_U_BOOT_HDR_SIZE diff --git a/test/dm/Makefile b/test/dm/Makefile index 67c1fe6d01..3f5a634afd 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -46,4 +46,5 @@ obj-$(CONFIG_SPMI) += spmi.o obj-$(CONFIG_WDT) += wdt.o obj-$(CONFIG_AXI) += axi.o obj-$(CONFIG_MISC) += misc.o +obj-$(CONFIG_DM_SERIAL) += serial.o endif diff --git a/test/dm/serial.c b/test/dm/serial.c new file mode 100644 index 0000000000..5c603e1f42 --- /dev/null +++ b/test/dm/serial.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, STMicroelectronics + */ + +#include <common.h> +#include <serial.h> +#include <dm.h> +#include <dm/test.h> +#include <test/ut.h> + +static int dm_test_serial(struct unit_test_state *uts) +{ + struct udevice *dev_serial; + + ut_assertok(uclass_get_device_by_name(UCLASS_SERIAL, "serial", + &dev_serial)); + + ut_assertok(serial_tstc()); + /* + * test with default config which is the only one supported by + * sandbox_serial driver + */ + ut_assertok(serial_setconfig(SERIAL_DEFAULT_CONFIG)); + /* + * test with a serial config which is not supported by + * sandbox_serial driver: test with wrong parity + */ + ut_asserteq(-ENOTSUPP, + serial_setconfig(SERIAL_CONFIG(SERIAL_PAR_ODD, + SERIAL_8_BITS, + SERIAL_ONE_STOP))); + /* + * test with a serial config which is not supported by + * sandbox_serial driver: test with wrong bits number + */ + ut_asserteq(-ENOTSUPP, + serial_setconfig(SERIAL_CONFIG(SERIAL_PAR_NONE, + SERIAL_6_BITS, + SERIAL_ONE_STOP))); + + /* + * test with a serial config which is not supported by + * sandbox_serial driver: test with wrong stop bits number + */ + ut_asserteq(-ENOTSUPP, + serial_setconfig(SERIAL_CONFIG(SERIAL_PAR_NONE, + SERIAL_8_BITS, + SERIAL_TWO_STOP))); + + return 0; +} + +DM_TEST(dm_test_serial, DM_TESTF_SCAN_FDT); diff --git a/test/stdint/int-types.c b/test/stdint/int-types.c index 2660084d94..f6d09e8643 100644 --- a/test/stdint/int-types.c +++ b/test/stdint/int-types.c @@ -1,5 +1,4 @@ #include <common.h> -#include <inttypes.h> int test_types(void) { @@ -7,7 +6,7 @@ int test_types(void) uint64_t uint64 = 0; u64 u64_val = 0; - printf("uintptr = %" PRIuPTR "\n", uintptr); - printf("uint64 = %" PRIu64 "\n", uint64); - printf("u64 = %" PRIu64 "\n", u64_val); + printf("uintptr = %lu\n", uintptr); + printf("uint64 = %llu\n", uint64); + printf("u64 = %llu\n", u64_val); } diff --git a/test/stdint/test-includes.sh b/test/stdint/test-includes.sh index 077bdc73a1..1db8515e82 100755 --- a/test/stdint/test-includes.sh +++ b/test/stdint/test-includes.sh @@ -46,10 +46,8 @@ try_test() { $cmd } -# Run a test with and without CONFIG_USE_STDINT try_both() { try_test $@ - try_test $@ -DCONFIG_USE_STDINT } # board arch soc path-to-gcc diff --git a/tools/buildman/func_test.py b/tools/buildman/func_test.py index 363db9d8ce..119d02cbb2 100644 --- a/tools/buildman/func_test.py +++ b/tools/buildman/func_test.py @@ -27,7 +27,7 @@ settings_data = ''' [make-flags] src=/home/sjg/c/src chroot=/home/sjg/c/chroot -vboot=USE_STDINT=1 VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference +vboot=VBOOT_DEBUG=1 MAKEFLAGS_VBOOT=DEBUG=1 CFLAGS_EXTRA_VBOOT=-DUNROLL_LOOPS VBOOT_SOURCE=${src}/platform/vboot_reference chromeos_coreboot=VBOOT=${chroot}/build/link/usr ${vboot} chromeos_daisy=VBOOT=${chroot}/build/daisy/usr ${vboot} chromeos_peach=VBOOT=${chroot}/build/peach_pit/usr ${vboot} diff --git a/tools/env/Makefile b/tools/env/Makefile index 4633e0e72b..b627796e94 100644 --- a/tools/env/Makefile +++ b/tools/env/Makefile @@ -9,7 +9,8 @@ override HOSTCC = $(CC) # Compile for a hosted environment on the target -HOST_EXTRACFLAGS = $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \ +HOST_EXTRACFLAGS = -I$(srctree)/tools \ + $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \ -idirafter $(srctree)/tools/env \ -DUSE_HOSTCC \ -DTEXT_BASE=$(TEXT_BASE) diff --git a/tools/k3_fit_atf.sh b/tools/k3_fit_atf.sh new file mode 100755 index 0000000000..430b5ca616 --- /dev/null +++ b/tools/k3_fit_atf.sh @@ -0,0 +1,99 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0+ +# +# script to generate FIT image source for K3 Family boards with +# ATF, OPTEE, SPL and multiple device trees (given on the command line). +# Inspired from board/sunxi/mksunxi_fit_atf.sh +# +# usage: $0 <dt_name> [<dt_name> [<dt_name] ...] + +[ -z "$ATF" ] && ATF="bl31.bin" + +if [ ! -f $ATF ]; then + echo "WARNING ATF file $ATF NOT found, resulting binary is non-functional" >&2 + ATF=/dev/null +fi + +[ -z "$TEE" ] && TEE="bl32.bin" + +if [ ! -f $TEE ]; then + echo "WARNING OPTEE file $TEE NOT found, resulting might be non-functional" >&2 + TEE=/dev/null +fi + +cat << __HEADER_EOF +/dts-v1/; + +/ { + description = "Configuration to load ATF and SPL"; + #address-cells = <1>; + + images { + atf { + description = "ARM Trusted Firmware"; + data = /incbin/("$ATF"); + type = "firmware"; + arch = "arm64"; + compression = "none"; + os = "arm-trusted-firmware"; + load = <0x70000000>; + entry = <0x70000000>; + }; + tee { + description = "OPTEE"; + data = /incbin/("$TEE"); + type = "tee"; + arch = "arm64"; + compression = "none"; + os = "tee"; + load = <0x9e800000>; + entry = <0x9e800000>; + }; + spl { + description = "SPL (64-bit)"; + data = /incbin/("spl/u-boot-spl-nodtb.bin"); + type = "standalone"; + os = "U-Boot"; + arch = "arm64"; + compression = "none"; + load = <0x80080000>; + entry = <0x80080000>; + }; +__HEADER_EOF + +for dtname in $* +do + cat << __FDT_IMAGE_EOF + $(basename $dtname) { + description = "$(basename $dtname .dtb)"; + data = /incbin/("$dtname"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + }; +__FDT_IMAGE_EOF +done + +cat << __CONF_HEADER_EOF + }; + configurations { + default = "$(basename $1)"; + +__CONF_HEADER_EOF + +for dtname in $* +do + cat << __CONF_SECTION_EOF + $(basename $dtname) { + description = "$(basename $dtname .dtb)"; + firmware = "atf"; + loadables = "tee", "spl"; + fdt = "$(basename $dtname)"; + }; +__CONF_SECTION_EOF +done + +cat << __ITS_EOF + }; +}; +__ITS_EOF diff --git a/tools/mkimage.c b/tools/mkimage.c index e0d4d20be4..6abd4d6a8b 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -318,6 +318,7 @@ int main(int argc, char **argv) struct image_type_params *tparams = NULL; int pad_len = 0; int dfd; + size_t map_len; params.cmdname = *argv; params.addr = 0; @@ -576,7 +577,8 @@ int main(int argc, char **argv) } params.file_size = sbuf.st_size; - ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0); + map_len = sbuf.st_size; + ptr = mmap(0, map_len, PROT_READ | PROT_WRITE, MAP_SHARED, ifd, 0); if (ptr == MAP_FAILED) { fprintf (stderr, "%s: Can't map %s: %s\n", params.cmdname, params.imagefile, strerror(errno)); @@ -600,7 +602,7 @@ int main(int argc, char **argv) params.cmdname, tparams->name); } - (void) munmap((void *)ptr, sbuf.st_size); + (void)munmap((void *)ptr, map_len); /* We're a bit of paranoid */ #if defined(_POSIX_SYNCHRONIZED_IO) && \ diff --git a/tools/version.h b/tools/version.h new file mode 120000 index 0000000000..bb576071e8 --- /dev/null +++ b/tools/version.h @@ -0,0 +1 @@ +../include/version.h
\ No newline at end of file |