diff options
Diffstat (limited to 'arch/arm/mach-bcm')
-rw-r--r-- | arch/arm/mach-bcm/Kconfig | 88 | ||||
-rw-r--r-- | arch/arm/mach-bcm/Makefile | 25 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_5301x.c | 56 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc.c | 136 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc.h | 52 | ||||
-rw-r--r-- | arch/arm/mach-bcm/bcm_kona_smc_asm.S | 41 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm21664.c | 77 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm281xx.c | 85 | ||||
-rw-r--r-- | arch/arm/mach-bcm/board_bcm2835.c | 137 | ||||
-rw-r--r-- | arch/arm/mach-bcm/kona.c | 65 | ||||
-rw-r--r-- | arch/arm/mach-bcm/kona_l2_cache.c | 47 | ||||
-rw-r--r-- | arch/arm/mach-bcm/kona_l2_cache.h (renamed from arch/arm/mach-bcm/kona.h) | 11 |
12 files changed, 558 insertions, 262 deletions
diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index b1aa6a9b3bd1..9bc6db1c1348 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -1,37 +1,91 @@ config ARCH_BCM - bool "Broadcom SoC Support" - depends on ARCH_MULTIPLATFORM + bool "Broadcom SoC Support" if ARCH_MULTI_V6_V7 help - This enables support for Broadcom ARM based SoC - chips - -if ARCH_BCM + This enables support for Broadcom ARM based SoC chips menu "Broadcom SoC Selection" + depends on ARCH_BCM config ARCH_BCM_MOBILE - bool "Broadcom Mobile SoC" if ARCH_MULTI_V7 - depends on MMU + bool "Broadcom Mobile SoC Support" if ARCH_MULTI_V7 select ARCH_REQUIRE_GPIOLIB select ARM_ERRATA_754322 select ARM_ERRATA_764369 if SMP + select ARM_ERRATA_775420 select ARM_GIC - select CPU_V7 - select CLKSRC_OF - select GENERIC_CLOCKEVENTS - select GENERIC_TIME select GPIO_BCM_KONA - select SPARSE_IRQ select TICK_ONESHOT - select CACHE_L2X0 select HAVE_ARM_ARCH_TIMER select PINCTRL help This enables support for systems based on Broadcom mobile SoCs. - It currently supports the 'BCM281XX' family, which includes - BCM11130, BCM11140, BCM11351, BCM28145 and - BCM28155 variants. + +if ARCH_BCM_MOBILE + +menu "Broadcom Mobile SoC Selection" + +config ARCH_BCM_281XX + bool "Broadcom BCM281XX SoC family" + default y + help + Enable support for the the BCM281XX family, which includes + BCM11130, BCM11140, BCM11351, BCM28145 and BCM28155 + variants. + +config ARCH_BCM_21664 + bool "Broadcom BCM21664 SoC family" + default y + help + Enable support for the the BCM21664 family, which includes + BCM21663 and BCM21664 variants. + +config ARCH_BCM_MOBILE_L2_CACHE + bool "Broadcom mobile SoC level 2 cache support" + depends on (ARCH_BCM_281XX || ARCH_BCM_21664) + default y + select CACHE_L2X0 + select ARCH_BCM_MOBILE_SMC + +config ARCH_BCM_MOBILE_SMC + bool + depends on ARCH_BCM_281XX || ARCH_BCM_21664 endmenu endif + +config ARCH_BCM2835 + bool "Broadcom BCM2835 family" if ARCH_MULTI_V6 + select ARCH_REQUIRE_GPIOLIB + select ARM_AMBA + select ARM_ERRATA_411920 + select ARM_TIMER_SP804 + select CLKSRC_OF + select PINCTRL + select PINCTRL_BCM2835 + help + This enables support for the Broadcom BCM2835 SoC. This SoC is + used in the Raspberry Pi and Roku 2 devices. + +config ARCH_BCM_5301X + bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 + select ARM_GIC + select CACHE_L2X0 + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select ARM_GLOBAL_TIMER + select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK + help + Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. + + This is a network SoC line mostly used in home routers and + wifi access points, it's internal name is Northstar. + This inclused the following SoC: BCM53010, BCM53011, BCM53012, + BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707, + BCM4708 and BCM4709. + + Do not confuse this with the BCM4760 which is a totally + different SoC or with the older BCM47XX and BCM53XX based + network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx + +endmenu diff --git a/arch/arm/mach-bcm/Makefile b/arch/arm/mach-bcm/Makefile index c2ccd5a0f772..731292114975 100644 --- a/arch/arm/mach-bcm/Makefile +++ b/arch/arm/mach-bcm/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2012-2013 Broadcom Corporation +# Copyright (C) 2012-2014 Broadcom Corporation # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -10,6 +10,23 @@ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -obj-$(CONFIG_ARCH_BCM_MOBILE) := board_bcm281xx.o bcm_kona_smc.o bcm_kona_smc_asm.o kona.o -plus_sec := $(call as-instr,.arch_extension sec,+sec) -AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) +# BCM281XX +obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o + +# BCM21664 +obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o + +# BCM281XX and BCM21664 L2 cache control +obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o + +# Support for secure monitor traps +obj-$(CONFIG_ARCH_BCM_MOBILE_SMC) += bcm_kona_smc.o +ifeq ($(call as-instr,.arch_extension sec,as_has_sec),as_has_sec) +CFLAGS_bcm_kona_smc.o += -Wa,-march=armv7-a+sec -DREQUIRES_SEC +endif + +# BCM2835 +obj-$(CONFIG_ARCH_BCM2835) += board_bcm2835.o + +# BCM5301X +obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c new file mode 100644 index 000000000000..e9bcbdbce555 --- /dev/null +++ b/arch/arm/mach-bcm/bcm_5301x.c @@ -0,0 +1,56 @@ +/* + * Broadcom BCM470X / BCM5301X ARM platform code. + * + * Copyright 2013 Hauke Mehrtens <hauke@hauke-m.de> + * + * Licensed under the GNU/GPL. See COPYING for details. + */ +#include <linux/of_platform.h> +#include <asm/hardware/cache-l2x0.h> + +#include <asm/mach/arch.h> +#include <asm/siginfo.h> +#include <asm/signal.h> + + +static bool first_fault = true; + +static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) +{ + if (fsr == 0x1c06 && first_fault) { + first_fault = false; + + /* + * These faults with code 0x1c06 happens for no good reason, + * possibly left over from the CFE boot loader. + */ + pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", + addr, fsr); + + /* Returning non-zero causes fault display and panic */ + return 0; + } + + /* Others should cause a fault */ + return 1; +} + +static void __init bcm5301x_init_early(void) +{ + /* Install our hook */ + hook_fault_code(16 + 6, bcm5301x_abort_handler, SIGBUS, BUS_OBJERR, + "imprecise external abort"); +} + +static const char __initconst *bcm5301x_dt_compat[] = { + "brcm,bcm4708", + NULL, +}; + +DT_MACHINE_START(BCM5301X, "BCM5301X") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, + .init_early = bcm5301x_init_early, + .dt_compat = bcm5301x_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-bcm/bcm_kona_smc.c b/arch/arm/mach-bcm/bcm_kona_smc.c index 5e31e918f325..a55a7ecf146a 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.c +++ b/arch/arm/mach-bcm/bcm_kona_smc.c @@ -21,11 +21,8 @@ #include "bcm_kona_smc.h" -struct secure_bridge_data { - void __iomem *bounce; /* virtual address */ - u32 __iomem buffer_addr; /* physical address */ - int initialized; -} bridge_data; +static u32 bcm_smc_buffer_phys; /* physical address */ +static void __iomem *bcm_smc_buffer; /* virtual address */ struct bcm_kona_smc_data { unsigned service_id; @@ -33,6 +30,7 @@ struct bcm_kona_smc_data { unsigned arg1; unsigned arg2; unsigned arg3; + unsigned result; }; static const struct of_device_id bcm_kona_smc_ids[] __initconst = { @@ -41,59 +39,125 @@ static const struct of_device_id bcm_kona_smc_ids[] __initconst = { {}, }; -/* Map in the bounce area */ +/* Map in the args buffer area */ int __init bcm_kona_smc_init(void) { struct device_node *node; + const __be32 *prop_val; + u64 prop_size = 0; + unsigned long buffer_size; + u32 buffer_phys; /* Read buffer addr and size from the device tree node */ node = of_find_matching_node(NULL, bcm_kona_smc_ids); if (!node) return -ENODEV; - /* Don't care about size or flags of the DT node */ - bridge_data.buffer_addr = - be32_to_cpu(*of_get_address(node, 0, NULL, NULL)); - BUG_ON(!bridge_data.buffer_addr); + prop_val = of_get_address(node, 0, &prop_size, NULL); + if (!prop_val) + return -EINVAL; - bridge_data.bounce = of_iomap(node, 0); - BUG_ON(!bridge_data.bounce); + /* We assume space for four 32-bit arguments */ + if (prop_size < 4 * sizeof(u32) || prop_size > (u64)ULONG_MAX) + return -EINVAL; + buffer_size = (unsigned long)prop_size; - bridge_data.initialized = 1; + buffer_phys = be32_to_cpup(prop_val); + if (!buffer_phys) + return -EINVAL; + + bcm_smc_buffer = ioremap(buffer_phys, buffer_size); + if (!bcm_smc_buffer) + return -ENOMEM; + bcm_smc_buffer_phys = buffer_phys; pr_info("Kona Secure API initialized\n"); return 0; } +/* + * int bcm_kona_do_smc(u32 service_id, u32 buffer_addr) + * + * Only core 0 can run the secure monitor code. If an "smc" request + * is initiated on a different core it must be redirected to core 0 + * for execution. We rely on the caller to handle this. + * + * Each "smc" request supplies a service id and the address of a + * buffer containing parameters related to the service to be + * performed. A flags value defines the behavior of the level 2 + * cache and interrupt handling while the secure monitor executes. + * + * Parameters to the "smc" request are passed in r4-r6 as follows: + * r4 service id + * r5 flags (SEC_ROM_*) + * r6 physical address of buffer with other parameters + * + * Execution of an "smc" request produces two distinct results. + * + * First, the secure monitor call itself (regardless of the specific + * service request) can succeed, or can produce an error. When an + * "smc" request completes this value is found in r12; it should + * always be SEC_EXIT_NORMAL. + * + * In addition, the particular service performed produces a result. + * The values that should be expected depend on the service. We + * therefore return this value to the caller, so it can handle the + * request result appropriately. This result value is found in r0 + * when the "smc" request completes. + */ +static int bcm_kona_do_smc(u32 service_id, u32 buffer_phys) +{ + register u32 ip asm("ip"); /* Also called r12 */ + register u32 r0 asm("r0"); + register u32 r4 asm("r4"); + register u32 r5 asm("r5"); + register u32 r6 asm("r6"); + + r4 = service_id; + r5 = 0x3; /* Keep IRQ and FIQ off in SM */ + r6 = buffer_phys; + + asm volatile ( + /* Make sure we got the registers we want */ + __asmeq("%0", "ip") + __asmeq("%1", "r0") + __asmeq("%2", "r4") + __asmeq("%3", "r5") + __asmeq("%4", "r6") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + " smc #0\n" + : "=r" (ip), "=r" (r0) + : "r" (r4), "r" (r5), "r" (r6) + : "r1", "r2", "r3", "r7", "lr"); + + BUG_ON(ip != SEC_EXIT_NORMAL); + + return r0; +} + /* __bcm_kona_smc() should only run on CPU 0, with pre-emption disabled */ static void __bcm_kona_smc(void *info) { struct bcm_kona_smc_data *data = info; - u32 *args = bridge_data.bounce; - int rc = 0; + u32 *args = bcm_smc_buffer; - /* Must run on CPU 0 */ BUG_ON(smp_processor_id() != 0); + BUG_ON(!args); - /* Check map in the bounce area */ - BUG_ON(!bridge_data.initialized); - - /* Copy one 32 bit word into the bounce area */ - args[0] = data->arg0; - args[1] = data->arg1; - args[2] = data->arg2; - args[3] = data->arg3; + /* Copy the four 32 bit argument values into the bounce area */ + writel_relaxed(data->arg0, args++); + writel_relaxed(data->arg1, args++); + writel_relaxed(data->arg2, args++); + writel(data->arg3, args); /* Flush caches for input data passed to Secure Monitor */ - if (data->service_id != SSAPI_BRCM_START_VC_CORE) - flush_cache_all(); - - /* Trap into Secure Monitor */ - rc = bcm_kona_smc_asm(data->service_id, bridge_data.buffer_addr); + flush_cache_all(); - if (rc != SEC_ROM_RET_OK) - pr_err("Secure Monitor call failed (0x%x)!\n", rc); + /* Trap into Secure Monitor and record the request result */ + data->result = bcm_kona_do_smc(data->service_id, bcm_smc_buffer_phys); } unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, @@ -106,17 +170,13 @@ unsigned bcm_kona_smc(unsigned service_id, unsigned arg0, unsigned arg1, data.arg1 = arg1; data.arg2 = arg2; data.arg3 = arg3; + data.result = 0; /* * Due to a limitation of the secure monitor, we must use the SMP * infrastructure to forward all secure monitor calls to Core 0. */ - if (get_cpu() != 0) - smp_call_function_single(0, __bcm_kona_smc, (void *)&data, 1); - else - __bcm_kona_smc(&data); + smp_call_function_single(0, __bcm_kona_smc, &data, 1); - put_cpu(); - - return 0; + return data.result; } diff --git a/arch/arm/mach-bcm/bcm_kona_smc.h b/arch/arm/mach-bcm/bcm_kona_smc.h index d098a7e76744..2e29ec67e414 100644 --- a/arch/arm/mach-bcm/bcm_kona_smc.h +++ b/arch/arm/mach-bcm/bcm_kona_smc.h @@ -15,55 +15,12 @@ #define BCM_KONA_SMC_H #include <linux/types.h> -#define FLAGS (SEC_ROM_ICACHE_ENABLE_MASK | SEC_ROM_DCACHE_ENABLE_MASK | \ - SEC_ROM_IRQ_ENABLE_MASK | SEC_ROM_FIQ_ENABLE_MASK) -/*! - * Definitions for IRQ & FIQ Mask for ARM - */ - -#define FIQ_IRQ_MASK 0xC0 -#define FIQ_MASK 0x40 -#define IRQ_MASK 0x80 - -/*! - * Secure Mode FLAGs - */ - -/* When set, enables ICache within the secure mode */ -#define SEC_ROM_ICACHE_ENABLE_MASK 0x00000001 - -/* When set, enables DCache within the secure mode */ -#define SEC_ROM_DCACHE_ENABLE_MASK 0x00000002 - -/* When set, enables IRQ within the secure mode */ -#define SEC_ROM_IRQ_ENABLE_MASK 0x00000004 - -/* When set, enables FIQ within the secure mode */ -#define SEC_ROM_FIQ_ENABLE_MASK 0x00000008 - -/* When set, enables Unified L2 cache within the secure mode */ -#define SEC_ROM_UL2_CACHE_ENABLE_MASK 0x00000010 - -/* Broadcom Secure Service API Service IDs */ -#define SSAPI_DORMANT_ENTRY_SERV 0x01000000 -#define SSAPI_PUBLIC_OTP_SERV 0x01000001 -#define SSAPI_ENABLE_L2_CACHE 0x01000002 -#define SSAPI_DISABLE_L2_CACHE 0x01000003 -#define SSAPI_WRITE_SCU_STATUS 0x01000004 -#define SSAPI_WRITE_PWR_GATE 0x01000005 - -/* Broadcom Secure Service API Return Codes */ +/* Broadcom Secure Service API service IDs, return codes, and exit codes */ +#define SSAPI_ENABLE_L2_CACHE 0x01000002 #define SEC_ROM_RET_OK 0x00000001 -#define SEC_ROM_RET_FAIL 0x00000009 - -#define SSAPI_RET_FROM_INT_SERV 0x4 #define SEC_EXIT_NORMAL 0x1 -#define SSAPI_ROW_AES 0x0E000006 -#define SSAPI_BRCM_START_VC_CORE 0x0E000008 - -#ifndef __ASSEMBLY__ extern int __init bcm_kona_smc_init(void); extern unsigned bcm_kona_smc(unsigned service_id, @@ -72,9 +29,4 @@ extern unsigned bcm_kona_smc(unsigned service_id, unsigned arg2, unsigned arg3); -extern int bcm_kona_smc_asm(u32 service_id, - u32 buffer_addr); - -#endif /* __ASSEMBLY__ */ - #endif /* BCM_KONA_SMC_H */ diff --git a/arch/arm/mach-bcm/bcm_kona_smc_asm.S b/arch/arm/mach-bcm/bcm_kona_smc_asm.S deleted file mode 100644 index a1608480d60d..000000000000 --- a/arch/arm/mach-bcm/bcm_kona_smc_asm.S +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 Broadcom Corporation - * - * 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/linkage.h> -#include "bcm_kona_smc.h" - -/* - * int bcm_kona_smc_asm(u32 service_id, u32 buffer_addr) - */ - -ENTRY(bcm_kona_smc_asm) - stmfd sp!, {r4-r12, lr} - mov r4, r0 @ service_id - mov r5, #3 @ Keep IRQ and FIQ off in SM - /* - * Since interrupts are disabled in the open mode, we must keep - * interrupts disabled in secure mode by setting R5=0x3. If interrupts - * are enabled in open mode, we can set R5=0x0 to allow interrupts in - * secure mode. If we did this, the secure monitor would return back - * control to the open mode to handle the interrupt prior to completing - * the secure service. If this happened, R12 would not be - * SEC_EXIT_NORMAL and we would need to call SMC again after resetting - * R5 (it gets clobbered by the secure monitor) and setting R4 to - * SSAPI_RET_FROM_INT_SERV to indicate that we want the secure monitor - * to finish up the previous uncompleted secure service. - */ - mov r6, r1 @ buffer_addr - smc #0 - /* Check r12 for SEC_EXIT_NORMAL here if interrupts are enabled */ - ldmfd sp!, {r4-r12, pc} -ENDPROC(bcm_kona_smc_asm) diff --git a/arch/arm/mach-bcm/board_bcm21664.c b/arch/arm/mach-bcm/board_bcm21664.c new file mode 100644 index 000000000000..f0521cc0640d --- /dev/null +++ b/arch/arm/mach-bcm/board_bcm21664.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014 Broadcom Corporation + * + * 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_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, + &platform_bus); + kona_l2_cache_init(); +} + +static const char * const bcm21664_dt_compat[] = { + "brcm,bcm21664", + NULL, +}; + +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_bcm281xx.c b/arch/arm/mach-bcm/board_bcm281xx.c index cb3dc364405c..1ac59fc0cb15 100644 --- a/arch/arm/mach-bcm/board_bcm281xx.c +++ b/arch/arm/mach-bcm/board_bcm281xx.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Broadcom Corporation + * Copyright (C) 2012-2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -11,64 +11,65 @@ * GNU General Public License for more details. */ -#include <linux/of_platform.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/platform_device.h> #include <linux/clocksource.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> #include <asm/mach/arch.h> -#include <asm/mach/time.h> -#include <asm/hardware/cache-l2x0.h> -#include "bcm_kona_smc.h" -#include "kona.h" +#include "kona_l2_cache.h" + +#define SECWDOG_OFFSET 0x00000000 +#define SECWDOG_RESERVED_MASK 0xe2000000 +#define SECWDOG_WD_LOAD_FLAG_MASK 0x10000000 +#define SECWDOG_EN_MASK 0x08000000 +#define SECWDOG_SRSTEN_MASK 0x04000000 +#define SECWDOG_CLKS_SHIFT 20 +#define SECWDOG_COUNT_SHIFT 0 -static int __init kona_l2_cache_init(void) +static void bcm281xx_restart(enum reboot_mode mode, const char *cmd) { - if (!IS_ENABLED(CONFIG_CACHE_L2X0)) - return 0; + uint32_t val; + void __iomem *base; + struct device_node *np_wdog; - if (bcm_kona_smc_init() < 0) { - pr_info("Kona secure API not available. Skipping L2 init\n"); - return 0; + np_wdog = of_find_compatible_node(NULL, NULL, "brcm,kona-wdt"); + if (!np_wdog) { + pr_emerg("Couldn't find brcm,kona-wdt\n"); + return; + } + base = of_iomap(np_wdog, 0); + if (!base) { + pr_emerg("Couldn't map brcm,kona-wdt\n"); + return; } - bcm_kona_smc(SSAPI_ENABLE_L2_CACHE, 0, 0, 0, 0); - - /* - * The aux_val and aux_mask have no effect since L2 cache is already - * enabled. Pass 0s for aux_val and 1s for aux_mask for default value. - */ - return l2x0_of_init(0, ~0); -} - -static void bcm_board_setup_restart(void) -{ - struct device_node *np; + /* Enable watchdog with short timeout (244us). */ + val = readl(base + SECWDOG_OFFSET); + val &= SECWDOG_RESERVED_MASK | SECWDOG_WD_LOAD_FLAG_MASK; + val |= SECWDOG_EN_MASK | SECWDOG_SRSTEN_MASK | + (0x15 << SECWDOG_CLKS_SHIFT) | + (0x8 << SECWDOG_COUNT_SHIFT); + writel(val, base + SECWDOG_OFFSET); - np = of_find_compatible_node(NULL, NULL, "brcm,bcm11351"); - if (np) { - if (of_device_is_available(np)) - bcm_kona_setup_restart(); - of_node_put(np); - } - /* Restart setup for other boards goes here */ + /* Wait for reset */ + while (1); } -static void __init board_init(void) +static void __init bcm281xx_init(void) { of_platform_populate(NULL, of_default_bus_match_table, NULL, &platform_bus); - - bcm_board_setup_restart(); kona_l2_cache_init(); } -static const char * const bcm11351_dt_compat[] = { "brcm,bcm11351", NULL, }; +static const char * const bcm281xx_dt_compat[] = { + "brcm,bcm11351", /* Have to use the first number upstreamed */ + NULL, +}; -DT_MACHINE_START(BCM11351_DT, "BCM281xx Broadcom Application Processor") - .init_machine = board_init, - .restart = bcm_kona_restart, - .dt_compat = bcm11351_dt_compat, +DT_MACHINE_START(BCM281XX_DT, "BCM281xx Broadcom Application Processor") + .init_machine = bcm281xx_init, + .restart = bcm281xx_restart, + .dt_compat = bcm281xx_dt_compat, MACHINE_END diff --git a/arch/arm/mach-bcm/board_bcm2835.c b/arch/arm/mach-bcm/board_bcm2835.c new file mode 100644 index 000000000000..70f2f3925f0e --- /dev/null +++ b/arch/arm/mach-bcm/board_bcm2835.c @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2010 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/delay.h> +#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> +#include <asm/mach/map.h> + +#define PM_RSTC 0x1c +#define PM_RSTS 0x20 +#define PM_WDOG 0x24 + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC_WRCFG_MASK 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTS_HADWRH_SET 0x00000040 + +#define BCM2835_PERIPH_PHYS 0x20000000 +#define BCM2835_PERIPH_VIRT 0xf0000000 +#define BCM2835_PERIPH_SIZE SZ_16M + +static void __iomem *wdt_regs; + +/* + * The machine restart method can be called from an atomic context so we won't + * be able to ioremap the regs then. + */ +static void bcm2835_setup_restart(void) +{ + struct device_node *np = of_find_compatible_node(NULL, NULL, + "brcm,bcm2835-pm-wdt"); + if (WARN(!np, "unable to setup watchdog restart")) + return; + + wdt_regs = of_iomap(np, 0); + WARN(!wdt_regs, "failed to remap watchdog regs"); +} + +static void bcm2835_restart(enum reboot_mode mode, const char *cmd) +{ + u32 val; + + if (!wdt_regs) + return; + + /* use a timeout of 10 ticks (~150us) */ + writel_relaxed(10 | PM_PASSWORD, wdt_regs + PM_WDOG); + val = readl_relaxed(wdt_regs + PM_RSTC); + val &= ~PM_RSTC_WRCFG_MASK; + val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET; + writel_relaxed(val, wdt_regs + PM_RSTC); + + /* No sleeping, possibly atomic. */ + mdelay(1); +} + +/* + * We can't really power off, but if we do the normal reset scheme, and + * indicate to bootcode.bin not to reboot, then most of the chip will be + * powered off. + */ +static void bcm2835_power_off(void) +{ + u32 val; + + /* + * We set the watchdog hard reset bit here to distinguish this reset + * from the normal (full) reset. bootcode.bin will not reboot after a + * hard reset. + */ + val = readl_relaxed(wdt_regs + PM_RSTS); + val &= ~PM_RSTC_WRCFG_MASK; + val |= PM_PASSWORD | PM_RSTS_HADWRH_SET; + writel_relaxed(val, wdt_regs + PM_RSTS); + + /* Continue with normal reset mechanism */ + bcm2835_restart(REBOOT_HARD, ""); +} + +static struct map_desc io_map __initdata = { + .virtual = BCM2835_PERIPH_VIRT, + .pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS), + .length = BCM2835_PERIPH_SIZE, + .type = MT_DEVICE +}; + +static void __init bcm2835_map_io(void) +{ + iotable_init(&io_map, 1); +} + +static void __init bcm2835_init(void) +{ + int ret; + + bcm2835_setup_restart(); + if (wdt_regs) + pm_power_off = bcm2835_power_off; + + 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[] = { + "brcm,bcm2835", + NULL +}; + +DT_MACHINE_START(BCM2835, "BCM2835") + .map_io = bcm2835_map_io, + .init_irq = irqchip_init, + .init_machine = bcm2835_init, + .restart = bcm2835_restart, + .dt_compat = bcm2835_compat +MACHINE_END diff --git a/arch/arm/mach-bcm/kona.c b/arch/arm/mach-bcm/kona.c deleted file mode 100644 index 6939d9017f63..000000000000 --- a/arch/arm/mach-bcm/kona.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 Broadcom Corporation - * - * 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_address.h> -#include <asm/io.h> - -#include "kona.h" - -static void __iomem *watchdog_base; - -void bcm_kona_setup_restart(void) -{ - struct device_node *np_wdog; - - /* - * The assumption is that whoever calls bcm_kona_setup_restart() - * also needs a Kona Watchdog Timer entry in Device Tree, i.e. we - * report an error if the DT entry is missing. - */ - np_wdog = of_find_compatible_node(NULL, NULL, "brcm,kona-wdt"); - if (!np_wdog) { - pr_err("brcm,kona-wdt not found in DT, reboot disabled\n"); - return; - } - watchdog_base = of_iomap(np_wdog, 0); - WARN(!watchdog_base, "failed to map watchdog base"); - of_node_put(np_wdog); -} - -#define SECWDOG_OFFSET 0x00000000 -#define SECWDOG_RESERVED_MASK 0xE2000000 -#define SECWDOG_WD_LOAD_FLAG_MASK 0x10000000 -#define SECWDOG_EN_MASK 0x08000000 -#define SECWDOG_SRSTEN_MASK 0x04000000 -#define SECWDOG_CLKS_SHIFT 20 -#define SECWDOG_LOCK_SHIFT 0 - -void bcm_kona_restart(enum reboot_mode mode, const char *cmd) -{ - uint32_t val; - - if (!watchdog_base) - panic("Watchdog not mapped. Reboot failed.\n"); - - /* Enable watchdog2 with very short timeout. */ - val = readl(watchdog_base + SECWDOG_OFFSET); - val &= SECWDOG_RESERVED_MASK | SECWDOG_WD_LOAD_FLAG_MASK; - val |= SECWDOG_EN_MASK | SECWDOG_SRSTEN_MASK | - (0x8 << SECWDOG_CLKS_SHIFT) | - (0x8 << SECWDOG_LOCK_SHIFT); - writel(val, watchdog_base + SECWDOG_OFFSET); - - while (1) - ; -} diff --git a/arch/arm/mach-bcm/kona_l2_cache.c b/arch/arm/mach-bcm/kona_l2_cache.c new file mode 100644 index 000000000000..b31970377c20 --- /dev/null +++ b/arch/arm/mach-bcm/kona_l2_cache.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012-2014 Broadcom Corporation + * + * 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/init.h> +#include <linux/printk.h> +#include <asm/hardware/cache-l2x0.h> + +#include "bcm_kona_smc.h" + +void __init kona_l2_cache_init(void) +{ + unsigned int result; + int ret; + + ret = bcm_kona_smc_init(); + if (ret) { + pr_info("Secure API not available (%d). Skipping L2 init.\n", + ret); + return; + } + + result = bcm_kona_smc(SSAPI_ENABLE_L2_CACHE, 0, 0, 0, 0); + if (result != SEC_ROM_RET_OK) { + pr_err("Secure Monitor call failed (%u)! Skipping L2 init.\n", + result); + return; + } + + /* + * The aux_val and aux_mask have no effect since L2 cache is already + * enabled. Pass 0s for aux_val and 1s for aux_mask for default value. + */ + ret = l2x0_of_init(0, ~0); + if (ret) + pr_err("Couldn't enable L2 cache: %d\n", ret); +} diff --git a/arch/arm/mach-bcm/kona.h b/arch/arm/mach-bcm/kona_l2_cache.h index 291eca3e06ff..46f84a95ab1c 100644 --- a/arch/arm/mach-bcm/kona.h +++ b/arch/arm/mach-bcm/kona_l2_cache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Broadcom Corporation + * Copyright (C) 2012-2014 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -11,7 +11,8 @@ * GNU General Public License for more details. */ -#include <linux/reboot.h> - -void bcm_kona_setup_restart(void); -void bcm_kona_restart(enum reboot_mode mode, const char *cmd); +#ifdef CONFIG_ARCH_BCM_MOBILE_L2_CACHE +void kona_l2_cache_init(void); +#else +#define kona_l2_cache_init() ((void)0) +#endif |