diff options
Diffstat (limited to 'arch/arm/mach-bcm')
-rw-r--r-- | arch/arm/mach-bcm/Kconfig | 19 | ||||
-rw-r--r-- | arch/arm/mach-bcm/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm21664.c | 45 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm23550.c | 25 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm281xx.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm2835.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-bcm/kona_l2_cache.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-bcm/platsmp.c | 174 |
8 files changed, 138 insertions, 143 deletions
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 4f1709b31822..34f0fca0b847 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -17,7 +17,7 @@ config ARCH_BCM_IPROC select ARM_GLOBAL_TIMER select COMMON_CLK_IPROC select CLKSRC_MMIO - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select ARM_AMBA select PINCTRL help @@ -80,7 +80,7 @@ comment "KONA architected SoCs" config ARCH_BCM_MOBILE bool - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select ARM_ERRATA_754322 select ARM_ERRATA_775420 select ARM_GIC @@ -112,9 +112,17 @@ config ARCH_BCM_21664 Enable support for the BCM21664 family, which includes BCM21663 and BCM21664 variants. +config ARCH_BCM_23550 + bool "Broadcom BCM23550 SoC" + depends on ARCH_MULTI_V7 + select ARCH_BCM_MOBILE + select HAVE_SMP + help + Enable support for the BCM23550. + config ARCH_BCM_MOBILE_L2_CACHE bool "Broadcom mobile SoC level 2 cache support" - depends on ARCH_BCM_MOBILE + depends on ARCH_BCM_281XX || ARCH_BCM_21664 default y select CACHE_L2X0 select ARCH_BCM_MOBILE_SMC @@ -129,7 +137,7 @@ config ARCH_BCM_MOBILE_SMP select HAVE_ARM_SCU select ARM_ERRATA_764369 help - SMP support for the BCM281XX and BCM21664 SoC families. + SMP support for the BCM281XX, BCM21664 and BCM23550 SoC families. Provided as an option so SMP support for SoCs of this type can be disabled for an SMP-enabled kernel. @@ -138,7 +146,7 @@ comment "Other Architectures" config ARCH_BCM2835 bool "Broadcom BCM2835 family" depends on ARCH_MULTI_V6 || ARCH_MULTI_V7 - select ARCH_REQUIRE_GPIOLIB + select GPIOLIB select ARM_AMBA select ARM_ERRATA_411920 if ARCH_MULTI_V6 select ARM_TIMER_SP804 @@ -178,7 +186,6 @@ config ARCH_BRCMSTB select BRCMSTB_L2_IRQ select BCM7120_L2_IRQ select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - select ARCH_WANT_OPTIONAL_GPIOLIB select SOC_BRCMSTB select SOC_BUS help diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index 7d665151c772..980f5850097c 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -26,7 +26,10 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o # BCM21664 obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o -# BCM281XX and BCM21664 SMP support +# BCM23550 +obj-$(CONFIG_ARCH_BCM_23550) += board_bcm23550.o + +# BCM281XX, BCM21664 and BCM23550 SMP support obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += platsmp.o # BCM281XX and BCM21664 L2 cache control diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c index 82ad5687771f..c5bf01641172 100644 --- a/arch/arm/mach-bcm/board_bcm21664.c +++ b/arch/arm/mach-bcm/board_bcm21664.c @@ -11,56 +11,12 @@ * GNU General Public License for more details. */ -#include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/io.h> - #include <asm/mach/arch.h> #include "kona_l2_cache.h" -#define RSTMGR_DT_STRING "brcm,bcm21664-resetmgr" - -#define RSTMGR_REG_WR_ACCESS_OFFSET 0 -#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET 4 - -#define RSTMGR_WR_PASSWORD 0xa5a5 -#define RSTMGR_WR_PASSWORD_SHIFT 8 -#define RSTMGR_WR_ACCESS_ENABLE 1 - -static void bcm21664_restart(enum reboot_mode mode, const char *cmd) -{ - void __iomem *base; - struct device_node *resetmgr; - - resetmgr = of_find_compatible_node(NULL, NULL, RSTMGR_DT_STRING); - if (!resetmgr) { - pr_emerg("Couldn't find " RSTMGR_DT_STRING "\n"); - return; - } - base = of_iomap(resetmgr, 0); - if (!base) { - pr_emerg("Couldn't map " RSTMGR_DT_STRING "\n"); - return; - } - - /* - * A soft reset is triggered by writing a 0 to bit 0 of the soft reset - * register. To write to that register we must first write the password - * and the enable bit in the write access enable register. - */ - writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) | - RSTMGR_WR_ACCESS_ENABLE, - base + RSTMGR_REG_WR_ACCESS_OFFSET); - writel(0, base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET); - - /* Wait for reset */ - while (1); -} - static void __init bcm21664_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); kona_l2_cache_init(); } @@ -71,6 +27,5 @@ static const char * const bcm21664_dt_compat[] = { DT_MACHINE_START(BCM21664_DT, "BCM21664 Broadcom Application Processor") .init_machine = bcm21664_init, - .restart = bcm21664_restart, .dt_compat = bcm21664_dt_compat, MACHINE_END diff --git a/arch/arm/mach-bcm/board_bcm23550.c b/arch/arm/mach-bcm/board_bcm23550.c new file mode 100644 index 000000000000..0ac01debd077 --- /dev/null +++ b/arch/arm/mach-bcm/board_bcm23550.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Broadcom + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of_platform.h> + +#include <asm/mach/arch.h> + +static const char * const bcm23550_dt_compat[] = { + "brcm,bcm23550", + NULL, +}; + +DT_MACHINE_START(BCM23550_DT, "BCM23550 Broadcom Application Processor") + .dt_compat = bcm23550_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-bcm/board_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c index 2e367bd7c600..b81bb386951d 100644 --- a/arch/arm/mach-bcm/board_bcm281xx.c +++ b/arch/arm/mach-bcm/board_bcm281xx.c @@ -13,7 +13,6 @@ #include <linux/clocksource.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <asm/mach/arch.h> @@ -58,7 +57,6 @@ static void bcm281xx_restart(enum reboot_mode mode, const char *cmd) static void __init bcm281xx_init(void) { - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); kona_l2_cache_init(); } diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c index 834d67684e20..0c1edfc98696 100644 --- a/arch/arm/mach-bcm/board_bcm2835.c +++ b/arch/arm/mach-bcm/board_bcm2835.c @@ -15,7 +15,6 @@ #include <linux/init.h> #include <linux/irqchip.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/clk/bcm2835.h> #include <asm/mach/arch.h> @@ -23,16 +22,7 @@ static void __init bcm2835_init(void) { - int ret; - bcm2835_init_clocks(); - - ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, - NULL); - if (ret) { - pr_err("of_platform_populate failed: %d\n", ret); - BUG(); - } } static const char * const bcm2835_compat[] = { diff --git a/arch/arm/mach-bcm/kona_l2_cache.c b/arch/arm/mach-bcm/kona_l2_cache.c index b31970377c20..59ad86304092 100644 --- a/arch/arm/mach-bcm/kona_l2_cache.c +++ b/arch/arm/mach-bcm/kona_l2_cache.c @@ -17,6 +17,7 @@ #include <asm/hardware/cache-l2x0.h> #include "bcm_kona_smc.h" +#include "kona_l2_cache.h" void __init kona_l2_cache_init(void) { diff --git a/arch/arm/mach-bcm/platsmp.c b/arch/arm/mach-bcm/platsmp.c index cfae9c71fb74..3ac3a9bc663c 100644 --- a/arch/arm/mach-bcm/platsmp.c +++ b/arch/arm/mach-bcm/platsmp.c @@ -19,6 +19,7 @@ #include <linux/io.h> #include <linux/jiffies.h> #include <linux/of.h> +#include <linux/of_address.h> #include <linux/sched.h> #include <linux/smp.h> @@ -37,9 +38,6 @@ #define OF_SECONDARY_BOOT "secondary-boot-reg" #define MPIDR_CPUID_BITMASK 0x3 -/* I/O address of register used to coordinate secondary core startup */ -static u32 secondary_boot_addr; - /* * Enable the Cortex A9 Snoop Control Unit * @@ -81,20 +79,40 @@ static int __init scu_a9_enable(void) return 0; } -static int nsp_write_lut(void) +static u32 secondary_boot_addr_for(unsigned int cpu) +{ + u32 secondary_boot_addr = 0; + struct device_node *cpu_node = of_get_cpu_node(cpu, NULL); + + if (!cpu_node) { + pr_err("Failed to find device tree node for CPU%u\n", cpu); + return 0; + } + + if (of_property_read_u32(cpu_node, + OF_SECONDARY_BOOT, + &secondary_boot_addr)) + pr_err("required secondary boot register not specified for CPU%u\n", + cpu); + + of_node_put(cpu_node); + + return secondary_boot_addr; +} + +static int nsp_write_lut(unsigned int cpu) { void __iomem *sku_rom_lut; phys_addr_t secondary_startup_phy; + const u32 secondary_boot_addr = secondary_boot_addr_for(cpu); - if (!secondary_boot_addr) { - pr_warn("required secondary boot register not specified\n"); + if (!secondary_boot_addr) return -EINVAL; - } sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, - sizeof(secondary_boot_addr)); + sizeof(phys_addr_t)); if (!sku_rom_lut) { - pr_warn("unable to ioremap SKU-ROM LUT register\n"); + pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu); return -ENOMEM; } @@ -113,70 +131,12 @@ static int nsp_write_lut(void) static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) { - static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; - struct device_node *cpus_node = NULL; - struct device_node *cpu_node = NULL; - int ret; - - /* - * This function is only called via smp_ops->smp_prepare_cpu(). - * That only happens if a "/cpus" device tree node exists - * and has an "enable-method" property that selects the SMP - * operations defined herein. - */ - cpus_node = of_find_node_by_path("/cpus"); - if (!cpus_node) - return; - - for_each_child_of_node(cpus_node, cpu_node) { - u32 cpuid; - - if (of_node_cmp(cpu_node->type, "cpu")) - continue; - - if (of_property_read_u32(cpu_node, "reg", &cpuid)) { - pr_debug("%s: missing reg property\n", - cpu_node->full_name); - ret = -ENOENT; - goto out; - } - - /* - * "secondary-boot-reg" property should be defined only - * for secondary cpu - */ - if ((cpuid & MPIDR_CPUID_BITMASK) == 1) { - /* - * Our secondary enable method requires a - * "secondary-boot-reg" property to specify a register - * address used to request the ROM code boot a secondary - * core. If we have any trouble getting this we fall - * back to uniprocessor mode. - */ - if (of_property_read_u32(cpu_node, - OF_SECONDARY_BOOT, - &secondary_boot_addr)) { - pr_warn("%s: no" OF_SECONDARY_BOOT "property\n", - cpu_node->name); - ret = -ENOENT; - goto out; - } - } - } - - /* - * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is - * returned, the SoC reported a uniprocessor configuration. - * We bail on any other error. - */ - ret = scu_a9_enable(); -out: - of_node_put(cpu_node); - of_node_put(cpus_node); + const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; - if (ret) { + /* Enable the SCU on Cortex A9 based SoCs */ + if (scu_a9_enable()) { /* Update the CPU present map to reflect uniprocessor mode */ - pr_warn("disabling SMP\n"); + pr_warn("failed to enable A9 SCU - disabling SMP\n"); init_cpu_present(&only_cpu_0); } } @@ -207,6 +167,7 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) u32 cpu_id; u32 boot_val; bool timeout = false; + const u32 secondary_boot_addr = secondary_boot_addr_for(cpu); cpu_id = cpu_logical_map(cpu); if (cpu_id & ~BOOT_ADDR_CPUID_MASK) { @@ -214,13 +175,11 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) return -EINVAL; } - if (!secondary_boot_addr) { - pr_err("required secondary boot register not specified\n"); + if (!secondary_boot_addr) return -EINVAL; - } - boot_reg = ioremap_nocache( - (phys_addr_t)secondary_boot_addr, sizeof(u32)); + boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr, + sizeof(phys_addr_t)); if (!boot_reg) { pr_err("unable to map boot register for cpu %u\n", cpu_id); return -ENOMEM; @@ -255,6 +214,57 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) return -ENXIO; } +/* Cluster Dormant Control command to bring CPU into a running state */ +#define CDC_CMD 6 +#define CDC_CMD_OFFSET 0 +#define CDC_CMD_REG(cpu) (CDC_CMD_OFFSET + 4*(cpu)) + +/* + * BCM23550 has a Cluster Dormant Control block that keeps the core in + * idle state. A command needs to be sent to the block to bring the CPU + * into running state. + */ +static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + void __iomem *cdc_base; + struct device_node *dn; + char *name; + int ret; + + /* Make sure a CDC node exists before booting the + * secondary core. + */ + name = "brcm,bcm23550-cdc"; + dn = of_find_compatible_node(NULL, NULL, name); + if (!dn) { + pr_err("unable to find cdc node\n"); + return -ENODEV; + } + + cdc_base = of_iomap(dn, 0); + of_node_put(dn); + + if (!cdc_base) { + pr_err("unable to remap cdc base register\n"); + return -ENOMEM; + } + + /* Boot the secondary core */ + ret = kona_boot_secondary(cpu, idle); + if (ret) + goto out; + + /* Bring this CPU to RUN state so that nIRQ nFIQ + * signals are unblocked. + */ + writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu)); + +out: + iounmap(cdc_base); + + return ret; +} + static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) { int ret; @@ -263,7 +273,7 @@ static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) * After wake up, secondary core branches to the startup * address programmed at SKU ROM LUT location. */ - ret = nsp_write_lut(); + ret = nsp_write_lut(cpu); if (ret) { pr_err("unable to write startup addr to SKU ROM LUT\n"); goto out; @@ -276,12 +286,18 @@ out: return ret; } -static const struct smp_operations bcm_smp_ops __initconst = { +static const struct smp_operations kona_smp_ops __initconst = { .smp_prepare_cpus = bcm_smp_prepare_cpus, .smp_boot_secondary = kona_boot_secondary, }; CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", - &bcm_smp_ops); + &kona_smp_ops); + +static const struct smp_operations bcm23550_smp_ops __initconst = { + .smp_boot_secondary = bcm23550_boot_secondary, +}; +CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550", + &bcm23550_smp_ops); static const struct smp_operations nsp_smp_ops __initconst = { .smp_prepare_cpus = bcm_smp_prepare_cpus, |