diff options
Diffstat (limited to 'arch')
100 files changed, 1372 insertions, 900 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a7f8e7f4b88f..2d34c0a44877 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1467,7 +1467,7 @@ config ARM_PSCI config ARCH_NR_GPIO int default 2048 if ARCH_SOCFPGA - default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \ + default 1024 if ARCH_BRCMSTB || ARCH_RENESAS || ARCH_TEGRA || \ ARCH_ZYNQ default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \ SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 199ebc1c4538..693f84392f1b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -942,6 +942,13 @@ choice via SCIF0 on Renesas RZ/G1M (R8A7743), R-Car H2 (R8A7790), M2-W (R8A7791), V2H (R8A7792), or M2-N (R8A7793). + config DEBUG_RCAR_GEN2_SCIF1 + bool "Kernel low-level debugging messages via SCIF1 on R8A77470" + depends on ARCH_R8A77470 + help + Say Y here if you want kernel low-level debugging support + via SCIF1 on Renesas RZ/G1C (R8A77470). + config DEBUG_RCAR_GEN2_SCIF2 bool "Kernel low-level debugging messages via SCIF2 on R8A7794" depends on ARCH_R8A7794 @@ -1495,6 +1502,7 @@ config DEBUG_LL_INCLUDE default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF2 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF0 + default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF1 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF2 default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF4 default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA0 @@ -1617,6 +1625,7 @@ config DEBUG_UART_PHYS default 0xe6c80000 if DEBUG_RMOBILE_SCIFA4 default 0xe6e58000 if DEBUG_RCAR_GEN2_SCIF2 default 0xe6e60000 if DEBUG_RCAR_GEN2_SCIF0 + default 0xe6e68000 if DEBUG_RCAR_GEN2_SCIF1 default 0xe6ee0000 if DEBUG_RCAR_GEN2_SCIF4 default 0xe8008000 if DEBUG_R7S72100_SCIF2 default 0xf0000be0 if ARCH_EBSA110 @@ -1651,8 +1660,8 @@ config DEBUG_UART_PHYS DEBUG_NETX_UART || \ DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \ DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \ - DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \ - DEBUG_RCAR_GEN2_SCIF4 || \ + DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF1 || \ + DEBUG_RCAR_GEN2_SCIF2 || DEBUG_RCAR_GEN2_SCIF4 || \ DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \ DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \ DEBUG_S3C64XX_UART || \ diff --git a/arch/arm/Makefile b/arch/arm/Makefile index e4e537f27339..a92f5a876d96 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -212,7 +212,7 @@ machine-$(CONFIG_ARCH_S3C24XX) += s3c24xx machine-$(CONFIG_ARCH_S3C64XX) += s3c64xx machine-$(CONFIG_ARCH_S5PV210) += s5pv210 machine-$(CONFIG_ARCH_SA1100) += sa1100 -machine-$(CONFIG_ARCH_SHMOBILE) += shmobile +machine-$(CONFIG_ARCH_RENESAS) += shmobile machine-$(CONFIG_ARCH_SIRF) += prima2 machine-$(CONFIG_ARCH_SOCFPGA) += socfpga machine-$(CONFIG_ARCH_STI) += sti diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 70b4a14ed993..1e9f7af8f70f 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DMABOUNCE) += dmabounce.o obj-$(CONFIG_SHARP_LOCOMO) += locomo.o obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o obj-$(CONFIG_SHARP_SCOOP) += scoop.o +obj-$(CONFIG_SMP) += secure_cntvoff.o obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o CFLAGS_REMOVE_mcpm_entry.o = -pg diff --git a/arch/arm/common/secure_cntvoff.S b/arch/arm/common/secure_cntvoff.S new file mode 100644 index 000000000000..53fc7bdb6c2e --- /dev/null +++ b/arch/arm/common/secure_cntvoff.S @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2014 Renesas Electronics Corporation + * + * Initialization of CNTVOFF register from secure mode + * + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + +ENTRY(secure_cntvoff_init) + .arch armv7-a + /* + * CNTVOFF has to be initialized either from non-secure Hypervisor + * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled + * then it should be handled by the secure code. The CPU must implement + * the virtualization extensions. + */ + cps #MON_MODE + mrc p15, 0, r1, c1, c1, 0 /* Get Secure Config */ + orr r0, r1, #1 + mcr p15, 0, r0, c1, c1, 0 /* Set Non Secure bit */ + isb + mov r0, #0 + mcrr p15, 4, r0, r0, c14 /* CNTVOFF = 0 */ + isb + mcr p15, 0, r1, c1, c1, 0 /* Set Secure bit */ + isb + cps #SVC_MODE + ret lr +ENDPROC(secure_cntvoff_init) diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h index cb546425da8a..d1b62ee69f3b 100644 --- a/arch/arm/include/asm/cputype.h +++ b/arch/arm/include/asm/cputype.h @@ -2,9 +2,6 @@ #ifndef __ASM_ARM_CPUTYPE_H #define __ASM_ARM_CPUTYPE_H -#include <linux/stringify.h> -#include <linux/kernel.h> - #define CPUID_ID 0 #define CPUID_CACHETYPE 1 #define CPUID_TCM 2 @@ -62,6 +59,7 @@ ((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK) #define ARM_CPU_IMP_ARM 0x41 +#define ARM_CPU_IMP_BRCM 0x42 #define ARM_CPU_IMP_DEC 0x44 #define ARM_CPU_IMP_INTEL 0x69 @@ -79,6 +77,10 @@ #define ARM_CPU_PART_CORTEX_A15 0x4100c0f0 #define ARM_CPU_PART_MASK 0xff00fff0 +/* Broadcom implemented processors */ +#define ARM_CPU_PART_BRAHMA_B15 0x420000f0 +#define ARM_CPU_PART_BRAHMA_B53 0x42001000 + /* DEC implemented cores */ #define ARM_CPU_PART_SA1100 0x4400a110 @@ -98,6 +100,11 @@ /* Qualcomm implemented cores */ #define ARM_CPU_PART_SCORPION 0x510002d0 +#ifndef __ASSEMBLY__ + +#include <linux/stringify.h> +#include <linux/kernel.h> + extern unsigned int processor_id; #ifdef CONFIG_CPU_CP15 @@ -326,4 +333,6 @@ static inline int __attribute_const__ cpuid_feature_extract_field(u32 features, #define cpuid_feature_extract(reg, field) \ cpuid_feature_extract_field(read_cpuid_ext(reg), field) +#endif /* __ASSEMBLY__ */ + #endif diff --git a/arch/arm/include/asm/secure_cntvoff.h b/arch/arm/include/asm/secure_cntvoff.h new file mode 100644 index 000000000000..1f93aee1f630 --- /dev/null +++ b/arch/arm/include/asm/secure_cntvoff.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASMARM_ARCH_CNTVOFF_H +#define __ASMARM_ARCH_CNTVOFF_H + +extern void secure_cntvoff_init(void); + +#endif diff --git a/arch/arm/include/debug/brcmstb.S b/arch/arm/include/debug/brcmstb.S index c826f15d2f80..0f580caa81e5 100644 --- a/arch/arm/include/debug/brcmstb.S +++ b/arch/arm/include/debug/brcmstb.S @@ -11,20 +11,25 @@ * GNU General Public License for more details. */ #include <linux/serial_reg.h> +#include <asm/cputype.h> /* Physical register offset and virtual register offset */ #define REG_PHYS_BASE 0xf0000000 +#define REG_PHYS_BASE_V7 0x08000000 #define REG_VIRT_BASE 0xfc000000 #define REG_PHYS_ADDR(x) ((x) + REG_PHYS_BASE) +#define REG_PHYS_ADDR_V7(x) ((x) + REG_PHYS_BASE_V7) /* Product id can be read from here */ #define SUN_TOP_CTRL_BASE REG_PHYS_ADDR(0x404000) +#define SUN_TOP_CTRL_BASE_V7 REG_PHYS_ADDR_V7(0x404000) #define UARTA_3390 REG_PHYS_ADDR(0x40a900) #define UARTA_7250 REG_PHYS_ADDR(0x40b400) #define UARTA_7260 REG_PHYS_ADDR(0x40c000) #define UARTA_7268 UARTA_7260 #define UARTA_7271 UARTA_7268 +#define UARTA_7278 REG_PHYS_ADDR_V7(0x40c000) #define UARTA_7364 REG_PHYS_ADDR(0x40b000) #define UARTA_7366 UARTA_7364 #define UARTA_74371 REG_PHYS_ADDR(0x406b00) @@ -55,8 +60,21 @@ mov \rv, #0 @ yes; record init is done str \rv, [\tmp] + /* Check for V7 memory map if B53 */ + mrc p15, 0, \rv, c0, c0, 0 @ get Main ID register + ldr \rp, =ARM_CPU_PART_MASK + and \rv, \rv, \rp + ldr \rp, =ARM_CPU_PART_BRAHMA_B53 @ check for B53 CPU + cmp \rv, \rp + bne 10f + + /* if PERIPHBASE doesn't overlap REG_PHYS_BASE use V7 map */ + mrc p15, 1, \rv, c15, c3, 0 @ get PERIPHBASE from CBAR + ands \rv, \rv, #REG_PHYS_BASE + ldreq \rp, =SUN_TOP_CTRL_BASE_V7 + /* Check SUN_TOP_CTRL base */ - ldr \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA +10: ldrne \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA ldr \rv, [\rp, #0] @ get register contents ARM_BE8( rev \rv, \rv ) and \rv, \rv, #0xffffff00 @ strip revision bits [7:0] @@ -72,6 +90,7 @@ ARM_BE8( rev \rv, \rv ) 27: checkuart(\rp, \rv, 0x07437100, 74371) 28: checkuart(\rp, \rv, 0x74390000, 7439) 29: checkuart(\rp, \rv, 0x74450000, 7445) +30: checkuart(\rp, \rv, 0x72780000, 7278) /* No valid UART found */ 90: mov \rp, #0 diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig index 63ab1d368625..3d719cf645e3 100644 --- a/arch/arm/mach-berlin/Kconfig +++ b/arch/arm/mach-berlin/Kconfig @@ -23,8 +23,12 @@ config MACH_BERLIN_BG2 config MACH_BERLIN_BG2CD bool "Marvell Armada 1500-mini (BG2CD)" + select ARM_ERRATA_754322 + select ARM_ERRATA_775420 + select ARM_GLOBAL_TIMER select CACHE_L2X0 - select HAVE_ARM_TWD if SMP + select HAVE_ARM_SCU + select HAVE_ARM_TWD select PINCTRL_BERLIN_BG2CD config MACH_BERLIN_BG2Q diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c index ac181c6797ee..2424ad40190c 100644 --- a/arch/arm/mach-berlin/berlin.c +++ b/arch/arm/mach-berlin/berlin.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Device Tree support for Marvell Berlin SoCs. * @@ -5,10 +6,6 @@ * * based on GPL'ed 2.6 kernel sources * (c) Marvell International Ltd. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ #include <linux/init.h> diff --git a/arch/arm/mach-berlin/headsmp.S b/arch/arm/mach-berlin/headsmp.S index dc82a3486b05..3057885d9772 100644 --- a/arch/arm/mach-berlin/headsmp.S +++ b/arch/arm/mach-berlin/headsmp.S @@ -1,11 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2014 Marvell Technology Group Ltd. * * Antoine Ténart <antoine.tenart@free-electrons.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/linkage.h> diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c index 7586b7aec272..593fc4a69d84 100644 --- a/arch/arm/mach-berlin/platsmp.c +++ b/arch/arm/mach-berlin/platsmp.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2014 Marvell Technology Group Ltd. * * Antoine Ténart <antoine.tenart@free-electrons.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/io.h> @@ -81,7 +78,6 @@ static void __init berlin_smp_prepare_cpus(unsigned int max_cpus) goto unmap_scu; scu_enable(scu_base); - flush_cache_all(); /* * Write the first instruction the CPU will execute after being reset diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c index ff8b7e76b6e9..e4ab3f3a2a1f 100644 --- a/arch/arm/mach-davinci/aemif.c +++ b/arch/arm/mach-davinci/aemif.c @@ -189,7 +189,7 @@ int davinci_aemif_setup(struct platform_device *pdev) * Setup Async configuration register in case we did not boot * from NAND and so bootloader did not bother to set it up. */ - val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4); + val = davinci_aemif_readl(base, A1CR_OFFSET + pdata->core_chipsel * 4); /* * Extended Wait is not valid and Select Strobe mode is not * used @@ -198,13 +198,13 @@ int davinci_aemif_setup(struct platform_device *pdev) if (pdata->options & NAND_BUSWIDTH_16) val |= 0x1; - davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val); + davinci_aemif_writel(base, A1CR_OFFSET + pdata->core_chipsel * 4, val); clkrate = clk_get_rate(clk); if (pdata->timing) - ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id, - clkrate); + ret = davinci_aemif_setup_timing(pdata->timing, base, + pdata->core_chipsel, clkrate); if (ret < 0) dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 004f9c8de032..4568c7392be3 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -310,6 +310,7 @@ static struct davinci_aemif_timing da830_evm_nandflash_timing = { }; static struct davinci_nand_pdata da830_evm_nand_pdata = { + .core_chipsel = 1, .parts = da830_evm_nand_partitions, .nr_parts = ARRAY_SIZE(da830_evm_nand_partitions), .ecc_mode = NAND_ECC_HW, diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 3063478bcc36..b4caeecdab1c 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -244,6 +244,7 @@ static struct davinci_aemif_timing da850_evm_nandflash_timing = { }; static struct davinci_nand_pdata da850_evm_nandflash_data = { + .core_chipsel = 1, .parts = da850_evm_nandflash_partition, .nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition), .ecc_mode = NAND_ECC_HW, diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index cb30637d9eaf..d95000dc534c 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -77,6 +77,7 @@ static struct mtd_partition davinci_nand_partitions[] = { }; static struct davinci_nand_pdata davinci_nand_data = { + .core_chipsel = 0, .mask_chipsel = BIT(14), .parts = davinci_nand_partitions, .nr_parts = ARRAY_SIZE(davinci_nand_partitions), diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c index 59743bd76793..8249a0bf69f0 100644 --- a/arch/arm/mach-davinci/board-dm355-leopard.c +++ b/arch/arm/mach-davinci/board-dm355-leopard.c @@ -72,6 +72,7 @@ static struct mtd_partition davinci_nand_partitions[] = { }; static struct davinci_nand_pdata davinci_nand_data = { + .core_chipsel = 0, .mask_chipsel = BIT(14), .parts = davinci_nand_partitions, .nr_parts = ARRAY_SIZE(davinci_nand_partitions), diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index 0ac085b58a2b..435f7ec7d9af 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -138,6 +138,7 @@ static struct mtd_partition davinci_nand_partitions[] = { }; static struct davinci_nand_pdata davinci_nand_data = { + .core_chipsel = 0, .mask_chipsel = BIT(14), .parts = davinci_nand_partitions, .nr_parts = ARRAY_SIZE(davinci_nand_partitions), diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 95b55aae1366..82d9d70ab6be 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -152,6 +152,7 @@ static struct davinci_aemif_timing davinci_evm_nandflash_timing = { }; static struct davinci_nand_pdata davinci_evm_nandflash_data = { + .core_chipsel = 0, .parts = davinci_evm_nandflash_partition, .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition), .ecc_mode = NAND_ECC_HW, @@ -768,6 +769,8 @@ static __init void davinci_evm_init(void) struct clk *aemif_clk; struct davinci_soc_info *soc_info = &davinci_soc_info; + dm644x_init_devices(); + ret = dm644x_gpio_register(); if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 2d37f5b0e1f5..764be73735a2 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -84,6 +84,7 @@ static struct davinci_aemif_timing dm6467tevm_nandflash_timing = { }; static struct davinci_nand_pdata davinci_nand_data = { + .core_chipsel = 0, .mask_cle = 0x80000, .mask_ale = 0x40000, .parts = davinci_nand_partitions, diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c index d1c85484c2e2..37b3e48a21d1 100644 --- a/arch/arm/mach-davinci/board-mityomapl138.c +++ b/arch/arm/mach-davinci/board-mityomapl138.c @@ -400,6 +400,7 @@ static struct mtd_partition mityomapl138_nandflash_partition[] = { }; static struct davinci_nand_pdata mityomapl138_nandflash_data = { + .core_chipsel = 1, .parts = mityomapl138_nandflash_partition, .nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition), .ecc_mode = NAND_ECC_HW, diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index f2875770fbff..25ad9b0612be 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -87,6 +87,7 @@ static struct mtd_partition davinci_ntosd2_nandflash_partition[] = { }; static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = { + .core_chipsel = 0, .parts = davinci_ntosd2_nandflash_partition, .nr_parts = ARRAY_SIZE(davinci_ntosd2_nandflash_partition), .ecc_mode = NAND_ECC_HW, @@ -174,6 +175,8 @@ static __init void davinci_ntosd2_init(void) struct clk *aemif_clk; struct davinci_soc_info *soc_info = &davinci_soc_info; + dm644x_init_devices(); + ret = dm644x_gpio_register(); if (ret) pr_warn("%s: GPIO init failed: %d\n", __func__, ret); diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 2922da9d1684..e7c1728b0833 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -134,6 +134,8 @@ static __init void davinci_sffsdr_init(void) { struct davinci_soc_info *soc_info = &davinci_soc_info; + dm644x_init_devices(); + platform_add_devices(davinci_sffsdr_devices, ARRAY_SIZE(davinci_sffsdr_devices)); sffsdr_init_i2c(); diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index 270cef85750a..376cdd51ce9d 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h @@ -104,6 +104,7 @@ int dm365_gpio_register(void); /* DM644x function declarations */ void dm644x_init(void); +void dm644x_init_devices(void); void dm644x_init_time(void); void dm644x_init_asp(void); int dm644x_init_video(struct vpfe_config *, struct vpbe_config *); diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index b409801649e1..a2e8586c8a6d 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -961,19 +961,14 @@ int __init dm644x_init_video(struct vpfe_config *vpfe_cfg, return 0; } -static int __init dm644x_init_devices(void) +void __init dm644x_init_devices(void) { struct platform_device *edma_pdev; - int ret = 0; - - if (!cpu_is_davinci_dm644x()) - return 0; + int ret; edma_pdev = platform_device_register_full(&dm644x_edma_device); - if (IS_ERR(edma_pdev)) { + if (IS_ERR(edma_pdev)) pr_warn("%s: Failed to register eDMA\n", __func__); - return PTR_ERR(edma_pdev); - } platform_device_register(&dm644x_mdio_device); platform_device_register(&dm644x_emac_device); @@ -982,6 +977,4 @@ static int __init dm644x_init_devices(void) if (ret) pr_warn("%s: watchdog init failed: %d\n", __func__, ret); - return ret; } -postcore_initcall(dm644x_init_devices); diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 647c319f9f5f..b40963cf91c7 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -8,7 +8,6 @@ menuconfig ARCH_EXYNOS bool "Samsung EXYNOS" depends on ARCH_MULTI_V7 - select ARCH_HAS_BANDGAP select ARCH_HAS_HOLES_MEMORYMODEL select ARCH_SUPPORTS_BIG_ENDIAN select ARM_AMBA @@ -108,18 +107,6 @@ config SOC_EXYNOS5420 default y depends on ARCH_EXYNOS5 -config SOC_EXYNOS5440 - bool "SAMSUNG EXYNOS5440" - default y - depends on ARCH_EXYNOS5 - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - select HAVE_ARM_ARCH_TIMER - select AUTO_ZRELADDR - select PINCTRL_EXYNOS5440 - select PM_OPP - help - Enable EXYNOS5440 SoC support - config SOC_EXYNOS5800 bool "SAMSUNG EXYNOS5800" default y diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index 098f84a149a3..dcd21bb95e3b 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h @@ -21,7 +21,6 @@ #define EXYNOS5250_SOC_ID 0x43520000 #define EXYNOS5410_SOC_ID 0xE5410000 #define EXYNOS5420_SOC_ID 0xE5420000 -#define EXYNOS5440_SOC_ID 0xE5440000 #define EXYNOS5800_SOC_ID 0xE5422000 #define EXYNOS5_SOC_MASK 0xFFFFF000 @@ -39,7 +38,6 @@ IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK) IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK) IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK) IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK) -IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK) IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK) #if defined(CONFIG_SOC_EXYNOS3250) @@ -82,22 +80,12 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK) # define soc_is_exynos5420() 0 #endif -#if defined(CONFIG_SOC_EXYNOS5440) -# define soc_is_exynos5440() is_samsung_exynos5440() -#else -# define soc_is_exynos5440() 0 -#endif - #if defined(CONFIG_SOC_EXYNOS5800) # define soc_is_exynos5800() is_samsung_exynos5800() #else # define soc_is_exynos5800() 0 #endif -#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4412()) -#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \ - soc_is_exynos5420() || soc_is_exynos5800()) - extern u32 cp15_save_diag; extern u32 cp15_save_power; @@ -149,6 +137,11 @@ extern void exynos_cpu_restore_register(void); extern void exynos_pm_central_suspend(void); extern int exynos_pm_central_resume(void); extern void exynos_enter_aftr(void); +#ifdef CONFIG_SMP +extern void exynos_scu_enable(void); +#else +static inline void exynos_scu_enable(void) { } +#endif extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data; diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 8c4f5e342dc1..f4b6c93a7fd0 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -24,15 +24,6 @@ #include "common.h" -static struct map_desc exynos4_iodesc[] __initdata = { - { - .virtual = (unsigned long)S5P_VA_COREPERI_BASE, - .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI), - .length = SZ_8K, - .type = MT_DEVICE, - }, -}; - static struct platform_device exynos_cpuidle = { .name = "exynos_cpuidle", #ifdef CONFIG_ARM_EXYNOS_CPUIDLE @@ -63,15 +54,6 @@ void __init exynos_sysram_init(void) } } -static void __init exynos_init_late(void) -{ - if (of_machine_is_compatible("samsung,exynos5440")) - /* to be supported later */ - return; - - exynos_pm_init(); -} - static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, int depth, void *data) { @@ -79,8 +61,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, const __be32 *reg; int len; - if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && - !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) + if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid")) return 0; reg = of_get_flat_dt_prop(node, "reg", &len); @@ -95,17 +76,6 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, return 1; } -/* - * exynos_map_io - * - * register the standard cpu IO areas - */ -static void __init exynos_map_io(void) -{ - if (soc_is_exynos4()) - iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc)); -} - static void __init exynos_init_io(void) { debug_ll_io_init(); @@ -114,8 +84,6 @@ static void __init exynos_init_io(void) /* detect cpu id and rev. */ s5p_init_cpu(S5P_VA_CHIPID); - - exynos_map_io(); } /* @@ -209,7 +177,6 @@ static char const *const exynos_dt_compat[] __initconst = { "samsung,exynos5250", "samsung,exynos5260", "samsung,exynos5420", - "samsung,exynos5440", NULL }; @@ -232,7 +199,7 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)") .init_early = exynos_firmware_init, .init_irq = exynos_init_irq, .init_machine = exynos_dt_machine_init, - .init_late = exynos_init_late, + .init_late = exynos_pm_init, .dt_compat = exynos_dt_compat, .dt_fixup = exynos_dt_fixup, MACHINE_END diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 37a5ea5e2602..22ebe3654633 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -15,6 +15,4 @@ #define EXYNOS_PA_CHIPID 0x10000000 -#define EXYNOS4_PA_COREPERI 0x10500000 - #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 5156fe70e030..6a1e682371b3 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -163,6 +163,26 @@ int exynos_cluster_power_state(int cluster) S5P_CORE_LOCAL_PWR_EN); } +/** + * exynos_scu_enable : enables SCU for Cortex-A9 based system + */ +void exynos_scu_enable(void) +{ + struct device_node *np; + static void __iomem *scu_base; + + if (!scu_base) { + np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); + if (np) { + scu_base = of_iomap(np, 0); + of_node_put(np); + } else { + scu_base = ioremap(scu_a9_get_base(), SZ_4K); + } + } + scu_enable(scu_base); +} + static void __iomem *cpu_boot_reg_base(void) { if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) @@ -219,11 +239,6 @@ static void write_pen_release(int val) sync_cache_w(&pen_release); } -static void __iomem *scu_base_addr(void) -{ - return (void __iomem *)(S5P_VA_SCU); -} - static DEFINE_SPINLOCK(boot_lock); static void exynos_secondary_init(unsigned int cpu) @@ -389,7 +404,7 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) exynos_set_delayed_reset_assertion(true); if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) - scu_enable(scu_base_addr()); + exynos_scu_enable(); /* * Write the address of secondary startup into the diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index a822c5073715..48e7fb38613e 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -22,8 +22,6 @@ #include <asm/suspend.h> #include <asm/cacheflush.h> -#include <mach/map.h> - #include "common.h" static inline void __iomem *exynos_boot_vector_addr(void) @@ -172,7 +170,7 @@ void exynos_enter_aftr(void) cpu_suspend(0, exynos_aftr_finisher); if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { - scu_enable(S5P_VA_SCU); + exynos_scu_enable(); if (call_firmware_op(resume) == -ENOSYS) exynos_cpu_restore_register(); } diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index c2ed997fedef..d3db306a5a70 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -30,8 +30,6 @@ #include <asm/smp_scu.h> #include <asm/suspend.h> -#include <mach/map.h> - #include <plat/pm-common.h> #include "common.h" @@ -401,7 +399,7 @@ static void exynos_pm_resume(void) goto early_wakeup; if (cpuid == ARM_CPU_PART_CORTEX_A9) - scu_enable(S5P_VA_SCU); + exynos_scu_enable(); if (call_firmware_op(resume) == -ENOSYS && cpuid == ARM_CPU_PART_CORTEX_A9) diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index e47fa13f4b0c..6f4232384774 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -501,6 +501,7 @@ config SOC_IMX6SL config SOC_IMX6SLL bool "i.MX6 SoloLiteLite support" + select PINCTRL_IMX6SLL select SOC_IMX6 help diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c index 68c3f0799d5b..9d87f1dcf7bb 100644 --- a/arch/arm/mach-imx/mach-mx31_3ds.c +++ b/arch/arm/mach-imx/mach-mx31_3ds.c @@ -374,26 +374,12 @@ static struct imx_ssi_platform_data mx31_3ds_ssi_pdata = { }; /* SPI */ -static int spi0_internal_chipselect[] = { - MXC_SPI_CS(0), - MXC_SPI_CS(1), - MXC_SPI_CS(2), -}; - static const struct spi_imx_master spi0_pdata __initconst = { - .chipselect = spi0_internal_chipselect, - .num_chipselect = ARRAY_SIZE(spi0_internal_chipselect), -}; - -static int spi1_internal_chipselect[] = { - MXC_SPI_CS(0), - MXC_SPI_CS(1), - MXC_SPI_CS(2), + .num_chipselect = 3, }; static const struct spi_imx_master spi1_pdata __initconst = { - .chipselect = spi1_internal_chipselect, - .num_chipselect = ARRAY_SIZE(spi1_internal_chipselect), + .num_chipselect = 3, }; static struct spi_board_info mx31_3ds_spi_devs[] __initdata = { diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c index 6fd463642954..8bf52819d4d9 100644 --- a/arch/arm/mach-imx/mach-mx31lilly.c +++ b/arch/arm/mach-imx/mach-mx31lilly.c @@ -226,20 +226,12 @@ static void __init lilly1131_usb_init(void) /* SPI */ -static int spi_internal_chipselect[] = { - MXC_SPI_CS(0), - MXC_SPI_CS(1), - MXC_SPI_CS(2), -}; - static const struct spi_imx_master spi0_pdata __initconst = { - .chipselect = spi_internal_chipselect, - .num_chipselect = ARRAY_SIZE(spi_internal_chipselect), + .num_chipselect = 3, }; static const struct spi_imx_master spi1_pdata __initconst = { - .chipselect = spi_internal_chipselect, - .num_chipselect = ARRAY_SIZE(spi_internal_chipselect), + .num_chipselect = 3, }; static struct mc13xxx_platform_data mc13783_pdata __initdata = { diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c index a3250bc7f114..a3cbba6c955b 100644 --- a/arch/arm/mach-imx/mach-mx31lite.c +++ b/arch/arm/mach-imx/mach-mx31lite.c @@ -83,15 +83,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = { }; /* SPI */ -static int spi0_internal_chipselect[] = { - MXC_SPI_CS(0), - MXC_SPI_CS(1), - MXC_SPI_CS(2), -}; - static const struct spi_imx_master spi0_pdata __initconst = { - .chipselect = spi0_internal_chipselect, - .num_chipselect = ARRAY_SIZE(spi0_internal_chipselect), + .num_chipselect = 3, }; static const struct mxc_nand_platform_data @@ -133,13 +126,8 @@ static struct platform_device smsc911x_device = { * The MC13783 is the only hard-wired SPI device on the module. */ -static int spi1_internal_chipselect[] = { - MXC_SPI_CS(0), -}; - static const struct spi_imx_master spi1_pdata __initconst = { - .chipselect = spi1_internal_chipselect, - .num_chipselect = ARRAY_SIZE(spi1_internal_chipselect), + .num_chipselect = 1, }; static struct mc13xxx_platform_data mc13783_pdata __initdata = { diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c index 7716f83aecdd..643a3d749703 100644 --- a/arch/arm/mach-imx/mach-mx31moboard.c +++ b/arch/arm/mach-imx/mach-mx31moboard.c @@ -152,14 +152,8 @@ static const struct imxi2c_platform_data moboard_i2c1_data __initconst = { .bitrate = 100000, }; -static int moboard_spi1_cs[] = { - MXC_SPI_CS(0), - MXC_SPI_CS(2), -}; - static const struct spi_imx_master moboard_spi1_pdata __initconst = { - .chipselect = moboard_spi1_cs, - .num_chipselect = ARRAY_SIZE(moboard_spi1_cs), + .num_chipselect = 3, }; static struct regulator_consumer_supply sdhc_consumers[] = { @@ -296,19 +290,14 @@ static struct spi_board_info moboard_spi_board_info[] __initdata = { /* irq number is run-time assigned */ .max_speed_hz = 300000, .bus_num = 1, - .chip_select = 1, + .chip_select = 0, .platform_data = &moboard_pmic, .mode = SPI_CS_HIGH, }, }; -static int moboard_spi2_cs[] = { - MXC_SPI_CS(0), MXC_SPI_CS(1), -}; - static const struct spi_imx_master moboard_spi2_pdata __initconst = { - .chipselect = moboard_spi2_cs, - .num_chipselect = ARRAY_SIZE(moboard_spi2_cs), + .num_chipselect = 2, }; #define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0) diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c index ed675863655b..5714e2f1b106 100644 --- a/arch/arm/mach-imx/mach-pca100.c +++ b/arch/arm/mach-imx/mach-pca100.c @@ -20,7 +20,7 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/i2c.h> -#include <linux/platform_data/at24.h> +#include <linux/property.h> #include <linux/dma-mapping.h> #include <linux/spi/spi.h> #include <linux/spi/eeprom.h> @@ -168,16 +168,15 @@ static const struct imxi2c_platform_data pca100_i2c1_data __initconst = { .bitrate = 100000, }; -static struct at24_platform_data board_eeprom = { - .byte_len = 4096, - .page_size = 32, - .flags = AT24_FLAG_ADDR16, +static const struct property_entry board_eeprom_properties[] = { + PROPERTY_ENTRY_U32("pagesize", 32), + { } }; static struct i2c_board_info pca100_i2c_devices[] = { { - I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ - .platform_data = &board_eeprom, + I2C_BOARD_INFO("24c32", 0x52), /* E0=0, E1=1, E2=0 */ + .properties = board_eeprom_properties, }, { I2C_BOARD_INFO("pcf8563", 0x51), }, { diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c index b787ba6897e4..004737c40fda 100644 --- a/arch/arm/mach-imx/mach-pcm037.c +++ b/arch/arm/mach-imx/mach-pcm037.c @@ -23,7 +23,7 @@ #include <linux/smsc911x.h> #include <linux/interrupt.h> #include <linux/i2c.h> -#include <linux/platform_data/at24.h> +#include <linux/property.h> #include <linux/delay.h> #include <linux/spi/spi.h> #include <linux/irq.h> @@ -263,16 +263,15 @@ static const struct imxi2c_platform_data pcm037_i2c2_data __initconst = { .bitrate = 20000, }; -static struct at24_platform_data board_eeprom = { - .byte_len = 4096, - .page_size = 32, - .flags = AT24_FLAG_ADDR16, +static const struct property_entry board_eeprom_properties[] = { + PROPERTY_ENTRY_U32("pagesize", 32), + { } }; static struct i2c_board_info pcm037_i2c_devices[] = { { - I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ - .platform_data = &board_eeprom, + I2C_BOARD_INFO("24c32", 0x52), /* E0=0, E1=1, E2=0 */ + .properties = board_eeprom_properties, }, { I2C_BOARD_INFO("pcf8563", 0x51), } diff --git a/arch/arm/mach-imx/mach-pcm037_eet.c b/arch/arm/mach-imx/mach-pcm037_eet.c index 95bd97710494..15bc956d466b 100644 --- a/arch/arm/mach-imx/mach-pcm037_eet.c +++ b/arch/arm/mach-imx/mach-pcm037_eet.c @@ -56,11 +56,8 @@ static struct spi_board_info pcm037_spi_dev[] = { }; /* Platform Data for MXC CSPI */ -static int pcm037_spi1_cs[] = { MXC_SPI_CS(0), MXC_SPI_CS(1), }; - static const struct spi_imx_master pcm037_spi1_pdata __initconst = { - .chipselect = pcm037_spi1_cs, - .num_chipselect = ARRAY_SIZE(pcm037_spi1_cs), + .num_chipselect = 2, }; /* GPIO-keys input device */ diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c index 78e2bf8dcd96..e595e5368676 100644 --- a/arch/arm/mach-imx/mach-pcm043.c +++ b/arch/arm/mach-imx/mach-pcm043.c @@ -24,7 +24,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/i2c.h> -#include <linux/platform_data/at24.h> +#include <linux/property.h> #include <linux/usb/otg.h> #include <linux/usb/ulpi.h> @@ -110,16 +110,15 @@ static const struct imxi2c_platform_data pcm043_i2c0_data __initconst = { .bitrate = 50000, }; -static struct at24_platform_data board_eeprom = { - .byte_len = 4096, - .page_size = 32, - .flags = AT24_FLAG_ADDR16, +static const struct property_entry board_eeprom_properties[] = { + PROPERTY_ENTRY_U32("pagesize", 32), + { } }; static struct i2c_board_info pcm043_i2c_devices[] = { { - I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */ - .platform_data = &board_eeprom, + I2C_BOARD_INFO("24c32", 0x52), /* E0=0, E1=1, E2=0 */ + .properties = board_eeprom_properties, }, { I2C_BOARD_INFO("pcf8563", 0x51), }, diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c index 5ff154c9a086..da3336aaa4c5 100644 --- a/arch/arm/mach-imx/mach-vpr200.c +++ b/arch/arm/mach-imx/mach-vpr200.c @@ -29,7 +29,6 @@ #include <asm/mach/time.h> #include <linux/i2c.h> -#include <linux/platform_data/at24.h> #include <linux/mfd/mc13xxx.h> #include "common.h" @@ -145,15 +144,9 @@ static const struct imxi2c_platform_data vpr200_i2c0_data __initconst = { .bitrate = 50000, }; -static struct at24_platform_data vpr200_eeprom = { - .byte_len = 2048 / 8, - .page_size = 1, -}; - static struct i2c_board_info vpr200_i2c_devices[] = { { - I2C_BOARD_INFO("at24", 0x50), /* E0=0, E1=0, E2=0 */ - .platform_data = &vpr200_eeprom, + I2C_BOARD_INFO("24c02", 0x50), /* E0=0, E1=0, E2=0 */ }, { I2C_BOARD_INFO("mc13892", 0x08), .platform_data = &vpr200_pmic, diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 52e8e53ca154..80f54cb54276 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ #include <linux/gpio/driver.h> +#include <linux/gpio/machine.h> #include <linux/gpio.h> #include <linux/kernel.h> #include <linux/init.h> @@ -202,7 +203,10 @@ static struct resource latch2_resources[] = { }, }; +#define LATCH2_LABEL "latch2" + static struct bgpio_pdata latch2_pdata = { + .label = LATCH2_LABEL, .base = AMS_DELTA_LATCH2_GPIO_BASE, .ngpio = AMS_DELTA_LATCH2_NGPIO, }; @@ -217,6 +221,23 @@ static struct platform_device latch2_gpio_device = { }, }; +#define LATCH2_PIN_LCD_VBLEN 0 +#define LATCH2_PIN_LCD_NDISP 1 +#define LATCH2_PIN_NAND_NCE 2 +#define LATCH2_PIN_NAND_NRE 3 +#define LATCH2_PIN_NAND_NWP 4 +#define LATCH2_PIN_NAND_NWE 5 +#define LATCH2_PIN_NAND_ALE 6 +#define LATCH2_PIN_NAND_CLE 7 +#define LATCH2_PIN_KEYBRD_PWR 8 +#define LATCH2_PIN_KEYBRD_DATAOUT 9 +#define LATCH2_PIN_SCARD_RSTIN 10 +#define LATCH2_PIN_SCARD_CMDVCC 11 +#define LATCH2_PIN_MODEM_NRESET 12 +#define LATCH2_PIN_MODEM_CODEC 13 +#define LATCH2_PIN_HOOKFLASH1 14 +#define LATCH2_PIN_HOOKFLASH2 15 + static const struct gpio latch_gpios[] __initconst = { { .gpio = LATCH1_GPIO_BASE + 6, @@ -239,11 +260,6 @@ static const struct gpio latch_gpios[] __initconst = { .label = "scard_cmdvcc", }, { - .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC, - .flags = GPIOF_OUT_INIT_LOW, - .label = "modem_codec", - }, - { .gpio = AMS_DELTA_LATCH2_GPIO_BASE + 14, .flags = GPIOF_OUT_INIT_LOW, .label = "hookflash1", @@ -323,6 +339,22 @@ static struct platform_device ams_delta_nand_device = { .resource = ams_delta_nand_resources, }; +#define OMAP_GPIO_LABEL "gpio-0-15" + +static struct gpiod_lookup_table ams_delta_nand_gpio_table = { + .table = { + GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_NAND_RB, "rdy", + 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0), + { }, + }, +}; + static struct resource ams_delta_kp_resources[] = { [0] = { .start = INT_KEYBOARD, @@ -358,6 +390,14 @@ static struct platform_device ams_delta_lcd_device = { .id = -1, }; +static struct gpiod_lookup_table ams_delta_lcd_gpio_table = { + .table = { + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_VBLEN, "vblen", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_NDISP, "ndisp", 0), + { }, + }, +}; + static const struct gpio_led gpio_leds[] __initconst = { { .name = "camera", @@ -449,11 +489,35 @@ static struct platform_device ams_delta_audio_device = { .id = -1, }; +static struct gpiod_lookup_table ams_delta_audio_gpio_table = { + .table = { + GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_HOOK_SWITCH, + "hook_switch", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC, + "modem_codec", 0), + { }, + }, +}; + static struct platform_device cx20442_codec_device = { .name = "cx20442-codec", .id = -1, }; +static struct gpiod_lookup_table ams_delta_serio_gpio_table = { + .table = { + GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_DATA, + "data", 0), + GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_CLK, + "clock", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR, + "power", 0), + GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, + "dataout", 0), + { }, + }, +}; + static struct platform_device *ams_delta_devices[] __initdata = { &latch1_gpio_device, &latch2_gpio_device, @@ -468,6 +532,16 @@ static struct platform_device *late_devices[] __initdata = { &cx20442_codec_device, }; +static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = { + &ams_delta_audio_gpio_table, + &ams_delta_serio_gpio_table, +}; + +static struct gpiod_lookup_table *late_gpio_tables[] __initdata = { + &ams_delta_lcd_gpio_table, + &ams_delta_nand_gpio_table, +}; + static void __init ams_delta_init(void) { /* mux pins for uarts */ @@ -500,6 +574,20 @@ static void __init ams_delta_init(void) gpio_led_register_device(-1, &leds_pdata); platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices)); + /* + * As soon as devices have been registered, assign their dev_names + * to respective GPIO lookup tables before they are added. + */ + ams_delta_audio_gpio_table.dev_id = + dev_name(&ams_delta_audio_device.dev); + /* + * No device name is assigned to GPIO lookup table for serio device + * as long as serio driver is not converted to platform device driver. + */ + + gpiod_add_lookup_tables(ams_delta_gpio_tables, + ARRAY_SIZE(ams_delta_gpio_tables)); + ams_delta_init_fiq(); omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1); @@ -570,6 +658,15 @@ static int __init late_init(void) platform_add_devices(late_devices, ARRAY_SIZE(late_devices)); + /* + * As soon as devices have been registered, assign their dev_names + * to respective GPIO lookup tables before they are added. + */ + ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev); + ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev); + + gpiod_add_lookup_tables(late_gpio_tables, ARRAY_SIZE(late_gpio_tables)); + err = platform_device_register(&modem_nreset_device); if (err) { pr_err("Couldn't register the modem regulator device\n"); diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index c66372ed29e2..9ffa8d755a59 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c @@ -303,22 +303,22 @@ static const struct omap_lcd_config osk_lcd_config __initconst = { #ifdef CONFIG_OMAP_OSK_MISTRAL #include <linux/input.h> -#include <linux/platform_data/at24.h> +#include <linux/property.h> #include <linux/spi/spi.h> #include <linux/spi/ads7846.h> #include <linux/platform_data/keypad-omap.h> -static struct at24_platform_data at24c04 = { - .byte_len = SZ_4K / 8, - .page_size = 16, +static const struct property_entry mistral_at24_properties[] = { + PROPERTY_ENTRY_U32("pagesize", 16), + { } }; static struct i2c_board_info __initdata mistral_i2c_board_info[] = { { /* NOTE: powered from LCD supply */ I2C_BOARD_INFO("24c04", 0x50), - .platform_data = &at24c04, + .properties = mistral_at24_properties, }, /* TODO when driver support is ready: * - optionally ov9640 camera sensor at 0x30 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 0d9ce58bc464..01377c292db4 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -78,7 +78,6 @@ endif omap-4-5-pm-common = omap-mpuss-lowpower.o obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-pm-common) obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-pm-common) -obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o ifeq ($(CONFIG_PM),y) obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 6c61ecc62905..6b4f4975cf7a 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -31,8 +31,6 @@ static const struct of_device_id omap_dt_match_table[] __initconst = { static void __init __maybe_unused omap_generic_init(void) { pdata_quirks_init(omap_dt_match_table); - - omapdss_init_of(); omap_soc_device_init(); } diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index b79b1ca9aee9..6d44fe05a3fe 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -23,6 +23,7 @@ #include <linux/limits.h> #include <linux/err.h> #include <linux/clk-provider.h> +#include <linux/cpu_pm.h> #include <linux/io.h> @@ -31,6 +32,7 @@ #include "soc.h" #include "clock.h" #include "clockdomain.h" +#include "pm.h" /* clkdm_list contains all registered struct clockdomains */ static LIST_HEAD(clkdm_list); @@ -39,6 +41,8 @@ static LIST_HEAD(clkdm_list); static struct clkdm_autodep *autodeps; static struct clkdm_ops *arch_clkdm; +void clkdm_save_context(void); +void clkdm_restore_context(void); /* Private functions */ @@ -449,6 +453,22 @@ int clkdm_register_autodeps(struct clkdm_autodep *ia) return 0; } +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (enable_off_mode) + clkdm_save_context(); + break; + case CPU_CLUSTER_PM_EXIT: + if (enable_off_mode) + clkdm_restore_context(); + break; + } + + return NOTIFY_OK; +} + /** * clkdm_complete_init - set up the clockdomain layer * @@ -460,6 +480,7 @@ int clkdm_register_autodeps(struct clkdm_autodep *ia) int clkdm_complete_init(void) { struct clockdomain *clkdm; + static struct notifier_block nb; if (list_empty(&clkdm_list)) return -EACCES; @@ -474,6 +495,12 @@ int clkdm_complete_init(void) clkdm_clear_all_sleepdeps(clkdm); } + /* Only AM43XX can lose clkdm context during rtc-ddr suspend */ + if (soc_is_am43xx()) { + nb.notifier_call = cpu_notifier; + cpu_pm_register_notifier(&nb); + } + return 0; } @@ -1307,3 +1334,49 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh) return 0; } +/** + * _clkdm_save_context - save the context for the control of this clkdm + * + * Due to a suspend or hibernation operation, the state of the registers + * controlling this clkdm will be lost, save their context. + */ +static int _clkdm_save_context(struct clockdomain *clkdm, void *ununsed) +{ + if (!arch_clkdm || !arch_clkdm->clkdm_save_context) + return -EINVAL; + + return arch_clkdm->clkdm_save_context(clkdm); +} + +/** + * _clkdm_restore_context - restore context for control of this clkdm + * + * Restore the register values for this clockdomain. + */ +static int _clkdm_restore_context(struct clockdomain *clkdm, void *ununsed) +{ + if (!arch_clkdm || !arch_clkdm->clkdm_restore_context) + return -EINVAL; + + return arch_clkdm->clkdm_restore_context(clkdm); +} + +/** + * clkdm_save_context - Saves the context for each registered clkdm + * + * Save the context for each registered clockdomain. + */ +void clkdm_save_context(void) +{ + clkdm_for_each(_clkdm_save_context, NULL); +} + +/** + * clkdm_restore_context - Restores the context for each registered clkdm + * + * Restore the context for each registered clockdomain. + */ +void clkdm_restore_context(void) +{ + clkdm_for_each(_clkdm_restore_context, NULL); +} diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 24667a5a9dc0..c7d0953e4aa2 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -141,6 +141,7 @@ struct clockdomain { int usecount; int forcewake_count; struct list_head node; + u32 context; }; /** @@ -159,6 +160,8 @@ struct clockdomain { * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain * @clkdm_clk_enable: Put the clkdm in right state for a clock enable * @clkdm_clk_disable: Put the clkdm in right state for a clock disable + * @clkdm_save_context: Save the current clkdm context + * @clkdm_restore_context: Restore the clkdm context */ struct clkdm_ops { int (*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2); @@ -175,6 +178,8 @@ struct clkdm_ops { void (*clkdm_deny_idle)(struct clockdomain *clkdm); int (*clkdm_clk_enable)(struct clockdomain *clkdm); int (*clkdm_clk_disable)(struct clockdomain *clkdm); + int (*clkdm_save_context)(struct clockdomain *clkdm); + int (*clkdm_restore_context)(struct clockdomain *clkdm); }; int clkdm_register_platform_funcs(struct clkdm_ops *co); @@ -214,6 +219,9 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh); int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh); +void clkdm_save_context(void); +void clkdm_restore_context(void); + extern void __init omap242x_clockdomains_init(void); extern void __init omap243x_clockdomains_init(void); extern void __init omap3xxx_clockdomains_init(void); diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c index 1cc0247a2cb5..084d454f6074 100644 --- a/arch/arm/mach-omap2/cm33xx.c +++ b/arch/arm/mach-omap2/cm33xx.c @@ -72,6 +72,17 @@ static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) return v; } +static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask) +{ + u32 v; + + v = am33xx_cm_read_reg(inst, idx); + v &= mask; + v >>= __ffs(mask); + + return v; +} + /** * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield * @inst: CM instance register offset (*_INST macro) @@ -338,6 +349,46 @@ static u32 am33xx_cm_xlate_clkctrl(u8 part, u16 inst, u16 offset) return cm_base.pa + inst + offset; } +/** + * am33xx_clkdm_save_context - Save the clockdomain transition context + * @clkdm: The clockdomain pointer whose context needs to be saved + * + * Save the clockdomain transition context. + */ +static int am33xx_clkdm_save_context(struct clockdomain *clkdm) +{ + clkdm->context = am33xx_cm_read_reg_bits(clkdm->cm_inst, + clkdm->clkdm_offs, + AM33XX_CLKTRCTRL_MASK); + + return 0; +} + +/** + * am33xx_restore_save_context - Restore the clockdomain transition context + * @clkdm: The clockdomain pointer whose context needs to be restored + * + * Restore the clockdomain transition context. + */ +static int am33xx_clkdm_restore_context(struct clockdomain *clkdm) +{ + switch (clkdm->context) { + case OMAP34XX_CLKSTCTRL_DISABLE_AUTO: + am33xx_clkdm_deny_idle(clkdm); + break; + case OMAP34XX_CLKSTCTRL_FORCE_SLEEP: + am33xx_clkdm_sleep(clkdm); + break; + case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP: + am33xx_clkdm_wakeup(clkdm); + break; + case OMAP34XX_CLKSTCTRL_ENABLE_AUTO: + am33xx_clkdm_allow_idle(clkdm); + break; + } + return 0; +} + struct clkdm_ops am33xx_clkdm_operations = { .clkdm_sleep = am33xx_clkdm_sleep, .clkdm_wakeup = am33xx_clkdm_wakeup, @@ -345,6 +396,8 @@ struct clkdm_ops am33xx_clkdm_operations = { .clkdm_deny_idle = am33xx_clkdm_deny_idle, .clkdm_clk_enable = am33xx_clkdm_clk_enable, .clkdm_clk_disable = am33xx_clkdm_clk_disable, + .clkdm_save_context = am33xx_clkdm_save_context, + .clkdm_restore_context = am33xx_clkdm_restore_context, }; static const struct cm_ll_data am33xx_cm_ll_data = { diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c index 7deefee49fc3..c11ac492b626 100644 --- a/arch/arm/mach-omap2/cminst44xx.c +++ b/arch/arm/mach-omap2/cminst44xx.c @@ -481,6 +481,47 @@ static u32 omap4_cminst_xlate_clkctrl(u8 part, u16 inst, u16 offset) return _cm_bases[part].pa + inst + offset; } +/** + * omap4_clkdm_save_context - Save the clockdomain modulemode context + * @clkdm: The clockdomain pointer whose context needs to be saved + * + * Save the clockdomain modulemode context. + */ +static int omap4_clkdm_save_context(struct clockdomain *clkdm) +{ + clkdm->context = omap4_cminst_read_inst_reg(clkdm->prcm_partition, + clkdm->cm_inst, + clkdm->clkdm_offs + + OMAP4_CM_CLKSTCTRL); + clkdm->context &= OMAP4430_MODULEMODE_MASK; + return 0; +} + +/** + * omap4_clkdm_restore_context - Restore the clockdomain modulemode context + * @clkdm: The clockdomain pointer whose context needs to be restored + * + * Restore the clockdomain modulemode context. + */ +static int omap4_clkdm_restore_context(struct clockdomain *clkdm) +{ + switch (clkdm->context) { + case OMAP34XX_CLKSTCTRL_DISABLE_AUTO: + omap4_clkdm_deny_idle(clkdm); + break; + case OMAP34XX_CLKSTCTRL_FORCE_SLEEP: + omap4_clkdm_sleep(clkdm); + break; + case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP: + omap4_clkdm_wakeup(clkdm); + break; + case OMAP34XX_CLKSTCTRL_ENABLE_AUTO: + omap4_clkdm_allow_idle(clkdm); + break; + } + return 0; +} + struct clkdm_ops omap4_clkdm_operations = { .clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep, .clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep, @@ -496,6 +537,8 @@ struct clkdm_ops omap4_clkdm_operations = { .clkdm_deny_idle = omap4_clkdm_deny_idle, .clkdm_clk_enable = omap4_clkdm_clk_enable, .clkdm_clk_disable = omap4_clkdm_clk_disable, + .clkdm_save_context = omap4_clkdm_save_context, + .clkdm_restore_context = omap4_clkdm_restore_context, }; struct clkdm_ops am43xx_clkdm_operations = { diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index fbe0b78bf489..dff3750e432f 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -44,6 +44,9 @@ #define OMAP_INTC_START NR_IRQS +extern int (*omap_pm_soc_init)(void); +int omap_pm_nop_init(void); + #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP2) int omap2_pm_init(void); #else @@ -79,9 +82,12 @@ static inline int omap4_pm_init_early(void) #if defined(CONFIG_PM) && (defined(CONFIG_SOC_AM33XX) || \ defined(CONFIG_SOC_AM43XX)) -void amx3_common_pm_init(void); +int amx3_common_pm_init(void); #else -static inline void amx3_common_pm_init(void) { } +static inline int amx3_common_pm_init(void) +{ + return 0; +} #endif extern void omap2_init_common_infrastructure(void); @@ -122,14 +128,10 @@ void am43xx_init_early(void); void am43xx_init_late(void); void omap4430_init_early(void); void omap5_init_early(void); -void omap3_init_late(void); /* Do not use this one */ +void omap3_init_late(void); void omap4430_init_late(void); void omap2420_init_late(void); void omap2430_init_late(void); -void omap3430_init_late(void); -void omap35xx_init_late(void); -void omap3630_init_late(void); -void am35xx_init_late(void); void ti81xx_init_late(void); void am33xx_init_late(void); void omap5_init_late(void); @@ -350,7 +352,5 @@ extern int omap_dss_reset(struct omap_hwmod *); /* SoC specific clock initializer */ int omap_clk_init(void); -int __init omapdss_init_of(void); - #endif /* __ASSEMBLER__ */ #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */ diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 180da403639e..0bbfb20e193f 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c @@ -17,6 +17,7 @@ #include <linux/of_address.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h> +#include <linux/cpu_pm.h> #include "soc.h" #include "iomap.h" @@ -621,6 +622,110 @@ void __init omap3_ctrl_init(void) } #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */ +static unsigned long am43xx_control_reg_offsets[] = { + AM33XX_CONTROL_SYSCONFIG_OFFSET, + AM33XX_CONTROL_STATUS_OFFSET, + AM43XX_CONTROL_MPU_L2_CTRL_OFFSET, + AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET, + AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET, + AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET, + AM33XX_CONTROL_BANDGAP_CTRL_OFFSET, + AM33XX_CONTROL_BANDGAP_TRIM_OFFSET, + AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET, + AM33XX_CONTROL_MOSC_CTRL_OFFSET, + AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET, + AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET, + AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET, + AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET, + AM33XX_CONTROL_TPTC_CFG_OFFSET, + AM33XX_CONTROL_USB_CTRL0_OFFSET, + AM33XX_CONTROL_USB_CTRL1_OFFSET, + AM43XX_CONTROL_USB_CTRL2_OFFSET, + AM43XX_CONTROL_GMII_SEL_OFFSET, + AM43XX_CONTROL_MPUSS_CTRL_OFFSET, + AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET, + AM43XX_CONTROL_PWMSS_CTRL_OFFSET, + AM33XX_CONTROL_MREQPRIO_0_OFFSET, + AM33XX_CONTROL_MREQPRIO_1_OFFSET, + AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET, + AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET, + AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET, + AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET, + AM33XX_CONTROL_SMRT_CTRL_OFFSET, + AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET, + AM43XX_CONTROL_CQDETECT_STS_OFFSET, + AM43XX_CONTROL_CQDETECT_STS2_OFFSET, + AM43XX_CONTROL_VTP_CTRL_OFFSET, + AM33XX_CONTROL_VREF_CTRL_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET, + AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET, + AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET, + AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET, + AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET, + AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET, + AM33XX_CONTROL_RESET_ISO_OFFSET, +}; + +static u32 am33xx_control_vals[ARRAY_SIZE(am43xx_control_reg_offsets)]; + +/** + * am43xx_control_save_context - Save the wakeup domain registers + * + * Save the wkup domain registers + */ +void am43xx_control_save_context(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++) + am33xx_control_vals[i] = + omap_ctrl_readl(am43xx_control_reg_offsets[i]); +} + +/** + * am43xx_control_restore_context - Restore the wakeup domain registers + * + * Restore the wkup domain registers + */ +void am43xx_control_restore_context(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++) + omap_ctrl_writel(am33xx_control_vals[i], + am43xx_control_reg_offsets[i]); +} + +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (enable_off_mode) + am43xx_control_save_context(); + break; + case CPU_CLUSTER_PM_EXIT: + if (enable_off_mode) + am43xx_control_restore_context(); + break; + } + + return NOTIFY_OK; +} + struct control_init_data { int index; void __iomem *mem; @@ -699,6 +804,7 @@ int __init omap_control_init(void) const struct omap_prcm_init_data *data; int ret; struct regmap *syscon; + static struct notifier_block nb; for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) { data = match->data; @@ -731,6 +837,12 @@ int __init omap_control_init(void) } } + /* Only AM43XX can lose ctrl registers context during rtc-ddr suspend */ + if (soc_is_am43xx()) { + nb.notifier_call = cpu_notifier; + cpu_pm_register_notifier(&nb); + } + return 0; } diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h index ec406bc2c6d4..393b42110511 100644 --- a/arch/arm/mach-omap2/control.h +++ b/arch/arm/mach-omap2/control.h @@ -409,6 +409,67 @@ #define AM33XX_DEV_FEATURE 0x604 #define AM33XX_SGX_MASK BIT(29) +/* Additional AM33XX/AM43XX CONTROL registers */ +#define AM33XX_CONTROL_SYSCONFIG_OFFSET 0x0010 +#define AM33XX_CONTROL_STATUS_OFFSET 0x0040 +#define AM43XX_CONTROL_MPU_L2_CTRL_OFFSET 0x01e0 +#define AM33XX_CONTROL_CORTEX_VBBLDO_CTRL_OFFSET 0x041c +#define AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET 0x0428 +#define AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET 0x042c +#define AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET 0x0444 +#define AM33XX_CONTROL_BANDGAP_CTRL_OFFSET 0x0448 +#define AM33XX_CONTROL_BANDGAP_TRIM_OFFSET 0x044c +#define AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET 0x0458 +#define AM33XX_CONTROL_MOSC_CTRL_OFFSET 0x0468 +#define AM33XX_CONTROL_RCOSC_CTRL_OFFSET 0x046c +#define AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET 0x0470 +#define AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET 0x0534 +#define AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET 0x0608 +#define AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET 0x060c +#define AM33XX_CONTROL_MMU_CFG_OFFSET 0x0610 +#define AM33XX_CONTROL_TPTC_CFG_OFFSET 0x0614 +#define AM33XX_CONTROL_USB_CTRL0_OFFSET 0x0620 +#define AM33XX_CONTROL_USB_CTRL1_OFFSET 0x0628 +#define AM33XX_CONTROL_USB_WKUP_CTRL_OFFSET 0x0648 +#define AM43XX_CONTROL_USB_CTRL2_OFFSET 0x064c +#define AM43XX_CONTROL_GMII_SEL_OFFSET 0x0650 +#define AM43XX_CONTROL_MPUSS_CTRL_OFFSET 0x0654 +#define AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET 0x0658 +#define AM43XX_CONTROL_PWMSS_CTRL_OFFSET 0x0664 +#define AM33XX_CONTROL_MREQPRIO_0_OFFSET 0x0670 +#define AM33XX_CONTROL_MREQPRIO_1_OFFSET 0x0674 +#define AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET 0x0690 +#define AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET 0x0694 +#define AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET 0x0698 +#define AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET 0x069c +#define AM33XX_CONTROL_SMRT_CTRL_OFFSET 0x06a0 +#define AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET 0x06a4 +#define AM43XX_CONTROL_CQDETECT_STS_OFFSET 0x0e00 +#define AM43XX_CONTROL_CQDETECT_STS2_OFFSET 0x0e08 +#define AM43XX_CONTROL_VTP_CTRL_OFFSET 0x0e0c +#define AM33XX_CONTROL_VREF_CTRL_OFFSET 0x0e14 +#define AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET 0x0f90 +#define AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET 0x0f94 +#define AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET 0x0f98 +#define AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET 0x0f9c +#define AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET 0x0fa0 +#define AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET 0x0fa4 +#define AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET 0x0fa8 +#define AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET 0x0fac +#define AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET 0x0fb0 +#define AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET 0x0fb4 +#define AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET 0x0fb8 +#define AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET 0x0fbc +#define AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET 0x0fc0 +#define AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET 0x0fc4 +#define AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET 0x0fc8 +#define AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET 0x0fcc +#define AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET 0x0fd0 +#define AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET 0x0fd4 +#define AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET 0x0fd8 +#define AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET 0x0fdc +#define AM33XX_CONTROL_RESET_ISO_OFFSET 0x1000 + /* CONTROL OMAP STATUS register to identify OMAP3 features */ #define OMAP3_CONTROL_OMAP_STATUS 0x044c diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index b3f6eb5d04a2..9500b6e27380 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -32,7 +32,6 @@ #include <linux/platform_data/omapdss.h> #include "omap_hwmod.h" #include "omap_device.h" -#include "omap-pm.h" #include "common.h" #include "soc.h" @@ -126,11 +125,6 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask) omap4_dsi_mux_pads(dsi_id, 0); } -static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput) -{ - return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput); -} - static enum omapdss_version __init omap_display_get_version(void) { if (cpu_is_omap24xx()) @@ -169,7 +163,6 @@ static int __init omapdss_init_fbdev(void) static struct omap_dss_board_info board_data = { .dsi_enable_pads = omap_dsi_enable_pads, .dsi_disable_pads = omap_dsi_disable_pads, - .set_min_bus_tput = omap_dss_set_min_bus_tput, }; struct device_node *node; int r; @@ -392,7 +385,7 @@ static struct device_node * __init omapdss_find_dss_of_node(void) return NULL; } -int __init omapdss_init_of(void) +static int __init omapdss_init_of(void) { int r; struct device_node *node; @@ -422,3 +415,4 @@ int __init omapdss_init_of(void) return omapdss_init_fbdev(); } +omap_device_initcall(omapdss_init_of); diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index b064066d431c..0103548b0b15 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -18,7 +18,6 @@ #include "soc.h" #include "omap_device.h" -#include "omap-pm.h" #include "hsmmc.h" #include "control.h" diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c index 91a21c3923b2..37ff25ee3d89 100644 --- a/arch/arm/mach-omap2/i2c.c +++ b/arch/arm/mach-omap2/i2c.c @@ -22,7 +22,6 @@ #include "soc.h" #include "omap_hwmod.h" #include "omap_device.h" -#include "omap-pm.h" #include "prm.h" #include "common.h" diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index cf546dfe3b32..bb8e0bb7ef5d 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -37,7 +37,6 @@ #include "clock.h" #include "clock2xxx.h" #include "clock3xxx.h" -#include "omap-pm.h" #include "sdrc.h" #include "control.h" #include "serial.h" @@ -421,13 +420,6 @@ static void __init __maybe_unused omap_hwmod_init_postsetup(void) postsetup_state = _HWMOD_STATE_ENABLED; #endif omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state); - - omap_pm_if_early_init(); -} - -static void __init __maybe_unused omap_common_late_init(void) -{ - omap2_common_pm_late_init(); } #ifdef CONFIG_SOC_OMAP2420 @@ -450,9 +442,7 @@ void __init omap2420_init_early(void) void __init omap2420_init_late(void) { - omap_common_late_init(); - omap2_pm_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap2_pm_init; } #endif @@ -476,9 +466,7 @@ void __init omap2430_init_early(void) void __init omap2430_init_late(void) { - omap_common_late_init(); - omap2_pm_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap2_pm_init; } #endif @@ -529,43 +517,12 @@ void __init am35xx_init_early(void) void __init omap3_init_late(void) { - omap_common_late_init(); - omap3_pm_init(); - omap2_clk_enable_autoidle_all(); -} - -void __init omap3430_init_late(void) -{ - omap_common_late_init(); - omap3_pm_init(); - omap2_clk_enable_autoidle_all(); -} - -void __init omap35xx_init_late(void) -{ - omap_common_late_init(); - omap3_pm_init(); - omap2_clk_enable_autoidle_all(); -} - -void __init omap3630_init_late(void) -{ - omap_common_late_init(); - omap3_pm_init(); - omap2_clk_enable_autoidle_all(); -} - -void __init am35xx_init_late(void) -{ - omap_common_late_init(); - omap3_pm_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap3_pm_init; } void __init ti81xx_init_late(void) { - omap_common_late_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap_pm_nop_init; } #endif @@ -621,8 +578,7 @@ void __init am33xx_init_early(void) void __init am33xx_init_late(void) { - omap_common_late_init(); - amx3_common_pm_init(); + omap_pm_soc_init = amx3_common_pm_init; } #endif @@ -645,9 +601,7 @@ void __init am43xx_init_early(void) void __init am43xx_init_late(void) { - omap_common_late_init(); - omap2_clk_enable_autoidle_all(); - amx3_common_pm_init(); + omap_pm_soc_init = amx3_common_pm_init; } #endif @@ -675,9 +629,7 @@ void __init omap4430_init_early(void) void __init omap4430_init_late(void) { - omap_common_late_init(); - omap4_pm_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap4_pm_init; } #endif @@ -703,9 +655,7 @@ void __init omap5_init_early(void) void __init omap5_init_late(void) { - omap_common_late_init(); - omap4_pm_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap4_pm_init; } #endif @@ -728,9 +678,7 @@ void __init dra7xx_init_early(void) void __init dra7xx_init_late(void) { - omap_common_late_init(); - omap4_pm_init(); - omap2_clk_enable_autoidle_all(); + omap_pm_soc_init = omap4_pm_init; } #endif diff --git a/arch/arm/mach-omap2/omap-pm-noop.c b/arch/arm/mach-omap2/omap-pm-noop.c deleted file mode 100644 index 4ead077ea4e7..000000000000 --- a/arch/arm/mach-omap2/omap-pm-noop.c +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * omap-pm-noop.c - OMAP power management interface - dummy version - * - * This code implements the OMAP power management interface to - * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for - * debug/demonstration use, as it does nothing but printk() whenever a - * function is called (when DEBUG is defined, below) - * - * Copyright (C) 2008-2009 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation - * Paul Walmsley - * - * Interface developed by (in alphabetical order): - * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan - * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff - */ - -#undef DEBUG - -#include <linux/init.h> -#include <linux/cpufreq.h> -#include <linux/device.h> -#include <linux/platform_device.h> - -#include "omap_device.h" -#include "omap-pm.h" - -static bool off_mode_enabled; -static int dummy_context_loss_counter; - -/* - * Device-driver-originated constraints (via board-*.c files) - */ - -int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) -{ - if (!dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (t == -1) - pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n", - dev_name(dev)); - else - pr_debug("OMAP PM: add max MPU wakeup latency constraint: dev %s, t = %ld usec\n", - dev_name(dev), t); - - /* - * For current Linux, this needs to map the MPU to a - * powerdomain, then go through the list of current max lat - * constraints on the MPU and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) -{ - if (!dev || (agent_id != OCP_INITIATOR_AGENT && - agent_id != OCP_TARGET_AGENT)) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (r == 0) - pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n", - dev_name(dev), agent_id); - else - pr_debug("OMAP PM: add min bus tput constraint: dev %s for agent_id %d: rate %ld KiB\n", - dev_name(dev), agent_id, r); - - /* - * This code should model the interconnect and compute the - * required clock frequency, convert that to a VDD2 OPP ID, then - * set the VDD2 OPP appropriately. - * - * TI CDP code can call constraint_set here on the VDD2 OPP. - */ - - return 0; -} - -/* - * DSP Bridge-specific constraints - */ - - -/** - * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been enabled. - */ -void omap_pm_enable_off_mode(void) -{ - off_mode_enabled = true; -} - -/** - * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled - * - * Intended for use only by OMAP PM core code to notify this layer - * that off mode has been disabled. - */ -void omap_pm_disable_off_mode(void) -{ - off_mode_enabled = false; -} - -/* - * Device context loss tracking - */ - -#ifdef CONFIG_ARCH_OMAP2PLUS - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - int count; - - if (WARN_ON(!dev)) - return -ENODEV; - - if (dev->pm_domain == &omap_device_pm_domain) { - count = omap_device_get_context_loss_count(pdev); - } else { - WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device", - dev_name(dev)); - - count = dummy_context_loss_counter; - - if (off_mode_enabled) { - count++; - /* - * Context loss count has to be a non-negative value. - * Clear the sign bit to get a value range from 0 to - * INT_MAX. - */ - count &= INT_MAX; - dummy_context_loss_counter = count; - } - } - - pr_debug("OMAP PM: context loss count for dev %s = %d\n", - dev_name(dev), count); - - return count; -} - -#else - -int omap_pm_get_dev_context_loss_count(struct device *dev) -{ - return dummy_context_loss_counter; -} - -#endif - -/* Should be called before clk framework init */ -int __init omap_pm_if_early_init(void) -{ - return 0; -} - -/* Must be called after clock framework is initialized */ -int __init omap_pm_if_init(void) -{ - return 0; -} diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h deleted file mode 100644 index 5ba5df47f91b..000000000000 --- a/arch/arm/mach-omap2/omap-pm.h +++ /dev/null @@ -1,161 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * omap-pm.h - OMAP power management interface - * - * Copyright (C) 2008-2010 Texas Instruments, Inc. - * Copyright (C) 2008-2010 Nokia Corporation - * Paul Walmsley - * - * Interface developed by (in alphabetical order): Karthik Dasu, Jouni - * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa, - * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, - * Richard Woodruff - */ - -#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H -#define ASM_ARM_ARCH_OMAP_OMAP_PM_H - -#include <linux/device.h> -#include <linux/cpufreq.h> -#include <linux/clk.h> -#include <linux/pm_opp.h> - -/* - * agent_id values for use with omap_pm_set_min_bus_tput(): - * - * OCP_INITIATOR_AGENT is only valid for devices that can act as - * initiators -- it represents the device's L3 interconnect - * connection. OCP_TARGET_AGENT represents the device's L4 - * interconnect connection. - */ -#define OCP_TARGET_AGENT 1 -#define OCP_INITIATOR_AGENT 2 - -/** - * omap_pm_if_early_init - OMAP PM init code called before clock fw init - * @mpu_opp_table: array ptr to struct omap_opp for MPU - * @dsp_opp_table: array ptr to struct omap_opp for DSP - * @l3_opp_table : array ptr to struct omap_opp for CORE - * - * Initialize anything that must be configured before the clock - * framework starts. The "_if_" is to avoid name collisions with the - * PM idle-loop code. - */ -int __init omap_pm_if_early_init(void); - -/** - * omap_pm_if_init - OMAP PM init code called after clock fw init - * - * The main initialization code. OPP tables are passed in here. The - * "_if_" is to avoid name collisions with the PM idle-loop code. - */ -int __init omap_pm_if_init(void); - -/* - * Device-driver-originated constraints (via board-*.c files, platform_data) - */ - - -/** - * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency - * @dev: struct device * requesting the constraint - * @t: maximum MPU wakeup latency in microseconds - * - * Request that the maximum interrupt latency for the MPU to be no - * greater than @t microseconds. "Interrupt latency" in this case is - * defined as the elapsed time from the occurrence of a hardware or - * timer interrupt to the time when the device driver's interrupt - * service routine has been entered by the MPU. - * - * It is intended that underlying PM code will use this information to - * determine what power state to put the MPU powerdomain into, and - * possibly the CORE powerdomain as well, since interrupt handling - * code currently runs from SDRAM. Advanced PM or board*.c code may - * also configure interrupt controller priorities, OCP bus priorities, - * CPU speed(s), etc. - * - * This function will not affect device wakeup latency, e.g., time - * elapsed from when a device driver enables a hardware device with - * clk_enable(), to when the device is ready for register access or - * other use. To control this device wakeup latency, use - * omap_pm_set_max_dev_wakeup_lat() - * - * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the - * previous t value. To remove the latency target for the MPU, call - * with t = -1. - * - * XXX This constraint will be deprecated soon in favor of the more - * general omap_pm_set_max_dev_wakeup_lat() - * - * Returns -EINVAL for an invalid argument, -ERANGE if the constraint - * is not satisfiable, or 0 upon success. - */ -int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); - - -/** - * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device - * @dev: struct device * requesting the constraint - * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT) - * @r: minimum throughput (in KiB/s) - * - * Request that the minimum data throughput on the OCP interconnect - * attached to device @dev interconnect agent @tbus_id be no less - * than @r KiB/s. - * - * It is expected that the OMAP PM or bus code will use this - * information to set the interconnect clock to run at the lowest - * possible speed that satisfies all current system users. The PM or - * bus code will adjust the estimate based on its model of the bus, so - * device driver authors should attempt to specify an accurate - * quantity for their device use case, and let the PM or bus code - * overestimate the numbers as necessary to handle request/response - * latency, other competing users on the system, etc. On OMAP2/3, if - * a driver requests a minimum L4 interconnect speed constraint, the - * code will also need to add an minimum L3 interconnect speed - * constraint, - * - * Multiple calls to omap_pm_set_min_bus_tput() will replace the - * previous rate value for this device. To remove the interconnect - * throughput restriction for this device, call with r = 0. - * - * Returns -EINVAL for an invalid argument, -ERANGE if the constraint - * is not satisfiable, or 0 upon success. - */ -int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); - - -/* - * CPUFreq-originated constraint - * - * In the future, this should be handled by custom OPP clocktype - * functions. - */ - - -/* - * Device context loss tracking - */ - -/** - * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx - * @dev: struct device * - * - * This function returns the number of times that the device @dev has - * lost its internal context. This generally occurs on a powerdomain - * transition to OFF. Drivers use this as an optimization to avoid restoring - * context if the device hasn't lost it. To use, drivers should initially - * call this in their context save functions and store the result. Early in - * the driver's context restore function, the driver should call this function - * again, and compare the result to the stored counter. If they differ, the - * driver must restore device context. If the number of context losses - * exceeds the maximum positive integer, the function will wrap to 0 and - * continue counting. Returns the number of context losses for this device, - * or negative value upon error. - */ -int omap_pm_get_dev_context_loss_count(struct device *dev); - -void omap_pm_enable_off_mode(void); -void omap_pm_disable_off_mode(void); - -#endif diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 3b829a50d1db..ac219b9e6a4c 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -143,7 +143,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) struct resource res; const char *oh_name; int oh_cnt, i, ret = 0; - bool device_active = false; + bool device_active = false, skip_pm_domain = false; oh_cnt = of_property_count_strings(node, "ti,hwmods"); if (oh_cnt <= 0) { @@ -151,8 +151,15 @@ static int omap_device_build_from_dt(struct platform_device *pdev) return -ENODEV; } + /* SDMA still needs special handling for omap_device_build() */ + ret = of_property_read_string_index(node, "ti,hwmods", 0, &oh_name); + if (!ret && (!strncmp("dma_system", oh_name, 10) || + !strncmp("dma", oh_name, 3))) + skip_pm_domain = true; + /* Use ti-sysc driver instead of omap_device? */ - if (!omap_hwmod_parse_module_range(NULL, node, &res)) + if (!skip_pm_domain && + !omap_hwmod_parse_module_range(NULL, node, &res)) return -ENODEV; hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); @@ -191,11 +198,12 @@ static int omap_device_build_from_dt(struct platform_device *pdev) r->name = dev_name(&pdev->dev); } - dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain); - - if (device_active) { - omap_device_enable(pdev); - pm_runtime_set_active(&pdev->dev); + if (!skip_pm_domain) { + dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain); + if (device_active) { + omap_device_enable(pdev); + pm_runtime_set_active(&pdev->dev); + } } odbfd_exit1: diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e7d23e200ecc..2ceffd85dd3d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -481,7 +481,7 @@ static int _wait_softreset_complete(struct omap_hwmod *oh) sysc = oh->class->sysc; - if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS) + if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS && sysc->syss_offs > 0) omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs) & SYSS_RESETDONE_MASK), MAX_MODULE_SOFTRESET_WAIT, c); @@ -3171,19 +3171,19 @@ static int omap_hwmod_init_regbits(struct device *dev, */ int omap_hwmod_init_reg_offs(struct device *dev, const struct ti_sysc_module_data *data, - u32 *rev_offs, u32 *sysc_offs, u32 *syss_offs) + s32 *rev_offs, s32 *sysc_offs, s32 *syss_offs) { - *rev_offs = 0; + *rev_offs = -ENODEV; *sysc_offs = 0; *syss_offs = 0; - if (data->offsets[SYSC_REVISION] > 0) + if (data->offsets[SYSC_REVISION] >= 0) *rev_offs = data->offsets[SYSC_REVISION]; - if (data->offsets[SYSC_SYSCONFIG] > 0) + if (data->offsets[SYSC_SYSCONFIG] >= 0) *sysc_offs = data->offsets[SYSC_SYSCONFIG]; - if (data->offsets[SYSC_SYSSTATUS] > 0) + if (data->offsets[SYSC_SYSSTATUS] >= 0) *syss_offs = data->offsets[SYSC_SYSSTATUS]; return 0; @@ -3312,8 +3312,8 @@ static int omap_hwmod_check_module(struct device *dev, struct omap_hwmod *oh, const struct ti_sysc_module_data *data, struct sysc_regbits *sysc_fields, - u32 rev_offs, u32 sysc_offs, - u32 syss_offs, u32 sysc_flags, + s32 rev_offs, s32 sysc_offs, + s32 syss_offs, u32 sysc_flags, u32 idlemodes) { if (!oh->class->sysc) @@ -3365,7 +3365,7 @@ static int omap_hwmod_check_module(struct device *dev, int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, const struct ti_sysc_module_data *data, struct sysc_regbits *sysc_fields, - u32 rev_offs, u32 sysc_offs, u32 syss_offs, + s32 rev_offs, s32 sysc_offs, s32 syss_offs, u32 sysc_flags, u32 idlemodes) { struct omap_hwmod_class_sysconfig *sysc; @@ -3425,7 +3425,8 @@ int omap_hwmod_init_module(struct device *dev, { struct omap_hwmod *oh; struct sysc_regbits *sysc_fields; - u32 rev_offs, sysc_offs, syss_offs, sysc_flags, idlemodes; + s32 rev_offs, sysc_offs, syss_offs; + u32 sysc_flags, idlemodes; int error; if (!dev || !data) diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index c7122abbf977..b70cdc21f8a2 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -317,9 +317,9 @@ struct omap_hwmod_ocp_if { * then this field has to be populated with the correct offset structure. */ struct omap_hwmod_class_sysconfig { - u32 rev_offs; - u32 sysc_offs; - u32 syss_offs; + s32 rev_offs; + s32 sysc_offs; + s32 syss_offs; u16 sysc_flags; struct sysc_regbits *sysc_fields; u8 srst_udelay; diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index 5efe91c6e95b..9ded7bf972e7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -629,6 +629,7 @@ struct omap_hwmod am33xx_gpmc_hwmod = { /* 'i2c' class */ static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = { + .rev_offs = 0, .sysc_offs = 0x0010, .syss_offs = 0x0090, .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 23336b6c7125..d93f9ea4119e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -885,6 +885,7 @@ static struct omap_hwmod omap3xxx_dma_system_hwmod = { */ static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x008c, .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), @@ -990,6 +991,7 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = { /* 'mcbsp sidetone' class */ static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sidetone_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x0010, .sysc_flags = SYSC_HAS_AUTOIDLE, .sysc_fields = &omap_hwmod_sysc_type1, @@ -1018,6 +1020,7 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = { /* SR common */ static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x24, .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE), .sysc_fields = &omap34xx_sr_sysc_fields, @@ -1030,6 +1033,7 @@ static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = { }; static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x38, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c index 5f73b730d4fc..aa271ac5ebac 100644 --- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c @@ -378,6 +378,7 @@ static struct omap_hwmod am43xx_usb_otg_ss1_hwmod = { }; static struct omap_hwmod_class_sysconfig am43xx_qspi_sysc = { + .rev_offs = 0, .sysc_offs = 0x0010, .sysc_flags = SYSC_HAS_SIDLEMODE, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index e4f8ae9cd637..234ee0eec815 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1360,6 +1360,7 @@ static struct omap_hwmod omap44xx_hsi_hwmod = { */ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = { + .rev_offs = 0, .sysc_offs = 0x0010, .syss_offs = 0x0090, .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | @@ -1634,6 +1635,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = { /* The IP is not compliant to type1 / type2 scheme */ static struct omap_hwmod_class_sysconfig omap44xx_mcasp_sysc = { + .rev_offs = 0, .sysc_offs = 0x0004, .sysc_flags = SYSC_HAS_SIDLEMODE, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | @@ -1667,6 +1669,7 @@ static struct omap_hwmod omap44xx_mcasp_hwmod = { */ static struct omap_hwmod_class_sysconfig omap44xx_mcbsp_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x008c, .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), @@ -2353,6 +2356,7 @@ static struct omap_hwmod omap44xx_slimbus2_hwmod = { /* The IP is not compliant to type1 / type2 scheme */ static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x0038, .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index c72cd84b07ec..887a30fa775b 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -804,6 +804,7 @@ static struct omap_hwmod omap54xx_gpio8_hwmod = { */ static struct omap_hwmod_class_sysconfig omap54xx_i2c_sysc = { + .rev_offs = 0, .sysc_offs = 0x0010, .syss_offs = 0x0090, .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | @@ -974,6 +975,7 @@ static struct omap_hwmod omap54xx_mailbox_hwmod = { */ static struct omap_hwmod_class_sysconfig omap54xx_mcbsp_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x008c, .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), @@ -1997,6 +1999,7 @@ static struct omap_hwmod omap54xx_ocp2scp3_hwmod = { */ static struct omap_hwmod_class_sysconfig omap54xx_sata_sysc = { + .rev_offs = 0x00fc, .sysc_offs = 0x0000, .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index 62352d1e6361..a27c2fed298c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -1070,6 +1070,7 @@ static struct omap_hwmod dra7xx_hdq1w_hwmod = { */ static struct omap_hwmod_class_sysconfig dra7xx_i2c_sysc = { + .rev_offs = 0, .sysc_offs = 0x0010, .syss_offs = 0x0090, .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY | @@ -1440,6 +1441,7 @@ static struct omap_hwmod dra7xx_mcspi4_hwmod = { * */ static struct omap_hwmod_class_sysconfig dra7xx_mcasp_sysc = { + .rev_offs = 0, .sysc_offs = 0x0004, .sysc_flags = SYSC_HAS_SIDLEMODE, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), @@ -1898,6 +1900,7 @@ static struct omap_hwmod dra7xx_pciess2_hwmod = { */ static struct omap_hwmod_class_sysconfig dra7xx_qspi_sysc = { + .rev_offs = 0, .sysc_offs = 0x0010, .sysc_flags = SYSC_HAS_SIDLEMODE, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | @@ -1930,6 +1933,7 @@ static struct omap_hwmod dra7xx_qspi_hwmod = { * */ static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = { + .rev_offs = 0x0074, .sysc_offs = 0x0078, .sysc_flags = SYSC_HAS_SIDLEMODE, .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | @@ -1965,6 +1969,7 @@ static struct omap_hwmod dra7xx_rtcss_hwmod = { */ static struct omap_hwmod_class_sysconfig dra7xx_sata_sysc = { + .rev_offs = 0x00fc, .sysc_offs = 0x0000, .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | @@ -2003,6 +2008,7 @@ static struct omap_hwmod dra7xx_sata_hwmod = { /* The IP is not compliant to type1 / type2 scheme */ static struct omap_hwmod_class_sysconfig dra7xx_smartreflex_sysc = { + .rev_offs = -ENODEV, .sysc_offs = 0x0038, .sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c index 686655f884c1..8e44e2728620 100644 --- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c @@ -954,6 +954,7 @@ static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = { }; static struct omap_hwmod_class_sysconfig dm81xx_sata_sysc = { + .rev_offs = 0x00fc, .sysc_offs = 0x1100, .sysc_flags = SYSC_HAS_SIDLEMODE, .idlemodes = SIDLE_FORCE, diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 6459816c2879..7f02743edbe4 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -26,14 +26,12 @@ #include <linux/platform_data/iommu-omap.h> #include <linux/platform_data/ti-sysc.h> #include <linux/platform_data/wkup_m3.h> -#include <linux/platform_data/media/ir-rx51.h> #include <linux/platform_data/asoc-ti-mcbsp.h> #include "common.h" #include "common-board-devices.h" #include "control.h" #include "omap_device.h" -#include "omap-pm.h" #include "omap-secure.h" #include "soc.h" #include "hsmmc.h" @@ -514,18 +512,6 @@ void omap_auxdata_legacy_init(struct device *dev) dev->platform_data = &twl_gpio_auxdata; } -static struct ir_rx51_platform_data __maybe_unused rx51_ir_data = { - .set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat, -}; - -static struct platform_device __maybe_unused rx51_ir_device = { - .name = "ir_rx51", - .id = -1, - .dev = { - .platform_data = &rx51_ir_data, - }, -}; - #if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP) static struct omap_mcbsp_platform_data mcbsp_pdata; static void __init omap3_mcbsp_init(void) @@ -569,7 +555,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = { "480c9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]), OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]), OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]), - OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_ir_data), /* Only on am3517 */ OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL), OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0", diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c index 5c46ea6756d7..acb698d5780f 100644 --- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -31,7 +31,6 @@ #include "clock.h" #include "powerdomain.h" #include "clockdomain.h" -#include "omap-pm.h" #include "soc.h" #include "cm2xxx_3xxx.h" @@ -240,10 +239,6 @@ static int option_set(void *data, u64 val) *option = val; if (option == &enable_off_mode) { - if (val) - omap_pm_enable_off_mode(); - else - omap_pm_disable_off_mode(); if (cpu_is_omap34xx()) omap3_pm_off_mode_enable(val); } diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 6f68576e5695..ca03af8fe43f 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -16,11 +16,11 @@ #include <linux/pm_opp.h> #include <linux/export.h> #include <linux/suspend.h> +#include <linux/clk.h> #include <linux/cpu.h> #include <asm/system_misc.h> -#include "omap-pm.h" #include "omap_device.h" #include "common.h" @@ -230,16 +230,20 @@ static void __init omap4_init_voltages(void) omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva"); } -static int __init omap2_common_pm_init(void) +int __maybe_unused omap_pm_nop_init(void) { - omap_pm_if_init(); - return 0; } -omap_postcore_initcall(omap2_common_pm_init); + +int (*omap_pm_soc_init)(void); int __init omap2_common_pm_late_init(void) { + int error; + + if (!omap_pm_soc_init) + return 0; + /* Init the voltage layer */ omap3_twl_init(); omap4_twl_init(); @@ -252,5 +256,12 @@ int __init omap2_common_pm_late_init(void) /* Smartreflex device init */ omap_devinit_smartreflex(); + error = omap_pm_soc_init(); + if (error) + pr_warn("%s: pm soc init failed: %i\n", __func__, error); + + omap2_clk_enable_autoidle_all(); + return 0; } +omap_late_initcall(omap2_common_pm_late_init); diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c index 93c0b5ba9f09..9b3755a2e2ec 100644 --- a/arch/arm/mach-omap2/pm33xx-core.c +++ b/arch/arm/mach-omap2/pm33xx-core.c @@ -173,7 +173,7 @@ static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void) return NULL; } -void __init amx3_common_pm_init(void) +int __init amx3_common_pm_init(void) { struct am33xx_pm_platform_data *pdata; struct platform_device_info devinfo; @@ -186,4 +186,6 @@ void __init amx3_common_pm_init(void) devinfo.size_data = sizeof(*pdata); devinfo.id = -1; platform_device_register_full(&devinfo); + + return 0; } diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index b3870220612e..78e1ace7d17d 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -131,6 +131,19 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) return 0; } + /* + * Bootloader or kexec boot may have LOGICRETSTATE cleared + * for some domains. This is the case when kexec booting from + * Android kernels that support off mode for example. + * Make sure it's set at least for core and per, otherwise + * we currently will see lost GPIO interrupts for wlcore and + * smsc911x at least if per hits retention during idle. + */ + if (!strncmp(pwrdm->name, "core", 4) || + !strncmp(pwrdm->name, "l4per", 5) || + !strncmp(pwrdm->name, "wkup", 4)) + pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_RET); + pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC); if (!pwrst) return -ENOMEM; diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 76eb6ec5f157..27fdef624e97 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -14,6 +14,7 @@ */ #undef DEBUG +#include <linux/cpu_pm.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/list.h> @@ -39,6 +40,9 @@ #define PWRDM_TRACE_STATES_FLAG (1<<31) +void pwrdms_save_context(void); +void pwrdms_restore_context(void); + enum { PWRDM_STATE_NOW = 0, PWRDM_STATE_PREV, @@ -333,6 +337,22 @@ int pwrdm_register_pwrdms(struct powerdomain **ps) return 0; } +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (enable_off_mode) + pwrdms_save_context(); + break; + case CPU_CLUSTER_PM_EXIT: + if (enable_off_mode) + pwrdms_restore_context(); + break; + } + + return NOTIFY_OK; +} + /** * pwrdm_complete_init - set up the powerdomain layer * @@ -347,6 +367,7 @@ int pwrdm_register_pwrdms(struct powerdomain **ps) int pwrdm_complete_init(void) { struct powerdomain *temp_p; + static struct notifier_block nb; if (list_empty(&pwrdm_list)) return -EACCES; @@ -354,6 +375,12 @@ int pwrdm_complete_init(void) list_for_each_entry(temp_p, &pwrdm_list, node) pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON); + /* Only AM43XX can lose pwrdm context during rtc-ddr suspend */ + if (soc_is_am43xx()) { + nb.notifier_call = cpu_notifier; + cpu_pm_register_notifier(&nb); + } + return 0; } @@ -1199,3 +1226,63 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) return 0; } + +/** + * pwrdm_save_context - save powerdomain registers + * + * Register state is going to be lost due to a suspend or hibernate + * event. Save the powerdomain registers. + */ +static int pwrdm_save_context(struct powerdomain *pwrdm, void *unused) +{ + if (arch_pwrdm && arch_pwrdm->pwrdm_save_context) + arch_pwrdm->pwrdm_save_context(pwrdm); + return 0; +} + +/** + * pwrdm_save_context - restore powerdomain registers + * + * Restore powerdomain control registers after a suspend or resume + * event. + */ +static int pwrdm_restore_context(struct powerdomain *pwrdm, void *unused) +{ + if (arch_pwrdm && arch_pwrdm->pwrdm_restore_context) + arch_pwrdm->pwrdm_restore_context(pwrdm); + return 0; +} + +static int pwrdm_lost_power(struct powerdomain *pwrdm, void *unused) +{ + int state; + + /* + * Power has been lost across all powerdomains, increment the + * counter. + */ + + state = pwrdm_read_pwrst(pwrdm); + if (state != PWRDM_POWER_OFF) { + pwrdm->state_counter[state]++; + pwrdm->state_counter[PWRDM_POWER_OFF]++; + } + pwrdm->state = state; + + return 0; +} + +void pwrdms_save_context(void) +{ + pwrdm_for_each(pwrdm_save_context, NULL); +} + +void pwrdms_restore_context(void) +{ + pwrdm_for_each(pwrdm_restore_context, NULL); +} + +void pwrdms_lost_power(void) +{ + pwrdm_for_each(pwrdm_lost_power, NULL); +} diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 28a796ce07d7..9a907fb14044 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -144,6 +144,7 @@ struct powerdomain { s64 timer; s64 state_timer[PWRDM_MAX_PWRSTS]; #endif + u32 context; }; /** @@ -198,6 +199,8 @@ struct pwrdm_ops { int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm); int (*pwrdm_wait_transition)(struct powerdomain *pwrdm); int (*pwrdm_has_voltdm)(void); + void (*pwrdm_save_context)(struct powerdomain *pwrdm); + void (*pwrdm_restore_context)(struct powerdomain *pwrdm); }; int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs); @@ -273,4 +276,8 @@ extern struct powerdomain gfx_omap2_pwrdm; extern void pwrdm_lock(struct powerdomain *pwrdm); extern void pwrdm_unlock(struct powerdomain *pwrdm); +extern void pwrdms_save_context(void); +extern void pwrdms_restore_context(void); + +extern void pwrdms_lost_power(void); #endif diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c index ebaf80d72a10..d5141669c28d 100644 --- a/arch/arm/mach-omap2/prm33xx.c +++ b/arch/arm/mach-omap2/prm33xx.c @@ -342,6 +342,35 @@ static void am33xx_prm_global_warm_sw_reset(void) AM33XX_PRM_RSTCTRL_OFFSET); } +static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm) +{ + pwrdm->context = am33xx_prm_read_reg(pwrdm->prcm_offs, + pwrdm->pwrstctrl_offs); + /* + * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request, + * reading back a 1 indicates a request in progress. + */ + pwrdm->context &= ~AM33XX_LOWPOWERSTATECHANGE_MASK; +} + +static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm) +{ + int st, ctrl; + + st = am33xx_prm_read_reg(pwrdm->prcm_offs, + pwrdm->pwrstst_offs); + + am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs, + pwrdm->pwrstctrl_offs); + + /* Make sure we only wait for a transition if there is one */ + st &= OMAP_POWERSTATEST_MASK; + ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context; + + if (st != ctrl) + am33xx_pwrdm_wait_transition(pwrdm); +} + struct pwrdm_ops am33xx_pwrdm_operations = { .pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst, .pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst, @@ -357,6 +386,8 @@ struct pwrdm_ops am33xx_pwrdm_operations = { .pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst, .pwrdm_wait_transition = am33xx_pwrdm_wait_transition, .pwrdm_has_voltdm = am33xx_check_vcvp, + .pwrdm_save_context = am33xx_pwrdm_save_context, + .pwrdm_restore_context = am33xx_pwrdm_restore_context, }; static struct prm_ll_data am33xx_prm_ll_data = { diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index acb95936dfe7..7b95729e8359 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ +#include <linux/cpu_pm.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/errno.h> @@ -30,6 +31,7 @@ #include "prcm44xx.h" #include "prminst44xx.h" #include "powerdomain.h" +#include "pm.h" /* Static data */ @@ -57,6 +59,13 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = { .reconfigure_io_chain = &omap44xx_prm_reconfigure_io_chain, }; +struct omap_prm_irq_context { + unsigned long irq_enable; + unsigned long pm_ctrl; +}; + +static struct omap_prm_irq_context omap_prm_context; + /* * omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST * hardware register (which are specific to OMAP44xx SoCs) to reset @@ -667,6 +676,54 @@ static int omap4_check_vcvp(void) return 0; } +/** + * omap4_pwrdm_save_context - Saves the powerdomain state + * @pwrdm: pointer to individual powerdomain + * + * The function saves the powerdomain state control information. + * This is needed in rtc+ddr modes where we lose powerdomain context. + */ +static void omap4_pwrdm_save_context(struct powerdomain *pwrdm) +{ + pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, + pwrdm->prcm_offs, + pwrdm->pwrstctrl_offs); + + /* + * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request, + * reading back a 1 indicates a request in progress. + */ + pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK; +} + +/** + * omap4_pwrdm_restore_context - Restores the powerdomain state + * @pwrdm: pointer to individual powerdomain + * + * The function restores the powerdomain state control information. + * This is needed in rtc+ddr modes where we lose powerdomain context. + */ +static void omap4_pwrdm_restore_context(struct powerdomain *pwrdm) +{ + int st, ctrl; + + st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition, + pwrdm->prcm_offs, + pwrdm->pwrstctrl_offs); + + omap4_prminst_write_inst_reg(pwrdm->context, + pwrdm->prcm_partition, + pwrdm->prcm_offs, + pwrdm->pwrstctrl_offs); + + /* Make sure we only wait for a transition if there is one */ + st &= OMAP_POWERSTATEST_MASK; + ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context; + + if (st != ctrl) + omap4_pwrdm_wait_transition(pwrdm); +} + struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst, .pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst, @@ -685,10 +742,50 @@ struct pwrdm_ops omap4_pwrdm_operations = { .pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst, .pwrdm_wait_transition = omap4_pwrdm_wait_transition, .pwrdm_has_voltdm = omap4_check_vcvp, + .pwrdm_save_context = omap4_pwrdm_save_context, + .pwrdm_restore_context = omap4_pwrdm_restore_context, }; static int omap44xx_prm_late_init(void); +void prm_save_context(void) +{ + omap_prm_context.irq_enable = + omap4_prm_read_inst_reg(AM43XX_PRM_OCP_SOCKET_INST, + omap4_prcm_irq_setup.mask); + + omap_prm_context.pm_ctrl = + omap4_prm_read_inst_reg(AM43XX_PRM_DEVICE_INST, + omap4_prcm_irq_setup.pm_ctrl); +} + +void prm_restore_context(void) +{ + omap4_prm_write_inst_reg(omap_prm_context.irq_enable, + OMAP4430_PRM_OCP_SOCKET_INST, + omap4_prcm_irq_setup.mask); + + omap4_prm_write_inst_reg(omap_prm_context.pm_ctrl, + AM43XX_PRM_DEVICE_INST, + omap4_prcm_irq_setup.pm_ctrl); +} + +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + if (enable_off_mode) + prm_save_context(); + break; + case CPU_CLUSTER_PM_EXIT: + if (enable_off_mode) + prm_restore_context(); + break; + } + + return NOTIFY_OK; +} + /* * XXX document */ @@ -709,6 +806,7 @@ static const struct omap_prcm_init_data *prm_init_data; int __init omap44xx_prm_init(const struct omap_prcm_init_data *data) { + static struct notifier_block nb; omap_prm_base_init(); prm_init_data = data; @@ -730,6 +828,12 @@ int __init omap44xx_prm_init(const struct omap_prcm_init_data *data) omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET; } + /* Only AM43XX can lose prm context during rtc-ddr suspend */ + if (soc_is_am43xx()) { + nb.notifier_call = cpu_notifier; + cpu_pm_register_notifier(&nb); + } + return prm_register(&omap44xx_prm_ll_data); } diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 4fb4dc24e5e9..98ed5ac073bc 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -50,7 +50,6 @@ #include "omap_device.h" #include <plat/counter-32k.h> #include <clocksource/timer-ti-dm.h> -#include "omap-pm.h" #include "soc.h" #include "common.h" @@ -71,6 +70,9 @@ static struct clock_event_device clockevent_gpt; /* Clockevent hwmod for am335x and am437x suspend */ static struct omap_hwmod *clockevent_gpt_hwmod; +/* Clockesource hwmod for am437x suspend */ +static struct omap_hwmod *clocksource_gpt_hwmod; + #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER static unsigned long arch_timer_freq; @@ -168,6 +170,43 @@ static const struct of_device_id omap_timer_match[] __initconst = { { } }; +static int omap_timer_add_disabled_property(struct device_node *np) +{ + struct property *prop; + + prop = kzalloc(sizeof(*prop), GFP_KERNEL); + if (!prop) + return -ENOMEM; + + prop->name = "status"; + prop->value = "disabled"; + prop->length = strlen(prop->value); + + return of_add_property(np, prop); +} + +static int omap_timer_update_dt(struct device_node *np) +{ + int error = 0; + + if (!of_device_is_compatible(np, "ti,omap-counter32k")) { + error = omap_timer_add_disabled_property(np); + if (error) + return error; + } + + /* No parent interconnect target module configured? */ + if (of_get_property(np, "ti,hwmods", NULL)) + return error; + + /* Tag parent interconnect target module disabled */ + error = omap_timer_add_disabled_property(np->parent); + if (error) + return error; + + return 0; +} + /** * omap_get_timer_dt - get a timer using device-tree * @match - device-tree match structure for matching a device type @@ -183,6 +222,7 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id * const char *property) { struct device_node *np; + int error; for_each_matching_node(np, match) { if (!of_device_is_available(np)) @@ -197,17 +237,9 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id * of_get_property(np, "ti,timer-secure", NULL))) continue; - if (!of_device_is_compatible(np, "ti,omap-counter32k")) { - struct property *prop; + error = omap_timer_update_dt(np); + WARN(error, "%s: Could not update dt: %i\n", __func__, error); - prop = kzalloc(sizeof(*prop), GFP_KERNEL); - if (!prop) - return NULL; - prop->name = "status"; - prop->value = "disabled"; - prop->length = strlen(prop->value); - of_add_property(np, prop); - } return np; } @@ -266,8 +298,12 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, return -ENODEV; of_property_read_string_index(np, "ti,hwmods", 0, &oh_name); - if (!oh_name) - return -ENODEV; + if (!oh_name) { + of_property_read_string_index(np->parent, "ti,hwmods", 0, + &oh_name); + if (!oh_name) + return -ENODEV; + } timer->irq = irq_of_parse_and_map(np, 0); if (!timer->irq) @@ -419,9 +455,12 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void) if (!np) return -ENODEV; - of_property_read_string_index(np, "ti,hwmods", 0, &oh_name); - if (!oh_name) - return -ENODEV; + of_property_read_string_index(np->parent, "ti,hwmods", 0, &oh_name); + if (!oh_name) { + of_property_read_string_index(np, "ti,hwmods", 0, &oh_name); + if (!oh_name) + return -ENODEV; + } /* * First check hwmod data is available for sync32k counter @@ -442,6 +481,26 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void) return ret; } +static unsigned int omap2_gptimer_clksrc_load; + +static void omap2_gptimer_clksrc_suspend(struct clocksource *unused) +{ + omap2_gptimer_clksrc_load = + __omap_dm_timer_read_counter(&clksrc, OMAP_TIMER_NONPOSTED); + + omap_hwmod_idle(clocksource_gpt_hwmod); +} + +static void omap2_gptimer_clksrc_resume(struct clocksource *unused) +{ + omap_hwmod_enable(clocksource_gpt_hwmod); + + __omap_dm_timer_load_start(&clksrc, + OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, + omap2_gptimer_clksrc_load, + OMAP_TIMER_NONPOSTED); +} + static void __init omap2_gptimer_clocksource_init(int gptimer_id, const char *fck_source, const char *property) @@ -454,6 +513,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id, res = omap_dm_timer_init_one(&clksrc, fck_source, property, &clocksource_gpt.name, OMAP_TIMER_NONPOSTED); + + if (soc_is_am43xx()) { + clocksource_gpt.suspend = omap2_gptimer_clksrc_suspend; + clocksource_gpt.resume = omap2_gptimer_clksrc_resume; + + clocksource_gpt_hwmod = + omap_hwmod_lookup(clocksource_gpt.name); + } + BUG_ON(res); __omap_dm_timer_load_start(&clksrc, diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 4b8a0df8ea57..8c64f93b669b 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -446,6 +446,10 @@ static int __init pxa3xx_init(void) pxa3xx_init_pm(); + enable_irq_wake(IRQ_WAKEUP0); + if (cpu_is_pxa320()) + enable_irq_wake(IRQ_WAKEUP1); + register_syscore_ops(&pxa_irq_syscore_ops); register_syscore_ops(&pxa3xx_mfp_syscore_ops); diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index df62bb23dbee..bbea5fa9a140 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -27,11 +27,11 @@ #include <linux/platform_data/i2c-pxa.h> #include <linux/platform_data/pcf857x.h> -#include <linux/platform_data/at24.h> #include <linux/smc91x.h> #include <linux/gpio/machine.h> #include <linux/gpio.h> #include <linux/leds.h> +#include <linux/property.h> #include <asm/types.h> #include <asm/setup.h> @@ -795,9 +795,9 @@ static struct pcf857x_platform_data platform_data_pcf857x = { .context = NULL, }; -static struct at24_platform_data pca9500_eeprom_pdata = { - .byte_len = 256, - .page_size = 4, +static const struct property_entry pca9500_eeprom_properties[] = { + PROPERTY_ENTRY_U32("pagesize", 4), + { } }; /** @@ -935,7 +935,7 @@ static struct i2c_board_info __initdata stargate2_i2c_board_info[] = { }, { .type = "24c02", .addr = 0x57, - .platform_data = &pca9500_eeprom_pdata, + .properties = pca9500_eeprom_properties, }, { .type = "max1238", .addr = 0x35, diff --git a/arch/arm/mach-s3c24xx/h1940-bluetooth.c b/arch/arm/mach-s3c24xx/h1940-bluetooth.c index 46ad20ea87d1..186b5321658e 100644 --- a/arch/arm/mach-s3c24xx/h1940-bluetooth.c +++ b/arch/arm/mach-s3c24xx/h1940-bluetooth.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-1.0 +// SPDX-License-Identifier: GPL-1.0+ // // Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org> // diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c index 95753e0bc073..f9fc1f8d2b28 100644 --- a/arch/arm/mach-s3c24xx/mach-mini2440.c +++ b/arch/arm/mach-s3c24xx/mach-mini2440.c @@ -20,7 +20,7 @@ #include <linux/serial_core.h> #include <linux/serial_s3c.h> #include <linux/dm9000.h> -#include <linux/platform_data/at24.h> +#include <linux/property.h> #include <linux/platform_device.h> #include <linux/gpio_keys.h> #include <linux/i2c.h> @@ -481,15 +481,15 @@ static struct platform_device mini2440_audio = { /* * I2C devices */ -static struct at24_platform_data at24c08 = { - .byte_len = SZ_8K / 8, - .page_size = 16, +static const struct property_entry mini2440_at24_properties[] = { + PROPERTY_ENTRY_U32("pagesize", 16), + { } }; static struct i2c_board_info mini2440_i2c_devs[] __initdata = { { I2C_BOARD_INFO("24c08", 0x50), - .platform_data = &at24c08, + .properties = mini2440_at24_properties, }, }; diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 280e7312a9e1..fcc273f127bf 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -75,6 +75,10 @@ config ARCH_R8A7745 bool "RZ/G1E (R8A77450)" select ARCH_RCAR_GEN2 +config ARCH_R8A77470 + bool "RZ/G1C (R8A77470)" + select ARCH_RCAR_GEN2 + config ARCH_R8A7778 bool "R-Car M1A (R8A77781)" select ARCH_RCAR_GEN1 @@ -110,6 +114,15 @@ config ARCH_R8A7794 bool "R-Car E2 (R8A77940)" select ARCH_RCAR_GEN2 +config ARCH_R9A06G032 + bool "RZ/N1D (R9A06G032)" + select ARCH_RZN1 + +config ARCH_RZN1 + bool "RZ/N1 (R9A06G0xx) Family" + select ARM_AMBA + select CPU_V7 + config ARCH_SH73A0 bool "SH-Mobile AG5 (R8A73A00)" select ARCH_RMOBILE diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h index 43c1ac696274..2109f123bdfb 100644 --- a/arch/arm/mach-shmobile/common.h +++ b/arch/arm/mach-shmobile/common.h @@ -2,7 +2,6 @@ #ifndef __ARCH_MACH_COMMON_H #define __ARCH_MACH_COMMON_H -extern void shmobile_init_cntvoff(void); extern void shmobile_init_delay(void); extern void shmobile_boot_vector(void); extern unsigned long shmobile_boot_fn; diff --git a/arch/arm/mach-shmobile/headsmp-apmu.S b/arch/arm/mach-shmobile/headsmp-apmu.S index 5672b5849401..d49ab194766a 100644 --- a/arch/arm/mach-shmobile/headsmp-apmu.S +++ b/arch/arm/mach-shmobile/headsmp-apmu.S @@ -11,29 +11,9 @@ #include <linux/linkage.h> #include <asm/assembler.h> -ENTRY(shmobile_init_cntvoff) - /* - * CNTVOFF has to be initialized either from non-secure Hypervisor - * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled - * then it should be handled by the secure code - */ - cps #MON_MODE - mrc p15, 0, r1, c1, c1, 0 /* Get Secure Config */ - orr r0, r1, #1 - mcr p15, 0, r0, c1, c1, 0 /* Set Non Secure bit */ - instr_sync - mov r0, #0 - mcrr p15, 4, r0, r0, c14 /* CNTVOFF = 0 */ - instr_sync - mcr p15, 0, r1, c1, c1, 0 /* Set Secure bit */ - instr_sync - cps #SVC_MODE - ret lr -ENDPROC(shmobile_init_cntvoff) - #ifdef CONFIG_SMP ENTRY(shmobile_boot_apmu) - bl shmobile_init_cntvoff + bl secure_cntvoff_init b secondary_startup ENDPROC(shmobile_boot_apmu) #endif diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 5561dbed7a33..88fdc1801d90 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -26,6 +26,7 @@ #include <linux/of_fdt.h> #include <linux/of_platform.h> #include <asm/mach/arch.h> +#include <asm/secure_cntvoff.h> #include "common.h" #include "rcar-gen2.h" @@ -70,9 +71,10 @@ void __init rcar_gen2_timer_init(void) void __iomem *base; u32 freq; - shmobile_init_cntvoff(); + secure_cntvoff_init(); if (of_machine_is_compatible("renesas,r8a7745") || + of_machine_is_compatible("renesas,r8a77470") || of_machine_is_compatible("renesas,r8a7792") || of_machine_is_compatible("renesas,r8a7794")) { freq = 260000000 / 8; /* ZS / 8 */ @@ -205,6 +207,7 @@ MACHINE_END static const char * const rz_g1_boards_compat_dt[] __initconst = { "renesas,r8a7743", "renesas,r8a7745", + "renesas,r8a77470", NULL, }; diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index ce53ceaf4cc5..d9c8ecf88ec6 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -51,7 +51,7 @@ config MACH_SUN9I config ARCH_SUNXI_MC_SMP bool depends on SMP - default MACH_SUN9I + default MACH_SUN9I || MACH_SUN8I select ARM_CCI400_PORT_CTRL select ARM_CPU_SUSPEND diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile index 7de9cc286d53..71429aa85143 100644 --- a/arch/arm/mach-sunxi/Makefile +++ b/arch/arm/mach-sunxi/Makefile @@ -1,5 +1,5 @@ CFLAGS_mc_smp.o += -march=armv7-a obj-$(CONFIG_ARCH_SUNXI) += sunxi.o -obj-$(CONFIG_ARCH_SUNXI_MC_SMP) += mc_smp.o +obj-$(CONFIG_ARCH_SUNXI_MC_SMP) += mc_smp.o headsmp.o obj-$(CONFIG_SMP) += platsmp.o diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S new file mode 100644 index 000000000000..32d76be98541 --- /dev/null +++ b/arch/arm/mach-sunxi/headsmp.S @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2018 Chen-Yu Tsai + * Copyright (c) 2018 Bootlin + * + * Chen-Yu Tsai <wens@csie.org> + * Mylène Josserand <mylene.josserand@bootlin.com> + * + * SMP support for sunxi based systems with Cortex A7/A15 + * + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/cputype.h> + +ENTRY(sunxi_mc_smp_cluster_cache_enable) + .arch armv7-a + /* + * Enable cluster-level coherency, in preparation for turning on the MMU. + * + * Also enable regional clock gating and L2 data latency settings for + * Cortex-A15. These settings are from the vendor kernel. + */ + mrc p15, 0, r1, c0, c0, 0 + movw r2, #(ARM_CPU_PART_MASK & 0xffff) + movt r2, #(ARM_CPU_PART_MASK >> 16) + and r1, r1, r2 + movw r2, #(ARM_CPU_PART_CORTEX_A15 & 0xffff) + movt r2, #(ARM_CPU_PART_CORTEX_A15 >> 16) + cmp r1, r2 + bne not_a15 + + /* The following is Cortex-A15 specific */ + + /* ACTLR2: Enable CPU regional clock gates */ + mrc p15, 1, r1, c15, c0, 4 + orr r1, r1, #(0x1 << 31) + mcr p15, 1, r1, c15, c0, 4 + + /* L2ACTLR */ + mrc p15, 1, r1, c15, c0, 0 + /* Enable L2, GIC, and Timer regional clock gates */ + orr r1, r1, #(0x1 << 26) + /* Disable clean/evict from being pushed to external */ + orr r1, r1, #(0x1<<3) + mcr p15, 1, r1, c15, c0, 0 + + /* L2CTRL: L2 data RAM latency */ + mrc p15, 1, r1, c9, c0, 2 + bic r1, r1, #(0x7 << 0) + orr r1, r1, #(0x3 << 0) + mcr p15, 1, r1, c9, c0, 2 + + /* End of Cortex-A15 specific setup */ + not_a15: + + /* Get value of sunxi_mc_smp_first_comer */ + adr r1, first + ldr r0, [r1] + ldr r0, [r1, r0] + + /* Skip cci_enable_port_for_self if not first comer */ + cmp r0, #0 + bxeq lr + b cci_enable_port_for_self + + .align 2 + first: .word sunxi_mc_smp_first_comer - . +ENDPROC(sunxi_mc_smp_cluster_cache_enable) + +ENTRY(sunxi_mc_smp_secondary_startup) + bl sunxi_mc_smp_cluster_cache_enable + bl secure_cntvoff_init + b secondary_startup +ENDPROC(sunxi_mc_smp_secondary_startup) + +ENTRY(sunxi_mc_smp_resume) + bl sunxi_mc_smp_cluster_cache_enable + b cpu_resume +ENDPROC(sunxi_mc_smp_resume) diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c index c0246ec54a0a..b4037b603897 100644 --- a/arch/arm/mach-sunxi/mc_smp.c +++ b/arch/arm/mach-sunxi/mc_smp.c @@ -55,22 +55,35 @@ #define CPUCFG_CX_RST_CTRL_L2_RST BIT(8) #define CPUCFG_CX_RST_CTRL_CX_RST(n) BIT(4 + (n)) #define CPUCFG_CX_RST_CTRL_CORE_RST(n) BIT(n) +#define CPUCFG_CX_RST_CTRL_CORE_RST_ALL (0xf << 0) #define PRCM_CPU_PO_RST_CTRL(c) (0x4 + 0x4 * (c)) #define PRCM_CPU_PO_RST_CTRL_CORE(n) BIT(n) #define PRCM_CPU_PO_RST_CTRL_CORE_ALL 0xf #define PRCM_PWROFF_GATING_REG(c) (0x100 + 0x4 * (c)) -#define PRCM_PWROFF_GATING_REG_CLUSTER BIT(4) +/* The power off register for clusters are different from a80 and a83t */ +#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I BIT(0) +#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I BIT(4) #define PRCM_PWROFF_GATING_REG_CORE(n) BIT(n) #define PRCM_PWR_SWITCH_REG(c, cpu) (0x140 + 0x10 * (c) + 0x4 * (cpu)) #define PRCM_CPU_SOFT_ENTRY_REG 0x164 +/* R_CPUCFG registers, specific to sun8i-a83t */ +#define R_CPUCFG_CLUSTER_PO_RST_CTRL(c) (0x30 + (c) * 0x4) +#define R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(n) BIT(n) +#define R_CPUCFG_CPU_SOFT_ENTRY_REG 0x01a4 + #define CPU0_SUPPORT_HOTPLUG_MAGIC0 0xFA50392F #define CPU0_SUPPORT_HOTPLUG_MAGIC1 0x790DCA3A static void __iomem *cpucfg_base; static void __iomem *prcm_base; static void __iomem *sram_b_smp_base; +static void __iomem *r_cpucfg_base; + +extern void sunxi_mc_smp_secondary_startup(void); +extern void sunxi_mc_smp_resume(void); +static bool is_a83t; static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster) { @@ -157,6 +170,16 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster) reg &= ~PRCM_CPU_PO_RST_CTRL_CORE(cpu); writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); + if (is_a83t) { + /* assert cpu power-on reset */ + reg = readl(r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + reg &= ~(R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu)); + writel(reg, r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + udelay(10); + } + /* Cortex-A7: hold L1 reset disable signal low */ if (!sunxi_core_is_cortex_a15(cpu, cluster)) { reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster)); @@ -180,17 +203,38 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster) /* open power switch */ sunxi_cpu_power_switch_set(cpu, cluster, true); + /* Handle A83T bit swap */ + if (is_a83t) { + if (cpu == 0) + cpu = 4; + } + /* clear processor power gate */ reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); reg &= ~PRCM_PWROFF_GATING_REG_CORE(cpu); writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); udelay(20); + /* Handle A83T bit swap */ + if (is_a83t) { + if (cpu == 4) + cpu = 0; + } + /* de-assert processor power-on reset */ reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); reg |= PRCM_CPU_PO_RST_CTRL_CORE(cpu); writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); + if (is_a83t) { + reg = readl(r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + reg |= R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu); + writel(reg, r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + udelay(10); + } + /* de-assert all processor resets */ reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); reg |= CPUCFG_CX_RST_CTRL_DBG_RST(cpu); @@ -212,6 +256,14 @@ static int sunxi_cluster_powerup(unsigned int cluster) if (cluster >= SUNXI_NR_CLUSTERS) return -EINVAL; + /* For A83T, assert cluster cores resets */ + if (is_a83t) { + reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); + reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; /* Core Reset */ + writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); + udelay(10); + } + /* assert ACINACTM */ reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster)); reg |= CPUCFG_CX_CTRL_REG1_ACINACTM; @@ -222,6 +274,16 @@ static int sunxi_cluster_powerup(unsigned int cluster) reg &= ~PRCM_CPU_PO_RST_CTRL_CORE_ALL; writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster)); + /* assert cluster cores resets */ + if (is_a83t) { + reg = readl(r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; + writel(reg, r_cpucfg_base + + R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster)); + udelay(10); + } + /* assert cluster resets */ reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster)); reg &= ~CPUCFG_CX_RST_CTRL_DBG_SOC_RST; @@ -252,7 +314,10 @@ static int sunxi_cluster_powerup(unsigned int cluster) /* clear cluster power gate */ reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); - reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER; + if (is_a83t) + reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I; + else + reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I; writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); udelay(20); @@ -300,74 +365,7 @@ static void sunxi_cluster_cache_disable_without_axi(void) } static int sunxi_mc_smp_cpu_table[SUNXI_NR_CLUSTERS][SUNXI_CPUS_PER_CLUSTER]; -static int sunxi_mc_smp_first_comer; - -/* - * Enable cluster-level coherency, in preparation for turning on the MMU. - * - * Also enable regional clock gating and L2 data latency settings for - * Cortex-A15. These settings are from the vendor kernel. - */ -static void __naked sunxi_mc_smp_cluster_cache_enable(void) -{ - asm volatile ( - "mrc p15, 0, r1, c0, c0, 0\n" - "movw r2, #" __stringify(ARM_CPU_PART_MASK & 0xffff) "\n" - "movt r2, #" __stringify(ARM_CPU_PART_MASK >> 16) "\n" - "and r1, r1, r2\n" - "movw r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 & 0xffff) "\n" - "movt r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 >> 16) "\n" - "cmp r1, r2\n" - "bne not_a15\n" - - /* The following is Cortex-A15 specific */ - - /* ACTLR2: Enable CPU regional clock gates */ - "mrc p15, 1, r1, c15, c0, 4\n" - "orr r1, r1, #(0x1<<31)\n" - "mcr p15, 1, r1, c15, c0, 4\n" - - /* L2ACTLR */ - "mrc p15, 1, r1, c15, c0, 0\n" - /* Enable L2, GIC, and Timer regional clock gates */ - "orr r1, r1, #(0x1<<26)\n" - /* Disable clean/evict from being pushed to external */ - "orr r1, r1, #(0x1<<3)\n" - "mcr p15, 1, r1, c15, c0, 0\n" - - /* L2CTRL: L2 data RAM latency */ - "mrc p15, 1, r1, c9, c0, 2\n" - "bic r1, r1, #(0x7<<0)\n" - "orr r1, r1, #(0x3<<0)\n" - "mcr p15, 1, r1, c9, c0, 2\n" - - /* End of Cortex-A15 specific setup */ - "not_a15:\n" - - /* Get value of sunxi_mc_smp_first_comer */ - "adr r1, first\n" - "ldr r0, [r1]\n" - "ldr r0, [r1, r0]\n" - - /* Skip cci_enable_port_for_self if not first comer */ - "cmp r0, #0\n" - "bxeq lr\n" - "b cci_enable_port_for_self\n" - - ".align 2\n" - "first: .word sunxi_mc_smp_first_comer - .\n" - ); -} - -static void __naked sunxi_mc_smp_secondary_startup(void) -{ - asm volatile( - "bl sunxi_mc_smp_cluster_cache_enable\n" - "b secondary_startup" - /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */ - :: "i" (sunxi_mc_smp_cluster_cache_enable) - ); -} +int sunxi_mc_smp_first_comer; static DEFINE_SPINLOCK(boot_lock); @@ -516,7 +514,10 @@ static int sunxi_cluster_powerdown(unsigned int cluster) /* gate cluster power */ pr_debug("%s: gate cluster power\n", __func__); reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster)); - reg |= PRCM_PWROFF_GATING_REG_CLUSTER; + if (is_a83t) + reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I; + else + reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I; writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster)); udelay(20); @@ -598,8 +599,12 @@ out: return !ret; } -static bool sunxi_mc_smp_cpu_can_disable(unsigned int __unused) +static bool sunxi_mc_smp_cpu_can_disable(unsigned int cpu) { + /* CPU0 hotplug not handled for sun8i-a83t */ + if (is_a83t) + if (cpu == 0) + return false; return true; } #endif @@ -637,16 +642,6 @@ static bool __init sunxi_mc_smp_cpu_table_init(void) */ typedef typeof(cpu_reset) phys_reset_t; -static void __init __naked sunxi_mc_smp_resume(void) -{ - asm volatile( - "bl sunxi_mc_smp_cluster_cache_enable\n" - "b cpu_resume" - /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */ - :: "i" (sunxi_mc_smp_cluster_cache_enable) - ); -} - static int __init nocache_trampoline(unsigned long __unused) { phys_reset_t phys_reset; @@ -692,12 +687,14 @@ struct sunxi_mc_smp_nodes { struct device_node *prcm_node; struct device_node *cpucfg_node; struct device_node *sram_node; + struct device_node *r_cpucfg_node; }; /* This structure holds SoC-specific bits tied to an enable-method string. */ struct sunxi_mc_smp_data { const char *enable_method; int (*get_smp_nodes)(struct sunxi_mc_smp_nodes *nodes); + bool is_a83t; }; static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes) @@ -705,6 +702,7 @@ static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes) of_node_put(nodes->prcm_node); of_node_put(nodes->cpucfg_node); of_node_put(nodes->sram_node); + of_node_put(nodes->r_cpucfg_node); memset(nodes, 0, sizeof(*nodes)); } @@ -734,11 +732,42 @@ static int __init sun9i_a80_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes) return 0; } +static int __init sun8i_a83t_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes) +{ + nodes->prcm_node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a83t-r-ccu"); + if (!nodes->prcm_node) { + pr_err("%s: PRCM not available\n", __func__); + return -ENODEV; + } + + nodes->cpucfg_node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a83t-cpucfg"); + if (!nodes->cpucfg_node) { + pr_err("%s: CPUCFG not available\n", __func__); + return -ENODEV; + } + + nodes->r_cpucfg_node = of_find_compatible_node(NULL, NULL, + "allwinner,sun8i-a83t-r-cpucfg"); + if (!nodes->r_cpucfg_node) { + pr_err("%s: RCPUCFG not available\n", __func__); + return -ENODEV; + } + + return 0; +} + static const struct sunxi_mc_smp_data sunxi_mc_smp_data[] __initconst = { { .enable_method = "allwinner,sun9i-a80-smp", .get_smp_nodes = sun9i_a80_get_smp_nodes, }, + { + .enable_method = "allwinner,sun8i-a83t-smp", + .get_smp_nodes = sun8i_a83t_get_smp_nodes, + .is_a83t = true, + }, }; static int __init sunxi_mc_smp_init(void) @@ -746,6 +775,7 @@ static int __init sunxi_mc_smp_init(void) struct sunxi_mc_smp_nodes nodes = { 0 }; struct device_node *node; struct resource res; + void __iomem *addr; int i, ret; /* @@ -771,6 +801,8 @@ static int __init sunxi_mc_smp_init(void) break; } + is_a83t = sunxi_mc_smp_data[i].is_a83t; + of_node_put(node); if (ret) return -ENODEV; @@ -808,12 +840,23 @@ static int __init sunxi_mc_smp_init(void) goto err_unmap_prcm; } - sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0, - "sunxi-mc-smp"); - if (IS_ERR(sram_b_smp_base)) { - ret = PTR_ERR(sram_b_smp_base); - pr_err("%s: failed to map secure SRAM\n", __func__); - goto err_unmap_release_cpucfg; + if (is_a83t) { + r_cpucfg_base = of_io_request_and_map(nodes.r_cpucfg_node, + 0, "sunxi-mc-smp"); + if (IS_ERR(r_cpucfg_base)) { + ret = PTR_ERR(r_cpucfg_base); + pr_err("%s: failed to map R-CPUCFG registers\n", + __func__); + goto err_unmap_release_cpucfg; + } + } else { + sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0, + "sunxi-mc-smp"); + if (IS_ERR(sram_b_smp_base)) { + ret = PTR_ERR(sram_b_smp_base); + pr_err("%s: failed to map secure SRAM\n", __func__); + goto err_unmap_release_cpucfg; + } } /* Configure CCI-400 for boot cluster */ @@ -821,15 +864,18 @@ static int __init sunxi_mc_smp_init(void) if (ret) { pr_err("%s: failed to configure boot cluster: %d\n", __func__, ret); - goto err_unmap_release_secure_sram; + goto err_unmap_release_sram_rcpucfg; } /* We don't need the device nodes anymore */ sunxi_mc_smp_put_nodes(&nodes); /* Set the hardware entry point address */ - writel(__pa_symbol(sunxi_mc_smp_secondary_startup), - prcm_base + PRCM_CPU_SOFT_ENTRY_REG); + if (is_a83t) + addr = r_cpucfg_base + R_CPUCFG_CPU_SOFT_ENTRY_REG; + else + addr = prcm_base + PRCM_CPU_SOFT_ENTRY_REG; + writel(__pa_symbol(sunxi_mc_smp_secondary_startup), addr); /* Actually enable multi cluster SMP */ smp_set_ops(&sunxi_mc_smp_smp_ops); @@ -838,9 +884,14 @@ static int __init sunxi_mc_smp_init(void) return 0; -err_unmap_release_secure_sram: - iounmap(sram_b_smp_base); - of_address_to_resource(nodes.sram_node, 0, &res); +err_unmap_release_sram_rcpucfg: + if (is_a83t) { + iounmap(r_cpucfg_base); + of_address_to_resource(nodes.r_cpucfg_node, 0, &res); + } else { + iounmap(sram_b_smp_base); + of_address_to_resource(nodes.sram_node, 0, &res); + } release_mem_region(res.start, resource_size(&res)); err_unmap_release_cpucfg: iounmap(cpucfg_base); diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 5e9602ce1573..de4b0e932f22 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <asm/mach/arch.h> +#include <asm/secure_cntvoff.h> static const char * const sunxi_board_dt_compat[] = { "allwinner,sun4i-a10", @@ -62,7 +63,6 @@ MACHINE_END static const char * const sun8i_board_dt_compat[] = { "allwinner,sun8i-a23", "allwinner,sun8i-a33", - "allwinner,sun8i-a83t", "allwinner,sun8i-h2-plus", "allwinner,sun8i-h3", "allwinner,sun8i-r40", @@ -75,6 +75,24 @@ DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family") .dt_compat = sun8i_board_dt_compat, MACHINE_END +static void __init sun8i_a83t_cntvoff_init(void) +{ +#ifdef CONFIG_SMP + secure_cntvoff_init(); +#endif +} + +static const char * const sun8i_a83t_cntvoff_board_dt_compat[] = { + "allwinner,sun8i-a83t", + NULL, +}; + +DT_MACHINE_START(SUN8I_A83T_CNTVOFF_DT, "Allwinner A83t board") + .init_early = sun8i_a83t_cntvoff_init, + .init_time = sun6i_timer_init, + .dt_compat = sun8i_a83t_cntvoff_board_dt_compat, +MACHINE_END + static const char * const sun9i_board_dt_compat[] = { "allwinner,sun9i-a80", NULL, diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 02e712d2ea30..f9587be48235 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -97,6 +97,10 @@ static void __init tegra_dt_init_late(void) if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && of_machine_is_compatible("compal,paz00")) tegra_paz00_wifikill_init(); + + if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && + of_machine_is_compatible("nvidia,tegra20")) + platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0); } static const char * const tegra_dt_board_compat[] = { diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index f98332ea2ef2..c1086ebe0050 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -9,64 +9,33 @@ menuconfig ARCH_U8500 select ARM_ERRATA_764369 if SMP select ARM_GIC select CACHE_L2X0 + select CLKSRC_DBX500_PRCMU select CLKSRC_NOMADIK_MTU select GPIOLIB select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP + select I2C + select I2C_NOMADIK + select MFD_DB8500_PRCMU select PINCTRL + select PINCTRL_AB8500 + select PINCTRL_AB8505 select PINCTRL_ABX500 + select PINCTRL_DB8500 select PINCTRL_NOMADIK select PL310_ERRATA_753970 if CACHE_L2X0 - help - Support for ST-Ericsson's Ux500 architecture - -if ARCH_U8500 - -config UX500_SOC_DB8500 - bool - select MFD_DB8500_PRCMU - select PINCTRL_DB8500 - select PINCTRL_DB8540 - select PINCTRL_AB8500 - select PINCTRL_AB8505 - select PINCTRL_AB9540 - select PINCTRL_AB8540 - select REGULATOR - select REGULATOR_DB8500_PRCMU - select CLKSRC_DBX500_PRCMU select PM_GENERIC_DOMAINS if PM - -config MACH_MOP500 - bool "U8500 Development platform, MOP500 versions" - select I2C - select I2C_NOMADIK select REGULATOR + select REGULATOR_DB8500_PRCMU select REGULATOR_FIXED_VOLTAGE select SOC_BUS - select UX500_SOC_DB8500 help - Include support for the MOP500 development platform. - -config MACH_HREFV60 - bool "U8500 Development platform, HREFv60 version" - select MACH_MOP500 - help - Include support for the HREFv60 new development platform. - Includes HREFv70, v71 etc. + Support for ST-Ericsson's Ux500 architecture -config MACH_SNOWBALL - bool "U8500 Snowball platform" - select MACH_MOP500 - help - Include support for the snowball development platform. +if ARCH_U8500 -config UX500_AUTO_PLATFORM +config UX500_SOC_DB8500 def_bool y - select MACH_MOP500 - help - At least one platform needs to be selected in order to build - a working kernel. If everything else is disabled, this - automatically enables MACH_MOP500. config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 36cd23c8be9b..389ecf6faa00 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -111,11 +111,6 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd) prcmu_system_reset(0); } -static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL), - {}, -}; - static const struct of_device_id u8500_local_bus_nodes[] = { /* only create devices below soc node */ { .compatible = "stericsson,db8500", }, @@ -129,20 +124,13 @@ static void __init u8500_init_machine(void) /* Initialize ux500 power domains */ ux500_pm_domains_init(); - /* automatically probe child nodes of dbx5x0 devices */ - if (of_machine_is_compatible("st-ericsson,u8540")) - of_platform_populate(NULL, u8500_local_bus_nodes, - u8540_auxdata_lookup, NULL); - else - of_platform_populate(NULL, u8500_local_bus_nodes, - NULL, NULL); + of_platform_populate(NULL, u8500_local_bus_nodes, + NULL, NULL); } static const char * stericsson_dt_platform_compat[] = { "st-ericsson,u8500", - "st-ericsson,u8540", "st-ericsson,u9500", - "st-ericsson,u9540", NULL, }; diff --git a/arch/arm/mach-ux500/db8500-regs.h b/arch/arm/mach-ux500/db8500-regs.h index 27399553c841..3d6e1955119a 100644 --- a/arch/arm/mach-ux500/db8500-regs.h +++ b/arch/arm/mach-ux500/db8500-regs.h @@ -41,10 +41,6 @@ /* ASIC ID is at 0xbf4 offset within this region */ #define U8500_ASIC_ID_BASE 0x9001D000 -#define U9540_BOOT_ROM_BASE 0xFFFE0000 -/* ASIC ID is at 0xbf4 offset within this region */ -#define U9540_ASIC_ID_BASE 0xFFFFD000 - #define U8500_PER6_BASE 0xa03c0000 #define U8500_PER7_BASE 0xa03d0000 #define U8500_PER5_BASE 0xa03e0000 diff --git a/arch/arm/mm/cache-b15-rac.c b/arch/arm/mm/cache-b15-rac.c index d9586ba2e63c..c6ed14840c3c 100644 --- a/arch/arm/mm/cache-b15-rac.c +++ b/arch/arm/mm/cache-b15-rac.c @@ -33,7 +33,10 @@ extern void v7_flush_kern_cache_all(void); #define RAC_CPU_SHIFT (8) #define RACCFG_MASK (0xff) #define RAC_CONFIG1_REG (0x7c) -#define RAC_FLUSH_REG (0x80) +/* Brahma-B15 is a quad-core only design */ +#define B15_RAC_FLUSH_REG (0x80) +/* Brahma-B53 is an octo-core design */ +#define B53_RAC_FLUSH_REG (0x84) #define FLUSH_RAC (1 << 0) /* Bitmask to enable instruction and data prefetching with a 256-bytes stride */ @@ -52,6 +55,7 @@ static void __iomem *b15_rac_base; static DEFINE_SPINLOCK(rac_lock); static u32 rac_config0_reg; +static u32 rac_flush_offset; /* Initialization flag to avoid checking for b15_rac_base, and to prevent * multi-platform kernels from crashing here as well. @@ -70,14 +74,14 @@ static inline void __b15_rac_flush(void) { u32 reg; - __raw_writel(FLUSH_RAC, b15_rac_base + RAC_FLUSH_REG); + __raw_writel(FLUSH_RAC, b15_rac_base + rac_flush_offset); do { /* This dmb() is required to force the Bus Interface Unit * to clean oustanding writes, and forces an idle cycle * to be inserted. */ dmb(); - reg = __raw_readl(b15_rac_base + RAC_FLUSH_REG); + reg = __raw_readl(b15_rac_base + rac_flush_offset); } while (reg & FLUSH_RAC); } @@ -287,7 +291,7 @@ static struct syscore_ops b15_rac_syscore_ops = { static int __init b15_rac_init(void) { - struct device_node *dn; + struct device_node *dn, *cpu_dn; int ret = 0, cpu; u32 reg, en_mask = 0; @@ -305,6 +309,24 @@ static int __init b15_rac_init(void) goto out; } + cpu_dn = of_get_cpu_node(0, NULL); + if (!cpu_dn) { + ret = -ENODEV; + goto out; + } + + if (of_device_is_compatible(cpu_dn, "brcm,brahma-b15")) + rac_flush_offset = B15_RAC_FLUSH_REG; + else if (of_device_is_compatible(cpu_dn, "brcm,brahma-b53")) + rac_flush_offset = B53_RAC_FLUSH_REG; + else { + pr_err("Unsupported CPU\n"); + of_node_put(cpu_dn); + ret = -EINVAL; + goto out; + } + of_node_put(cpu_dn); + ret = register_reboot_notifier(&b15_rac_reboot_nb); if (ret) { pr_err("failed to register reboot notifier\n"); diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index afc1a1d4f7a5..c0a242cae79a 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -115,16 +115,6 @@ config OMAP_SERIAL_WAKE to data on the serial RX line. This allows you to wake the system from serial console. -choice - prompt "OMAP PM layer selection" - depends on ARCH_OMAP - default OMAP_PM_NOOP - -config OMAP_PM_NOOP - bool "No-op/debug PM layer" - -endchoice - endmenu endif diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index 42bac8d5ab5d..2da35735fa38 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -413,8 +413,7 @@ static int s3c_adc_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int s3c_adc_suspend(struct device *dev) { - struct platform_device *pdev = to_platform_device(dev); - struct adc_device *adc = platform_get_drvdata(pdev); + struct adc_device *adc = dev_get_drvdata(dev); unsigned long flags; u32 con; diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h index f5769e93544a..d69a0ca09fb5 100644 --- a/arch/arm/plat-samsung/include/plat/map-s5p.h +++ b/arch/arm/plat-samsung/include/plat/map-s5p.h @@ -11,10 +11,6 @@ #define S5P_VA_CHIPID S3C_ADDR(0x02000000) -#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000) -#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x)) -#define S5P_VA_SCU S5P_VA_COREPERI(0x0) - #define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000)) #define VA_VIC0 VA_VIC(0) #define VA_VIC1 VA_VIC(1) |