[PATCH 1/5] ARM: brcmstb: add infrastructure for ARM-based Broadcom STB SoCs

Marc C marc.ceeeee at gmail.com
Fri Nov 22 20:09:14 EST 2013


The BCM7xxx series of Broadcom SoCs are used primarily in set-top boxes.

This patch adds machine support for the ARM-based Broadcom SoCs.

Signed-off-by: Marc Carino <marc.ceeeee at gmail.com>
Acked-by: Florian Fainelli <f.fainelli at gmail.com>
---
 arch/arm/Kconfig                   |    2 +
 arch/arm/Kconfig.debug             |   16 +++-
 arch/arm/Makefile                  |    1 +
 arch/arm/configs/brcmstb_defconfig |  126 ++++++++++++++++++++++
 arch/arm/mach-brcmstb/Kconfig      |   24 ++++
 arch/arm/mach-brcmstb/Makefile     |   13 +++
 arch/arm/mach-brcmstb/common.c     |  153 ++++++++++++++++++++++++++
 arch/arm/mach-brcmstb/common.h     |   74 +++++++++++++
 arch/arm/mach-brcmstb/headsmp.S    |   33 ++++++
 arch/arm/mach-brcmstb/hotplug.c    |  208 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-brcmstb/platsmp.c    |   79 ++++++++++++++
 11 files changed, 728 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/configs/brcmstb_defconfig
 create mode 100644 arch/arm/mach-brcmstb/Kconfig
 create mode 100644 arch/arm/mach-brcmstb/Makefile
 create mode 100644 arch/arm/mach-brcmstb/common.c
 create mode 100644 arch/arm/mach-brcmstb/common.h
 create mode 100644 arch/arm/mach-brcmstb/headsmp.S
 create mode 100644 arch/arm/mach-brcmstb/hotplug.c
 create mode 100644 arch/arm/mach-brcmstb/platsmp.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1ad6fb6..62338a5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -930,6 +930,8 @@ source "arch/arm/mach-at91/Kconfig"

 source "arch/arm/mach-bcm/Kconfig"

+source "arch/arm/mach-brcmstb/Kconfig"
+
 source "arch/arm/mach-bcm2835/Kconfig"

 source "arch/arm/mach-clps711x/Kconfig"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 9762c84..e381b7a 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -94,6 +94,17 @@ choice
  depends on ARCH_BCM2835
  select DEBUG_UART_PL01X

+ config DEBUG_BRCMSTB_UART
+ bool "Use BRCMSTB UART for low-level debug"
+ depends on ARCH_BRCMSTB
+ select DEBUG_UART_8250
+ help
+  Say Y here if you want the debug print routines to direct
+  their output to the first serial port on these devices.
+
+  If you have a Broadcom STB chip and would like early print
+  messages to appear over the UART, select this option.
+
  config DEBUG_CLPS711X_UART1
  bool "Kernel low-level debugging messages via UART1"
  depends on ARCH_CLPS711X
@@ -951,6 +962,7 @@ config DEBUG_UART_PHYS
  default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
  default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
  default 0x20201000 if DEBUG_BCM2835
+ default 0xf0406b00 if DEBUG_BRCMSTB_UART
  default 0x40090000 if ARCH_LPC32XX
  default 0x40100000 if DEBUG_PXA_UART1
  default 0x42000000 if ARCH_GEMINI
@@ -990,6 +1002,7 @@ config DEBUG_UART_VIRT
  default 0xf0009000 if DEBUG_CNS3XXX
  default 0xf01fb000 if DEBUG_NOMADIK_UART
  default 0xf0201000 if DEBUG_BCM2835
+ default 0xfc406b00 if DEBUG_BRCMSTB_UART
  default 0xf11f1000 if ARCH_VERSATILE
  default 0xf1600000 if ARCH_INTEGRATOR
  default 0xf1c28000 if DEBUG_SUNXI_UART0
