[PATCH v6 2/5] ARM: BCM: Clean up SMP support for Broadcom Kona

Rob Herring robh at kernel.org
Mon Dec 7 06:23:06 PST 2015


On Sat, Dec 05, 2015 at 06:53:41AM -0500, Kapil Hali wrote:
> 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: Kapil Hali <kapilh at broadcom.com>
> ---
>  .../bindings/arm/bcm/brcm,bcm11351-cpu-method.txt  | 12 ++--
>  arch/arm/boot/dts/bcm11351.dtsi                    |  4 +-
>  arch/arm/boot/dts/bcm21664.dtsi                    |  4 +-

For the bindings:

Acked-by: Rob Herring <robh at kernel.org>

>  arch/arm/mach-bcm/kona_smp.c                       | 82 ++++++++++++++--------
>  4 files changed, 64 insertions(+), 38 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt
> index 8240c02..3c5fe4b 100644
> --- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt
> +++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt
> @@ -1,17 +1,17 @@
>  Broadcom Kona Family CPU Enable Method
>  --------------------------------------
>  This binding defines the enable method used for starting secondary
> -CPUs in the following Broadcom SoCs:
> +CPU in the following Broadcom SoCs:
>    BCM11130, BCM11140, BCM11351, BCM28145, BCM28155, BCM21664
>  
>  The enable method is specified by defining the following required
> -properties in the "cpus" device tree node:
> +properties in the corresponding secondary "cpu" device tree node:
>    - enable-method = "brcm,bcm11351-cpu-method";
>    - secondary-boot-reg = <...>;
>  
>  The secondary-boot-reg property is a u32 value that specifies the
> -physical address of the register used to request the ROM holding pen
> -code release a secondary CPU.  The value written to the register is
> +physical address of the register used to request the ROM code
> +release a secondary CPU.  The value written to the register is
>  formed by encoding the target CPU id into the low bits of the
>  physical start address it should jump to.
>  
> @@ -19,8 +19,6 @@ Example:
>  	cpus {
>  		#address-cells = <1>;
>  		#size-cells = <0>;
> -		enable-method = "brcm,bcm11351-cpu-method";
> -		secondary-boot-reg = <0x3500417c>;
>  
>  		cpu0: cpu at 0 {
>  			device_type = "cpu";
> @@ -31,6 +29,8 @@ Example:
>  		cpu1: cpu at 1 {
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a9";
> +			enable-method = "brcm,bcm11351-cpu-method";
> +			secondary-boot-reg = <0x3500417c>;
>  			reg = <1>;
>  		};
>  	};
> diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
> index 2ddaa51..18045c3 100644
> --- a/arch/arm/boot/dts/bcm11351.dtsi
> +++ b/arch/arm/boot/dts/bcm11351.dtsi
> @@ -30,8 +30,6 @@
>  	cpus {
>  		#address-cells = <1>;
>  		#size-cells = <0>;
> -		enable-method = "brcm,bcm11351-cpu-method";
> -		secondary-boot-reg = <0x3500417c>;
>  
>  		cpu0: cpu at 0 {
>  			device_type = "cpu";
> @@ -42,6 +40,8 @@
>  		cpu1: cpu at 1 {
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a9";
> +			enable-method = "brcm,bcm11351-cpu-method";
> +			secondary-boot-reg = <0x3500417c>;
>  			reg = <1>;
>  		};
>  	};
> diff --git a/arch/arm/boot/dts/bcm21664.dtsi b/arch/arm/boot/dts/bcm21664.dtsi
> index 2016b72..6dde95f 100644
> --- a/arch/arm/boot/dts/bcm21664.dtsi
> +++ b/arch/arm/boot/dts/bcm21664.dtsi
> @@ -30,8 +30,6 @@
>         cpus {
>  		#address-cells = <1>;
>  		#size-cells = <0>;
> -		enable-method = "brcm,bcm11351-cpu-method";
> -		secondary-boot-reg = <0x35004178>;
>  
>  		cpu0: cpu at 0 {
>  			device_type = "cpu";
> @@ -42,6 +40,8 @@
>  		cpu1: cpu at 1 {
>  			device_type = "cpu";
>  			compatible = "arm,cortex-a9";
> +			enable-method = "brcm,bcm11351-cpu-method";
> +			secondary-boot-reg = <0x35004178>;
>  			reg = <1>;
>  		};
>  	};
> diff --git a/arch/arm/mach-bcm/kona_smp.c b/arch/arm/mach-bcm/kona_smp.c
> index 66a0465..15af781 100644
> --- a/arch/arm/mach-bcm/kona_smp.c
> +++ b/arch/arm/mach-bcm/kona_smp.c
> @@ -1,5 +1,5 @@
>  /*
> - * 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,44 +79,68 @@ 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);
> -
> -	/*
> -	 * 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.
> -	 */
> -	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 */
> -		goto out;
> +	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
> +	 * 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(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 @@ out:
>   * - 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);
> -- 
> 2.1.0
> 



More information about the linux-arm-kernel mailing list