Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84320e1a authored by Kapil Hali's avatar Kapil Hali Committed by Florian Fainelli
Browse files

ARM: BCM: Clean up SMP support for Broadcom Kona



These changes cleans up SMP implementaion for Broadcom's
Kona SoC which are required for handling SMP for iProc
family of SoCs at a single place for BCM NSP and BCM Kona.

Signed-off-by: default avatarKapil Hali <kapilh@broadcom.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
parent f4ce7eff
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@
		#address-cells = <1>;
		#size-cells = <0>;
		enable-method = "brcm,bcm11351-cpu-method";
		secondary-boot-reg = <0x3500417c>;

		cpu0: cpu@0 {
			device_type = "cpu";
@@ -42,6 +41,7 @@
		cpu1: cpu@1 {
			device_type = "cpu";
			compatible = "arm,cortex-a9";
			secondary-boot-reg = <0x3500417c>;
			reg = <1>;
		};
	};
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@
		#address-cells = <1>;
		#size-cells = <0>;
		enable-method = "brcm,bcm11351-cpu-method";
		secondary-boot-reg = <0x35004178>;

		cpu0: cpu@0 {
			device_type = "cpu";
@@ -42,6 +41,7 @@
		cpu1: cpu@1 {
			device_type = "cpu";
			compatible = "arm,cortex-a9";
			secondary-boot-reg = <0x35004178>;
			reg = <1>;
		};
	};
+54 −28
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 Broadcom Corporation
 * Copyright (C) 2014-2015 Broadcom Corporation
 * Copyright 2014 Linaro Limited
 *
 * This program is free software; you can redistribute it and/or
@@ -30,9 +30,10 @@

/* Name of device node property defining secondary boot register location */
#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;
static u32	secondary_boot_addr;

/*
 * Enable the Cortex A9 Snoop Control Unit
@@ -78,32 +79,55 @@ static int __init scu_a9_enable(void)
static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
{
	static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
	struct device_node *node;
	struct device_node *cpus_node = NULL;
	struct device_node *cpu_node = NULL;
	int ret;

	BUG_ON(secondary_boot);		/* We're called only once */

	/*
	 * 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.
	 */
	node = of_find_node_by_path("/cpus");
	BUG_ON(!node);
	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;
		}

		/*
	 * Our secondary enable method requires a "secondary-boot-reg"
	 * property to specify a register address used to request the
	 * ROM code boot a secondary code.  If we have any trouble
	 * getting this we fall back to uniprocessor mode.
		 * "secondary-boot-reg" property should be defined only
		 * for secondary cpu
		 */
	if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) {
		pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n",
			node->name);
		ret = -ENOENT;		/* Arrange to disable SMP */
		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
@@ -112,10 +136,11 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
	 */
	ret = scu_a9_enable();
out:
	of_node_put(node);
	of_node_put(cpu_node);
	of_node_put(cpus_node);

	if (ret) {
		/* Update the CPU present map to reflect uniprocessor mode */
		BUG_ON(ret != -ENOENT);
		pr_warn("disabling SMP\n");
		init_cpu_present(&only_cpu_0);
	}
@@ -139,7 +164,7 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
 * - Wait for the secondary boot register to be re-written, which
 *   indicates the secondary core has started.
 */
static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	void __iomem *boot_reg;
	phys_addr_t boot_func;
@@ -154,15 +179,16 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
		return -EINVAL;
	}

	if (!secondary_boot) {
	if (!secondary_boot_addr) {
		pr_err("required secondary boot register not specified\n");
		return -EINVAL;
	}

	boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32));
	boot_reg = ioremap_nocache(
			(phys_addr_t)secondary_boot_addr, sizeof(u32));
	if (!boot_reg) {
		pr_err("unable to map boot register for cpu %u\n", cpu_id);
		return -ENOSYS;
		return -ENOMEM;
	}

	/*
@@ -191,12 +217,12 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)

	pr_err("timeout waiting for cpu %u to start\n", cpu_id);

	return -ENOSYS;
	return -ENXIO;
}

static struct smp_operations bcm_smp_ops __initdata = {
	.smp_prepare_cpus	= bcm_smp_prepare_cpus,
	.smp_boot_secondary	= bcm_boot_secondary,
	.smp_boot_secondary	= kona_boot_secondary,
};
CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
			&bcm_smp_ops);