@@ -1052,7 +1065,8 @@ config DEBUG_UART_8250_WORD
  default y if DEBUG_PICOXCELL_UART || DEBUG_SOCFPGA_UART || \
  ARCH_KEYSTONE || \
  DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
- DEBUG_DAVINCI_DA8XX_UART2 || DEBUG_DAVINCI_TNETV107X_UART1
+ DEBUG_DAVINCI_DA8XX_UART2 || DEBUG_DAVINCI_TNETV107X_UART1 || \
+ DEBUG_BRCMSTB_UART

 config DEBUG_UART_8250_FLOW_CONTROL
  bool "Enable flow control for 8250 UART"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index db50b62..4691de2 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -147,6 +147,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 machine-$(CONFIG_ARCH_AT91) += at91
 machine-$(CONFIG_ARCH_BCM) += bcm
 machine-$(CONFIG_ARCH_BCM2835) += bcm2835
+machine-$(CONFIG_ARCH_BRCMSTB) += brcmstb
 machine-$(CONFIG_ARCH_CLPS711X) += clps711x
 machine-$(CONFIG_ARCH_CNS3XXX) += cns3xxx
 machine-$(CONFIG_ARCH_DAVINCI) += davinci
diff --git a/arch/arm/configs/brcmstb_defconfig
b/arch/arm/configs/brcmstb_defconfig
new file mode 100644
index 0000000..0390e6d
--- /dev/null
+++ b/arch/arm/configs/brcmstb_defconfig
@@ -0,0 +1,126 @@
+CONFIG_CROSS_COMPILE="arm-linux-"
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_BRCMSTB=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_PCI=y
+CONFIG_SMP=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUG=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_BRIDGE=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_GLUEBI=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_ATA=y
+CONFIG_NETDEVICES=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_USBNET=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO is not set
+# CONFIG_CONSOLE_TRANSLATIONS is not set
+# CONFIG_VT_CONSOLE is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+# CONFIG_HWMON is not set
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_EXT4_FS=y
+CONFIG_JBD2_DEBUG=y
+# CONFIG_DNOTIFY is not set
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/mach-brcmstb/Kconfig b/arch/arm/mach-brcmstb/Kconfig
new file mode 100644
index 0000000..3ed63ef
--- /dev/null
+++ b/arch/arm/mach-brcmstb/Kconfig
@@ -0,0 +1,24 @@
+config ARCH_BRCMSTB
+ bool "Broadcom BCM7XXX based boards" if ARCH_MULTI_V7
+ depends on MMU
+ select ARM_ARCH_TIMER
+ select ARM_GIC
+ select BRCMSTB
+ select MIGHT_HAVE_PCI
+ select HAVE_SMP
+ select USE_OF
+ select CPU_V7
+ select GENERIC_CLOCKEVENTS
+ help
+  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
+  chipset.
+
+  This enables support for Broadcom ARM-based set-top box chipsets,
+  including the 7445 family of chips.
+
+####################################################################
+# Hidden options
+#####################################################################
+
+config BCM7445
+ bool
diff --git a/arch/arm/mach-brcmstb/Makefile b/arch/arm/mach-brcmstb/Makefile
new file mode 100644
index 0000000..9297c22
--- /dev/null
+++ b/arch/arm/mach-brcmstb/Makefile
@@ -0,0 +1,13 @@
+#
+# 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.
+
+obj-$(CONFIG_ARCH_BRCMSTB) := common.o headsmp.o platsmp.o hotplug.o
diff --git a/arch/arm/mach-brcmstb/common.c b/arch/arm/mach-brcmstb/common.c
new file mode 100644
index 0000000..587eb01
--- /dev/null
+++ b/arch/arm/mach-brcmstb/common.c
@@ -0,0 +1,153 @@
+/*
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/console.h>
+#include <linux/clocksource.h>
+#include <linux/clk-provider.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+
+struct platform_regs brcm_plat_regs;
+
+/***********************************************************************
+ * STB CPU (main application processor)
+ ***********************************************************************/
+
+static struct map_desc brcmstb_io_map[] __initdata = {
+ {
+ .virtual = (unsigned long)BRCMSTB_PERIPH_VIRT,
+ .pfn     = __phys_to_pfn(BRCMSTB_PERIPH_PHYS),
+ .length  = BRCMSTB_PERIPH_LENGTH,
+ .type    = MT_DEVICE,
+ },
+};
+
+static const char *brcmstb_match[] __initdata = {
+ "brcm,brcmstb",
+ NULL
+};
+
+static struct node_reg sun_top_ctrl_regs[] __initdata = {
+ {"reset-source-enable-reg", &brcm_plat_regs.reset_source_enable_reg},
+ {"sw-master-reset-reg", &brcm_plat_regs.sw_master_reset_reg},
+ {NULL, NULL}
+};
+
+static struct node_reg cpu_biu_ctrl_regs[] __initdata = {
+ {"cpu-reset-config-reg", &brcm_plat_regs.cpu_reset_config_reg},
+ {"cpu0-pwr-zone-ctrl-reg", &brcm_plat_regs.cpu0_pwr_zone_ctrl_reg},
+ {NULL, NULL}
+};
+
+static struct node_reg hif_continuation_regs[] __initdata = {
+ {"stb-boot-hi-addr0-reg", &brcm_plat_regs.hif_continuation_regs_base},
+ {NULL, NULL}
+};
+
+static struct node_reg_block top_reg_blocks[] __initdata = {
+ {"brcm,brcmstb-sun-top-ctrl", sun_top_ctrl_regs},
+ {"brcm,brcmstb-cpu-biu-ctrl", cpu_biu_ctrl_regs},
+ {"brcm,brcmstb-hif-continuation", hif_continuation_regs},
+ {NULL, NULL}
+};
+
+static void __init brcmstb_map_io(void)
+{
+ iotable_init(brcmstb_io_map, ARRAY_SIZE(brcmstb_io_map));
+}
+
+static void brcmstb_restart(enum reboot_mode mode, const char *cmd)
+{
+ writel_relaxed(1, brcm_plat_regs.reset_source_enable_reg);
+ readl_relaxed(brcm_plat_regs.reset_source_enable_reg);
+
+ writel_relaxed(1, brcm_plat_regs.sw_master_reset_reg);
+ readl_relaxed(brcm_plat_regs.sw_master_reset_reg);
+
+ while (1)
+ ;
+}
+
+static void __init brcmstb_init_early(void)
+{
+ void __iomem *addr;
+ struct node_reg_block *block;
+
+ add_preferred_console("ttyS", 0, "115200");
+
+ addr = ioremap(BPHYSADDR(BCHP_IRQ0_IRQEN), sizeof(u32));
+ writel_relaxed(BCHP_IRQ0_IRQEN_uarta_irqen_MASK
+ | BCHP_IRQ0_IRQEN_uartb_irqen_MASK
+ | BCHP_IRQ0_IRQEN_uartc_irqen_MASK, addr);
+ iounmap(addr);
+
+ block = top_reg_blocks;
+ while (block->compatible) {
+ struct device_node *np;
+ struct node_reg *reg;
+
+ np = of_find_compatible_node(NULL, NULL, block->compatible);
+ if (!np)
+ panic("brcmstb: DT missing \"%s\" node\n",
+ block->compatible);
+
+ addr = of_iomap(np, 0);
+ if (!addr)
+ panic("brcmstb: iomap failure\n");
+
+ reg = block->regs;
+ while (reg->prop) {
+ u32 val;
+
+ if (!of_property_read_u32(np, reg->prop, &val))
+ *(reg->addr) = addr + val;
+ else
+ panic("brcmstb: node \"%s\" missing prop \"%s\"\n",
+ block->compatible, reg->prop);
+
+ reg++;
+ }
+
+ of_node_put(np);
+
+ block++;
+ }
+}
+
+static void __init brcmstb_init(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+DT_MACHINE_START(BRCMSTB, "Broadcom STB (Flattened Device Tree)")
+ .map_io = brcmstb_map_io,
+ .dt_compat = brcmstb_match,
+ .restart = brcmstb_restart,
+ .smp = smp_ops(brcmstb_smp_ops),
+ .init_early = brcmstb_init_early,
+ .init_machine = brcmstb_init
+MACHINE_END
diff --git a/arch/arm/mach-brcmstb/common.h b/arch/arm/mach-brcmstb/common.h
new file mode 100644
index 0000000..f44a10d
--- /dev/null
+++ b/arch/arm/mach-brcmstb/common.h
@@ -0,0 +1,74 @@
+/*
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __BRCMSTB_COMMON_H__
+#define __BRCMSTB_COMMON_H__
+
+#if !defined(__ASSEMBLY__)
+#include <linux/smp.h>
+#endif
+
+#define BRCMSTB_PERIPH_VIRT 0xfc000000
+#define BRCMSTB_PERIPH_PHYS 0xf0000000
+#define BRCMSTB_PERIPH_LENGTH 0x02000000
+
+#define BVIRTADDR(x) (BRCMSTB_PERIPH_VIRT + ((x) & 0x0fffffff))
+#define BPHYSADDR(x) ((x) + BRCMSTB_PERIPH_PHYS)
+
+#define BCHP_UARTA_REG_START 0x00406b00
+
+#define BCHP_IRQ0_IRQEN 0x00406780
+#define BCHP_IRQ0_IRQEN_uarta_irqen_MASK 0x00010000
+#define BCHP_IRQ0_IRQEN_uartb_irqen_MASK 0x00020000
+#define BCHP_IRQ0_IRQEN_uartc_irqen_MASK 0x00040000
+
+#if !defined(__ASSEMBLY__)
+
+extern void brcmstb_secondary_startup(void);
+extern void brcmstb_cpu_boot(unsigned int cpu);
+extern void brcmstb_cpu_power_on(unsigned int cpu);
+extern int brcmstb_cpu_get_power_state(unsigned int cpu);
+extern struct smp_operations brcmstb_smp_ops;
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern void brcmstb_cpu_die(unsigned int cpu);
+extern int brcmstb_cpu_kill(unsigned int cpu);
+#endif
+
+struct node_reg {
+ const char *prop;
+ void __iomem **addr;
+};
+
+struct node_reg_block {
+ const char *compatible;
+ struct node_reg *regs;
+};
+
+struct platform_regs {
+ void __iomem *cpu_reset_config_reg;
+ void __iomem *cpu0_pwr_zone_ctrl_reg;
+ void __iomem *hif_continuation_regs_base;
+ void __iomem *reset_source_enable_reg;
+ void __iomem *sw_master_reset_reg;
+};
+
+extern struct platform_regs brcm_plat_regs;
+
+#endif
+
+#endif /* __BRCMSTB_COMMON_H__ */
diff --git a/arch/arm/mach-brcmstb/headsmp.S b/arch/arm/mach-brcmstb/headsmp.S
new file mode 100644
index 0000000..1d01358
--- /dev/null
+++ b/arch/arm/mach-brcmstb/headsmp.S
@@ -0,0 +1,33 @@
+/*
+ * SMP boot code for secondary CPUs
+ * Based on arch/arm/mach-tegra/headsmp.S
+ *
+ * Copyright (C) 2010 NVIDIA, Inc.
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+        .section ".text.head", "ax"
+ __CPUINIT
+
+ENTRY(brcmstb_secondary_startup)
+        mov     r0, #0xd3
+        msr     cpsr_fsxc, r0
+        bl      v7_invalidate_l1
+        b       secondary_startup
+ENDPROC(brcmstb_secondary_startup)
diff --git a/arch/arm/mach-brcmstb/hotplug.c b/arch/arm/mach-brcmstb/hotplug.c
new file mode 100644
index 0000000..edfadc2
--- /dev/null
+++ b/arch/arm/mach-brcmstb/hotplug.c
@@ -0,0 +1,208 @@
+/*
+ * Broadcom STB CPU hotplug support for ARM
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/printk.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+
+#include "common.h"
+
+#define ZONE_PWR_DN_REQ_MASK 0x00000200
+#define ZONE_PWR_UP_REQ_MASK 0x00000400
+#define ZONE_BLK_RST_ASSERT_MASK 0x00001000
+#define ZONE_PWR_OFF_STATE_MASK 0x02000000
+#define ZONE_PWR_ON_STATE_MASK 0x04000000
+#define ZONE_RESET_STATE_MASK 0x80000000
+
+static void __iomem *pwr_zone_ctrl_get_base(unsigned int cpu)
+{
+ void __iomem *base = brcm_plat_regs.cpu0_pwr_zone_ctrl_reg;
+ base += (cpu * 4);
+ return base;
+}
+
+static u32 pwr_zone_ctrl_rd(unsigned int cpu)
+{
+ void __iomem *base = pwr_zone_ctrl_get_base(cpu);
+ return readl_relaxed(base);
+}
+
+static void pwr_zone_ctrl_wr(unsigned int cpu, u32 val)
+{
+ void __iomem *base = pwr_zone_ctrl_get_base(cpu);
+ writel_relaxed(val, base);
+ dsb();
+}
+
+void brcmstb_cpu_boot(unsigned int cpu)
+{
+ unsigned long boot_vector;
+ const int reg_ofs = cpu * 8;
+ u32 val;
+
+ pr_info("SMP: Booting CPU%d...\n", cpu);
+
+ /*
+ * set the reset vector to point to the secondary_startup
+ * routine
+ */
+ boot_vector = virt_to_phys(brcmstb_secondary_startup);
+ writel_relaxed(0, brcm_plat_regs.hif_continuation_regs_base + reg_ofs);
+ writel_relaxed(boot_vector, brcm_plat_regs.hif_continuation_regs_base
+ + 4 + reg_ofs);
+
+ smp_wmb();
+ flush_cache_all();
+
+ /* unhalt the cpu */
+ val = readl_relaxed(brcm_plat_regs.cpu_reset_config_reg);
+ val &= ~BIT(cpu);
+ writel_relaxed(val, brcm_plat_regs.cpu_reset_config_reg);
+}
+
+void brcmstb_cpu_power_on(unsigned int cpu)
+{
+ /*
+ * The secondary cores power was cut, so we must go through
+ * power-on initialization.
+ */
+ u32 tmp;
+
+ pr_info("SMP: Powering up CPU%d...\n", cpu);
+
+ /* Request zone power up */
+ pwr_zone_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+
+ /* Wait for the power up FSM to complete */
+ do {
+ tmp = pwr_zone_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+}
+
+int brcmstb_cpu_get_power_state(unsigned int cpu)
+{
+ int tmp = pwr_zone_ctrl_rd(cpu);
+ return (tmp & ZONE_RESET_STATE_MASK) ? 0 : 1;
+}
+
+void __ref brcmstb_cpu_die(unsigned int cpu)
+{
+ /* Derived from misc_bpcm_arm.c */
+
+ /* Clear SCTLR.C bit */
+ __asm__(
+ "mrc p15, 0, r0, c1, c0, 0\n"
+ "bic r0, r0, #(1 << 2)\n"
+ "mcr p15, 0, r0, c1, c0, 0\n"
+ : /* no output */
+ : /* no input */
+ : "r0" /* clobber r0 */
+ );
+
+ /*
+ * Instruction barrier to ensure cache is really disabled before
+ * cleaning/invalidating the caches
+ */
+ isb();
+
+ flush_cache_all();
+
+ /* Invalidate all instruction caches to PoU (ICIALLU) */
+ /* Data sync. barrier to ensure caches have emptied out */
+ __asm__("mcr p15, 0, r0, c7, c5, 0\n" : : : "r0");
+ dsb();
+
+ /*
+ * Clear ACTLR.SMP bit to prevent broadcast TLB messages from reaching
+ * this core
+ */
+ __asm__(
+ "mrc p15, 0, r0, c1, c0, 1\n"
+ "bic r0, r0, #(1 << 6)\n"
+ "mcr p15, 0, r0, c1, c0, 1\n"
+ : /* no output */
+ : /* no input */
+ : "r0" /* clobber r0 */
+ );
+
+ /* Disable all IRQs for this CPU */
+ arch_local_irq_disable();
+
+ /*
+ * Final full barrier to ensure everything before this instruction has
+ * quiesced.
+ */
+ isb();
+ dsb();
+
+ /* Sit and wait to die */
+ wfi();
+
+ /* We should never get here... */
+ nop();
+ panic("Spurious interrupt on CPU %d received!\n", cpu);
+}
+
+static void busy_wait(int i)
+{
+ while (--i != 0)
+ nop();
+}
+
+int brcmstb_cpu_kill(unsigned int cpu)
+{
+ u32 tmp;
+ u32 val;
+
+ pr_info("SMP: Powering down CPU%d...\n", cpu);
+
+ /* Program zone reset */
+ pwr_zone_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
+      ZONE_PWR_DN_REQ_MASK);
+
+ /* Verify zone reset */
+ tmp = pwr_zone_ctrl_rd(cpu);
+ if (!(tmp & ZONE_RESET_STATE_MASK))
+ pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
+ __func__, cpu);
+
+ /* Wait for power down */
+ do {
+ tmp = pwr_zone_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+
+ /* Magic delay from misc_bpcm_arm.c */
+ busy_wait(10000);
+
+ /* Assert reset on the CPU */
+ val = readl_relaxed(brcm_plat_regs.cpu_reset_config_reg);
+ val |= BIT(cpu);
+ writel_relaxed(val, brcm_plat_regs.cpu_reset_config_reg);
+
+ return 1;
+}
+
diff --git a/arch/arm/mach-brcmstb/platsmp.c b/arch/arm/mach-brcmstb/platsmp.c
new file mode 100644
index 0000000..ea5db15
--- /dev/null
+++ b/arch/arm/mach-brcmstb/platsmp.c
@@ -0,0 +1,79 @@
+/*
+ * Broadcom STB SMP support for ARM
+ * Based on arch/arm/mach-tegra/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ *  Copyright (C) 2009 Palm
+ *  All Rights Reserved
+ *
+ *  Copyright (C) 2013 Broadcom Corporation
+ *  All Rights Reserved
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/printk.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/mach-types.h>
+
+#include "common.h"
+
+static DEFINE_SPINLOCK(boot_lock);
+
+/***********************************************************************
+ * SMP boot
+ ***********************************************************************/
+
+static void __cpuinit brcmstb_secondary_init(unsigned int cpu)
+{
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+static int __cpuinit brcmstb_boot_secondary(unsigned int cpu,
+    struct task_struct *idle)
+{
+ /*
+ * set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ /* Bring up power to the core if necessary */
+ if (brcmstb_cpu_get_power_state(cpu) == 0)
+ brcmstb_cpu_power_on(cpu);
+
+ brcmstb_cpu_boot(cpu);
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+
+ return 0;
+}
+
+struct smp_operations brcmstb_smp_ops __initdata = {
+ .smp_secondary_init = brcmstb_secondary_init,
+ .smp_boot_secondary = brcmstb_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+ .cpu_kill = brcmstb_cpu_kill,
+ .cpu_die = brcmstb_cpu_die,
+#endif
+};
-- 
1.7.1



More information about the linux-arm-kernel mailing list