@@ -163,6 +163,7 @@ nodes to be present and contain the properties described below. "arm,cortex-r4" "arm,cortex-r5" "arm,cortex-r7"+ "brcm,brahma-b15" "faraday,fa526" "intel,sa110" "intel,sa1100"
@@ -15,6 +15,7 @@ Main node required properties: "arm,cortex-a9-gic" "arm,cortex-a7-gic" "arm,arm11mp-gic"+ "brcm,brahma-b15-gic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The type shall be a <u32> and the value shall be 3.
@@ -0,0 +1,95 @@+ARM Broadcom STB platforms Device Tree Bindings+-----------------------------------------------+Boards with Broadcom Brahma15 ARM-based BCMxxxx (generally BCM7xxx variants)+SoC shall have the following DT organization:++Required root node properties:+ - compatible: "brcm,bcm<chip_id>", "brcm,brcmstb"++example:+/ {+ #address-cells = <2>;+ #size-cells = <2>;+ model = "Broadcom STB (bcm7445)";+ compatible = "brcm,bcm7445", "brcm,brcmstb";++Further, syscon nodes that map platform-specific registers used for general+system control is required:++ - compatible: "brcm,bcm<chip_id>-sun-top-ctrl", "syscon"+ - compatible: "brcm,bcm<chip_id>-hif-cpubiuctrl", "syscon"+ - compatible: "brcm,bcm<chip_id>-hif-continuation", "syscon"++example:+ rdb {+ #address-cells = <1>;+ #size-cells = <1>;+ compatible = "simple-bus";+ ranges = <0 0x00 0xf0000000 0x1000000>;++ sun_top_ctrl: syscon at 404000 {+ compatible = "brcm,bcm7445-sun-top-ctrl", "syscon";+ reg = <0x404000 0x51c>;+ };++ hif_cpubiuctrl: syscon at 3e2400 {+ compatible = "brcm,bcm7445-hif-cpubiuctrl", "syscon";+ reg = <0x3e2400 0x5b4>;+ };++ hif_continuation: syscon at 452000 {+ compatible = "brcm,bcm7445-hif-continuation", "syscon";+ reg = <0x452000 0x100>;+ };+ };++Lastly, nodes that allow for support of SMP initialization and reboot are+required:++smpboot+-------+Required properties:++ - compatible+ The string "brcm,brcmstb-smpboot".++ - syscon-cpu+ A phandle / integer array property which lets the BSP know the location+ of certain CPU power-on registers.++ The layout of the property is as follows:+ o a phandle to the "hif_cpubiuctrl" syscon node+ o offset to the base CPU power zone register+ o offset to the base CPU reset register++ - syscon-cont+ A phandle pointing to the syscon node which describes the CPU boot+ continuation registers.+ o a phandle to the "hif_continuation" syscon node++example:+ smpboot {+ compatible = "brcm,brcmstb-smpboot";+ syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;+ syscon-cont = <&hif_continuation>;+ };++reboot+-------+Required properties++ - compatible+ The string property "brcm,brcmstb-reboot".++ - syscon+ A phandle / integer array that points to the syscon node which describes+ the general system reset registers.+ o a phandle to "sun_top_ctrl"+ o offset to the "reset source enable" register+ o offset to the "software master reset" register++example:+ reboot {+ compatible = "brcm,brcmstb-reboot";+ syscon = <&sun_top_ctrl 0x304 0x308>;+ };
@@ -0,0 +1,120 @@+/*+*Copyright(C)2013BroadcomCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicenseas+*publishedbytheFreeSoftwareFoundationversion2.+*+*Thisprogramisdistributed"as is"WITHOUTANYWARRANTYofany+*kind,whetherexpressorimplied;withouteventheimpliedwarranty+*ofMERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*/++#include<linux/device.h>+#include<linux/errno.h>+#include<linux/init.h>+#include<linux/io.h>+#include<linux/jiffies.h>+#include<linux/of_address.h>+#include<linux/of_irq.h>+#include<linux/of_platform.h>+#include<linux/platform_device.h>+#include<linux/printk.h>+#include<linux/reboot.h>+#include<linux/regmap.h>+#include<linux/smp.h>+#include<linux/mfd/syscon.h>++#include<asm/system_misc.h>++#define RESET_SOURCE_ENABLE_REG 1+#define SW_MASTER_RESET_REG 2++staticstructregmap*regmap;+staticu32rst_src_en;+staticu32sw_mstr_rst;++staticvoidbrcmstb_reboot(enumreboot_modemode,constchar*cmd)+{+intrc;+u32tmp;++rc=regmap_write(regmap,rst_src_en,1);+if(rc){+pr_err("failed to write rst_src_en (%d)\n",rc);+return;+}++rc=regmap_read(regmap,rst_src_en,&tmp);+if(rc){+pr_err("failed to read rst_src_en (%d)\n",rc);+return;+}++rc=regmap_write(regmap,sw_mstr_rst,1);+if(rc){+pr_err("failed to write sw_mstr_rst (%d)\n",rc);+return;+}++rc=regmap_read(regmap,sw_mstr_rst,&tmp);+if(rc){+pr_err("failed to read sw_mstr_rst (%d)\n",rc);+return;+}++while(1)+;+}++staticintbrcmstb_reboot_probe(structplatform_device*pdev)+{+intrc;+structdevice_node*np=pdev->dev.of_node;++regmap=syscon_regmap_lookup_by_phandle(np,"syscon");+if(IS_ERR(regmap)){+pr_err("failed to get syscon phandle\n");+return-EINVAL;+}++rc=of_property_read_u32_index(np,"syscon",RESET_SOURCE_ENABLE_REG,+&rst_src_en);+if(rc){+pr_err("can't get rst_src_en offset (%d)\n",rc);+return-EINVAL;+}++rc=of_property_read_u32_index(np,"syscon",SW_MASTER_RESET_REG,+&sw_mstr_rst);+if(rc){+pr_err("can't get sw_mstr_rst offset (%d)\n",rc);+return-EINVAL;+}++arm_pm_restart=brcmstb_reboot;++return0;+}++staticconststructof_device_idof_match[]={+{.compatible="brcm,brcmstb-reboot",},+{},+};++staticstructplatform_driverbrcmstb_reboot_driver={+.probe=brcmstb_reboot_probe,+.driver={+.name="brcmstb-reboot",+.owner=THIS_MODULE,+.of_match_table=of_match,+},+};++staticint__initbrcmstb_reboot_init(void)+{+returnplatform_driver_probe(&brcmstb_reboot_driver,+brcmstb_reboot_probe);+}+subsys_initcall(brcmstb_reboot_init);
@@ -0,0 +1,110 @@+/*+*Copyright(C)2013BroadcomCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicenseas+*publishedbytheFreeSoftwareFoundationversion2.+*+*Thisprogramisdistributed"as is"WITHOUTANYWARRANTYofany+*kind,whetherexpressorimplied;withouteventheimpliedwarranty+*ofMERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*/++#include<linux/clk-provider.h>+#include<linux/console.h>+#include<linux/clocksource.h>+#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/of_address.h>+#include<linux/of_irq.h>+#include<linux/of_platform.h>+#include<linux/platform_device.h>+#include<linux/printk.h>+#include<linux/smp.h>++#include<asm/cacheflush.h>+#include<asm/mach-types.h>+#include<asm/mach/arch.h>+#include<asm/mach/map.h>+#include<asm/mach/time.h>++#include"brcmstb.h"++/***********************************************************************+*STBCPU(mainapplicationprocessor)+***********************************************************************/++staticconstchar*brcmstb_match[]__initconst={+"brcm,bcm7445",+"brcm,brcmstb",+NULL+};++staticvoid__initbrcmstb_init_early(void)+{+add_preferred_console("ttyS",0,"115200");+}++/***********************************************************************+*SMPboot+***********************************************************************/++#ifdef CONFIG_SMP+staticDEFINE_SPINLOCK(boot_lock);++staticvoid__cpuinitbrcmstb_secondary_init(unsignedintcpu)+{+/*+*Synchronisewiththebootthread.+*/+spin_lock(&boot_lock);+spin_unlock(&boot_lock);+}++staticint__cpuinitbrcmstb_boot_secondary(unsignedintcpu,+structtask_struct*idle)+{+/*+*setsynchronisationstatebetweenthisbootprocessor+*andthesecondaryone+*/+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);++/*+*nowthesecondarycoreisstartingupletitrunits+*calibrations,thenwaitforittofinish+*/+spin_unlock(&boot_lock);++return0;+}++structsmp_operationsbrcmstb_smp_ops__initdata={+.smp_prepare_cpus=brcmstb_cpu_ctrl_setup,+.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+};+#endif++DT_MACHINE_START(BRCMSTB,"Broadcom STB (Flattened Device Tree)")+.dt_compat=brcmstb_match,+#ifdef CONFIG_SMP+.smp=smp_ops(brcmstb_smp_ops),+#endif+.init_early=brcmstb_init_early,+MACHINE_END
@@ -0,0 +1,334 @@+/*+*BroadcomSTBCPUhotplugsupportforARM+*+*Copyright(C)2013BroadcomCorporation+*+*Thisprogramisfreesoftware;youcanredistributeitand/or+*modifyitunderthetermsoftheGNUGeneralPublicLicenseas+*publishedbytheFreeSoftwareFoundationversion2.+*+*Thisprogramisdistributed"as is"WITHOUTANYWARRANTYofany+*kind,whetherexpressorimplied;withouteventheimpliedwarranty+*ofMERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe+*GNUGeneralPublicLicenseformoredetails.+*/++#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/of_address.h>+#include<linux/of_irq.h>+#include<linux/of_platform.h>+#include<linux/printk.h>+#include<linux/regmap.h>+#include<linux/smp.h>+#include<linux/mfd/syscon.h>++#include<asm/cacheflush.h>+#include<asm/mach-types.h>++#include"brcmstb.h"++enum{+ZONE_MAN_CLKEN_MASK=BIT(0),+ZONE_MAN_RESET_CNTL_MASK=BIT(1),+ZONE_MAN_MEM_PWR_MASK=BIT(4),+ZONE_RESERVED_1_MASK=BIT(5),+ZONE_MAN_ISO_CNTL_MASK=BIT(6),+ZONE_MANUAL_CONTROL_MASK=BIT(7),+ZONE_PWR_DN_REQ_MASK=BIT(9),+ZONE_PWR_UP_REQ_MASK=BIT(10),+ZONE_BLK_RST_ASSERT_MASK=BIT(10),+ZONE_PWR_OFF_STATE_MASK=BIT(26),+ZONE_PWR_ON_STATE_MASK=BIT(26),+ZONE_DPG_PWR_STATE_MASK=BIT(28),+ZONE_MEM_PWR_STATE_MASK=BIT(29),+ZONE_RESET_STATE_MASK=BIT(31),+};++staticvoid__iomem*cpubiuctrl_block;+staticvoid__iomem*hif_cont_block;+staticu32cpu0_pwr_zone_ctrl_reg;+staticu32cpu_rst_cfg_reg;+staticu32hif_cont_reg;+DEFINE_PER_CPU(int,per_cpu_sw_state);++staticvoid__iomem*pwr_ctrl_get_base(unsignedintcpu)+{+void__iomem*base=cpubiuctrl_block+cpu0_pwr_zone_ctrl_reg;+base+=(cpu*4);+returnbase;+}++staticu32pwr_ctrl_rd(unsignedintcpu)+{+void__iomem*base=pwr_ctrl_get_base(cpu);+returnreadl_relaxed(base);+}++staticvoidpwr_ctrl_wr(unsignedintcpu,u32val)+{+void__iomem*base=pwr_ctrl_get_base(cpu);+writel(val,base);+}++staticvoidcpu_rst_cfg_set(intcpu,intset)+{+u32val;+val=readl_relaxed(cpubiuctrl_block+cpu_rst_cfg_reg);+if(set)+val|=BIT(cpu);+else+val&=~BIT(cpu);+writel_relaxed(val,cpubiuctrl_block+cpu_rst_cfg_reg);+}++staticvoidcpu_set_boot_addr(intcpu,unsignedlongboot_addr)+{+constintreg_ofs=cpu*8;+writel_relaxed(0,hif_cont_block+hif_cont_reg+reg_ofs);+writel_relaxed(boot_addr,hif_cont_block+hif_cont_reg+4+reg_ofs);+}++voidbrcmstb_cpu_boot(unsignedintcpu)+{+pr_info("SMP: Booting CPU%d...\n",cpu);++/*+*settheresetvectortopointtothesecondary_startup+*routine+*/+cpu_set_boot_addr(cpu,virt_to_phys(brcmstb_secondary_startup));++flush_cache_all();++/* unhalt the cpu */+cpu_rst_cfg_set(cpu,0);+}++voidbrcmstb_cpu_power_on(unsignedintcpu)+{+/*+*Thesecondarycorespowerwascut,sowemustgothrough+*power-oninitialization.+*/+u32tmp;++pr_info("SMP: Powering up CPU%d...\n",cpu);++/* Request zone power up */+pwr_ctrl_wr(cpu,ZONE_PWR_UP_REQ_MASK);++/* Wait for the power up FSM to complete */+do{+tmp=pwr_ctrl_rd(cpu);+}while(!(tmp&ZONE_PWR_ON_STATE_MASK));++per_cpu(per_cpu_sw_state,cpu)=1;+}++intbrcmstb_cpu_get_power_state(unsignedintcpu)+{+inttmp=pwr_ctrl_rd(cpu);+return(tmp&ZONE_RESET_STATE_MASK)?0:1;+}++void__refbrcmstb_cpu_die(unsignedintcpu)+{+/* 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 */+);++/*+*Instructionbarriertoensurecacheisreallydisabledbefore+*cleaning/invalidatingthecaches+*/+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();++/*+*ClearACTLR.SMPbittopreventbroadcastTLBmessagesfromreaching+*thiscore+*/+__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();++per_cpu(per_cpu_sw_state,cpu)=0;++/*+*Finalfullbarriertoensureeverythingbeforethisinstructionhas+*quiesced.+*/+isb();+dsb();++/* Sit and wait to die */+wfi();++/* We should never get here... */+nop();+panic("Spurious interrupt on CPU %d received!\n",cpu);+}++intbrcmstb_cpu_kill(unsignedintcpu)+{+u32tmp;++pr_info("SMP: Powering down CPU%d...\n",cpu);++while(per_cpu(per_cpu_sw_state,cpu))+;++/* Program zone reset */+pwr_ctrl_wr(cpu,ZONE_RESET_STATE_MASK|ZONE_BLK_RST_ASSERT_MASK|+ZONE_PWR_DN_REQ_MASK);++/* Verify zone reset */+tmp=pwr_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_ctrl_rd(cpu);+}while(!(tmp&ZONE_PWR_OFF_STATE_MASK));++/* Settle-time from Broadcom-internal DVT reference code */+udelay(7);++/* Assert reset on the CPU */+cpu_rst_cfg_set(cpu,1);++return1;+}++staticint__initsetup_hifcpubiuctrl_regs(structdevice_node*np)+{+intrc=0;+char*name;+intindex;+structdevice_node*syscon_np=NULL;++name="syscon-cpu";++syscon_np=of_parse_phandle(np,name,0);+if(!syscon_np){+pr_err("can't find phandle %s\n",name);+rc=-EINVAL;+gotocleanup;+}++cpubiuctrl_block=of_iomap(syscon_np,0);+if(!cpubiuctrl_block){+pr_err("iomap failed for cpubiuctrl_block\n");+rc=-EINVAL;+gotocleanup;+}++index=1;+rc=of_property_read_u32_index(np,name,index,+&cpu0_pwr_zone_ctrl_reg);+if(rc){+pr_err("failed to read %d from %s property (%d)\n",index,name,+rc);+rc=-EINVAL;+gotocleanup;+}++index=2;+rc=of_property_read_u32_index(np,name,index,&cpu_rst_cfg_reg);+if(rc){+pr_err("failed to read %d from %s property (%d)\n",index,name,+rc);+rc=-EINVAL;+gotocleanup;+}++cleanup:+if(syscon_np)+of_node_put(syscon_np);++returnrc;+}++staticint__initsetup_hifcont_regs(structdevice_node*np)+{+intrc=0;+char*name;+structdevice_node*syscon_np=NULL;++name="syscon-cont";++syscon_np=of_parse_phandle(np,name,0);+if(!syscon_np){+pr_err("can't find phandle %s\n",name);+rc=-EINVAL;+gotocleanup;+}++hif_cont_block=of_iomap(syscon_np,0);+if(!hif_cont_block){+pr_err("iomap failed for hif_cont_block\n");+rc=-EINVAL;+gotocleanup;+}++/* offset is@top of hif_cont_block */+hif_cont_reg=0;++cleanup:+if(syscon_np)+of_node_put(syscon_np);++returnrc;+}++void__initbrcmstb_cpu_ctrl_setup(unsignedintmax_cpus)+{+intrc;+structdevice_node*np;+char*name;++name="brcm,brcmstb-smpboot";+np=of_find_compatible_node(NULL,NULL,name);+if(!np){+pr_err("can't find compatible node %s\n",name);+return;+}++rc=setup_hifcpubiuctrl_regs(np);+if(rc)+return;++rc=setup_hifcont_regs(np);+if(rc)+return;+}+
From: Marc Carino <hidden> Date: 2014-01-22 03:36:39
Add a sample DTS which will allow bootup of a board populated
with the BCM7445 chip.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/boot/dts/bcm7445.dts | 111 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/bcm7445.dts
Document the Broadcom Brahma B15 GIC implementation as compatible
with the ARM GIC standard.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
@@ -15,6 +15,7 @@ Main node required properties: "arm,cortex-a9-gic" "arm,cortex-a7-gic" "arm,arm11mp-gic"+ "brcm,brahma-b15-gic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The type shall be a <u32> and the value shall be 3.--
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
Patch #8 [1] of this series has the "compatible" string set exactly that way. I was
following the pattern seen in the other reference DTS files, where "arm,cortex-a15-gic" is
used as the fall-back.
Thanks,
Marc C
[1] https://lkml.org/lkml/2014/1/21/649
On 01/22/2014 02:40 PM, Florian Fainelli wrote:
Hi Marc,
2014/1/21 Marc Carino [off-list ref]:
quoted
Document the Broadcom Brahma B15 GIC implementation as compatible
with the ARM GIC standard.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
@@ -15,6 +15,7 @@ Main node required properties: "arm,cortex-a9-gic" "arm,cortex-a7-gic" "arm,arm11mp-gic"+ "brcm,brahma-b15-gic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The type shall be a <u32> and the value shall be 3.--
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
Patch #8 [1] of this series has the "compatible" string set exactly that way. I was
following the pattern seen in the other reference DTS files, where "arm,cortex-a15-gic" is
used as the fall-back.
Ah, I missed that, thanks! How about the CPU compatible property?
AFAIK it is only used by arch/arm/kernel/topology.c, I am not sure if
we have the exact same number to use as the "vanilla" Cortex-A15 here,
or if we should have another number match against "brcm,brahma-b15".
What do you think?
Document the Broadcom Brahma B15 GIC implementation as compatible
with the ARM GIC standard.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
@@ -15,6 +15,7 @@ Main node required properties: "arm,cortex-a9-gic" "arm,cortex-a7-gic" "arm,arm11mp-gic"+ "brcm,brahma-b15-gic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The type shall be a <u32> and the value shall be 3.--
Patch #8 [1] of this series has the "compatible" string set exactly that way. I was
following the pattern seen in the other reference DTS files, where "arm,cortex-a15-gic" is
used as the fall-back.
Ah, I missed that, thanks! How about the CPU compatible property?
AFAIK it is only used by arch/arm/kernel/topology.c, I am not sure if
we have the exact same number to use as the "vanilla" Cortex-A15 here,
or if we should have another number match against "brcm,brahma-b15".
What do you think?
I think we should let the code fall-through to use the "SCHED_POWER_SCALE" defaults for
now, and not have an entry in the efficiency table. There are currently no BCM7xxx
platforms architected with heterogeneous multi-processing or multiple disparate CPU
clusters (like big.LITTLE).
Thanks,
Marc
On 01/23/2014 10:26 AM, Florian Fainelli wrote:
Hi Marc,
2014/1/22 Marc C [off-list ref]:
quoted
Hi Florian,
quoted
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
Patch #8 [1] of this series has the "compatible" string set exactly that way. I was
following the pattern seen in the other reference DTS files, where "arm,cortex-a15-gic" is
used as the fall-back.
Ah, I missed that, thanks! How about the CPU compatible property?
AFAIK it is only used by arch/arm/kernel/topology.c, I am not sure if
we have the exact same number to use as the "vanilla" Cortex-A15 here,
or if we should have another number match against "brcm,brahma-b15".
What do you think?
Document the Broadcom Brahma B15 GIC implementation as compatible
with the ARM GIC standard.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Do not we also need to update drivers/irqchip/irq-gic.c to look for
this compatible property? Alternatively should the example DTS contain
the following:
compatible = "brcm,brahma-b15-gic", "arm,cortex-a15-gic"?
@@ -15,6 +15,7 @@ Main node required properties: "arm,cortex-a9-gic" "arm,cortex-a7-gic" "arm,arm11mp-gic"+ "brcm,brahma-b15-gic" - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The type shall be a <u32> and the value shall be 3.--
__CPUINIT is either going or gone by now. This should disappear.
quoted hunk
+
+ENTRY(brcmstb_secondary_startup)
+ /*
+ * Ensure CPU is in a sane state by disabling all IRQs and switching
+ * into SVC mode.
+ */
+ setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r0
+
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(brcmstb_secondary_startup)
CPU isn't guaranteed to be the physical CPU ID (MPIDR.Aff*). While it
almost certainly will be, we can't guarantee it in the face of a kexec,
for example.
You can use cpu_logical_map(cpu) to get the physical ID.
+ return base;
+}
+
+static u32 pwr_ctrl_rd(unsigned int cpu)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ return readl_relaxed(base);
+}
+
+static void pwr_ctrl_wr(unsigned int cpu, u32 val)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ writel(val, base);
+}
+
+static void cpu_rst_cfg_set(int cpu, int set)
+{
+ u32 val;
+ val = readl_relaxed(cpubiuctrl_block + cpu_rst_cfg_reg);
+ if (set)
+ val |= BIT(cpu);
+ else
+ val &= ~BIT(cpu);
Likewise here.
+ writel_relaxed(val, cpubiuctrl_block + cpu_rst_cfg_reg);
+}
+
+static void cpu_set_boot_addr(int cpu, unsigned long boot_addr)
+{
+ const int reg_ofs = cpu * 8;
And here.
+ writel_relaxed(0, hif_cont_block + hif_cont_reg + reg_ofs);
+ writel_relaxed(boot_addr, hif_cont_block + hif_cont_reg + 4 + reg_ofs);
+}
+
+void brcmstb_cpu_boot(unsigned int cpu)
+{
+ pr_info("SMP: Booting CPU%d...\n", cpu);
+
+ /*
+ * set the reset vector to point to the secondary_startup
+ * routine
+ */
+ cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
+
+ flush_cache_all();
Why? What does the new CPU need before its caches are coherent and up?
+
+ /* unhalt the cpu */
+ cpu_rst_cfg_set(cpu, 0);
+}
+
+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_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+
+ /* Wait for the power up FSM to complete */
+ do {
+ tmp = pwr_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+
+ per_cpu(per_cpu_sw_state, cpu) = 1;
+}
+
+int brcmstb_cpu_get_power_state(unsigned int cpu)
+{
+ int tmp = pwr_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 */
+ );
This is odd. Why not allow GCC to allocate the register?
+
+ /*
+ * Instruction barrier to ensure cache is really disabled before
+ * cleaning/invalidating the caches
+ */
+ isb();
I think you could use:
set_cr(get_cr() & ~CR_C))
Which would do all of the above (including the isb), and will get GCC to
allocate the register.
+
+ 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();
Surely you can use an output operand to get GCC to allocate the register
for you?
+
+ /* Disable all IRQs for this CPU */
+ arch_local_irq_disable();
+
+ per_cpu(per_cpu_sw_state, cpu) = 0;
Your caches are off at this point, so this could be going straight to
memory. Yet readers of this value aren't cleaning their caches before
reading this, so they could hit a stale cached copy.
+
+ /*
+ * 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();
Why the nop first?
+ panic("Spurious interrupt on CPU %d received!\n", cpu);
+}
+
+int brcmstb_cpu_kill(unsigned int cpu)
+{
+ u32 tmp;
+
+ pr_info("SMP: Powering down CPU%d...\n", cpu);
+
+ while (per_cpu(per_cpu_sw_state, cpu))
+ ;
As this was written to with caches disabled, the cached copy of the
value (which this is reading) could be stale. Surely you need to
clean+invalidate the line for this value each time you read it to give
it a chance to update?
+
+ /* Program zone reset */
+ pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
+ ZONE_PWR_DN_REQ_MASK);
+
+ /* Verify zone reset */
+ tmp = pwr_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_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+
+ /* Settle-time from Broadcom-internal DVT reference code */
+ udelay(7);
+
+ /* Assert reset on the CPU */
+ cpu_rst_cfg_set(cpu, 1);
+
+ return 1;
+}
+
+static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
+{
+ int rc = 0;
+ char *name;
+ int index;
+ struct device_node *syscon_np = NULL;
+
+ name = "syscon-cpu";
+
+ syscon_np = of_parse_phandle(np, name, 0);
+ if (!syscon_np) {
+ pr_err("can't find phandle %s\n", name);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ cpubiuctrl_block = of_iomap(syscon_np, 0);
+ if (!cpubiuctrl_block) {
+ pr_err("iomap failed for cpubiuctrl_block\n");
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ index = 1;
+ rc = of_property_read_u32_index(np, name, index,
+ &cpu0_pwr_zone_ctrl_reg);
The index variable seems rather pointless. Why not just use the value
in-place?
+ if (rc) {
+ pr_err("failed to read %d from %s property (%d)\n", index, name,
+ rc);
It might be better to state _what_ you're looking for (what does the
value represent?).
On the third posting, Will Deacon asked if the hwcap override was really
required [1]. Two postings later there's been no answer.
Is your CPUID_EXT_ISAR0 value wrong? If so, please add a comment to that
effect (as with __krait_proc_info).
Thanks,
Mark.
[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2014-January/225895.html
@@ -0,0 +1,95 @@+ARM Broadcom STB platforms Device Tree Bindings+-----------------------------------------------+Boards with Broadcom Brahma15 ARM-based BCMxxxx (generally BCM7xxx variants)+SoC shall have the following DT organization:++Required root node properties:+ - compatible: "brcm,bcm<chip_id>", "brcm,brcmstb"++example:+/ {+ #address-cells = <2>;+ #size-cells = <2>;+ model = "Broadcom STB (bcm7445)";+ compatible = "brcm,bcm7445", "brcm,brcmstb";++Further, syscon nodes that map platform-specific registers used for general+system control is required:++ - compatible: "brcm,bcm<chip_id>-sun-top-ctrl", "syscon"+ - compatible: "brcm,bcm<chip_id>-hif-cpubiuctrl", "syscon"+ - compatible: "brcm,bcm<chip_id>-hif-continuation", "syscon"++example:+ rdb {+ #address-cells = <1>;+ #size-cells = <1>;+ compatible = "simple-bus";+ ranges = <0 0x00 0xf0000000 0x1000000>;++ sun_top_ctrl: syscon at 404000 {+ compatible = "brcm,bcm7445-sun-top-ctrl", "syscon";+ reg = <0x404000 0x51c>;+ };++ hif_cpubiuctrl: syscon at 3e2400 {+ compatible = "brcm,bcm7445-hif-cpubiuctrl", "syscon";+ reg = <0x3e2400 0x5b4>;+ };++ hif_continuation: syscon at 452000 {+ compatible = "brcm,bcm7445-hif-continuation", "syscon";+ reg = <0x452000 0x100>;+ };+ };++Lastly, nodes that allow for support of SMP initialization and reboot are+required:++smpboot+-------+Required properties:++ - compatible+ The string "brcm,brcmstb-smpboot".++ - syscon-cpu+ A phandle / integer array property which lets the BSP know the location+ of certain CPU power-on registers.++ The layout of the property is as follows:+ o a phandle to the "hif_cpubiuctrl" syscon node+ o offset to the base CPU power zone register+ o offset to the base CPU reset register
How variable are these values?
+
+ - syscon-cont
+ A phandle pointing to the syscon node which describes the CPU boot
+ continuation registers.
+ o a phandle to the "hif_continuation" syscon node
+
+example:
+ smpboot {
+ compatible = "brcm,brcmstb-smpboot";
+ syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;
+ syscon-cont = <&hif_continuation>;
+ };
This looks odd. This doesn't seem like a device, but rather a grouping
of disparate devices used for a particular software purpose.
+
+reboot
+-------
+Required properties
+
+ - compatible
+ The string property "brcm,brcmstb-reboot".
+
+ - syscon
+ A phandle / integer array that points to the syscon node which describes
+ the general system reset registers.
+ o a phandle to "sun_top_ctrl"
+ o offset to the "reset source enable" register
+ o offset to the "software master reset" register
From: Mark Rutland <mark.rutland@arm.com> Date: 2014-01-24 11:09:49
On Wed, Jan 22, 2014 at 03:30:52AM +0000, Marc Carino wrote:
quoted hunk
Add a sample DTS which will allow bootup of a board populated
with the BCM7445 chip.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/boot/dts/bcm7445.dts | 111 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/bcm7445.dts
I think I can drop this. It was a holdover from our older kernels.
quoted
+ /*
+ * set the reset vector to point to the secondary_startup
+ * routine
+ */
+ cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
+
+ flush_cache_all();
Why? What does the new CPU need before its caches are coherent and up?
Absolutely nothing! I should be able to drop this as well.
Regarding the CPU power-down sequence, I'll review it and make sure it follows the
"Processor power domain" sequence in the A15 TRM. For any deviations, I'll double-check
with our H/W designers to ensure there aren't any magic requirements unaccounted for.
Thank you for taking a deep-dive into the code! I'll make the appropriate modifications
per your suggestions.
Regards,
Marc C
On 01/24/2014 02:14 AM, Mark Rutland wrote:
On Wed, Jan 22, 2014 at 03:30:45AM +0000, Marc Carino wrote:
quoted
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 <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/configs/multi_v7_defconfig | 1 +
arch/arm/mach-bcm/Kconfig | 14 ++
arch/arm/mach-bcm/Makefile | 4 +
arch/arm/mach-bcm/brcmstb.c | 110 ++++++++++++
arch/arm/mach-bcm/brcmstb.h | 38 ++++
arch/arm/mach-bcm/headsmp-brcmstb.S | 34 ++++
arch/arm/mach-bcm/hotplug-brcmstb.c | 334 +++++++++++++++++++++++++++++++++++
7 files changed, 535 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-bcm/brcmstb.c
create mode 100644 arch/arm/mach-bcm/brcmstb.h
create mode 100644 arch/arm/mach-bcm/headsmp-brcmstb.S
create mode 100644 arch/arm/mach-bcm/hotplug-brcmstb.c
__CPUINIT is either going or gone by now. This should disappear.
quoted
+
+ENTRY(brcmstb_secondary_startup)
+ /*
+ * Ensure CPU is in a sane state by disabling all IRQs and switching
+ * into SVC mode.
+ */
+ setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r0
+
+ bl v7_invalidate_l1
+ b secondary_startup
+ENDPROC(brcmstb_secondary_startup)
CPU isn't guaranteed to be the physical CPU ID (MPIDR.Aff*). While it
almost certainly will be, we can't guarantee it in the face of a kexec,
for example.
You can use cpu_logical_map(cpu) to get the physical ID.
quoted
+ return base;
+}
+
+static u32 pwr_ctrl_rd(unsigned int cpu)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ return readl_relaxed(base);
+}
+
+static void pwr_ctrl_wr(unsigned int cpu, u32 val)
+{
+ void __iomem *base = pwr_ctrl_get_base(cpu);
+ writel(val, base);
+}
+
+static void cpu_rst_cfg_set(int cpu, int set)
+{
+ u32 val;
+ val = readl_relaxed(cpubiuctrl_block + cpu_rst_cfg_reg);
+ if (set)
+ val |= BIT(cpu);
+ else
+ val &= ~BIT(cpu);
Likewise here.
quoted
+ writel_relaxed(val, cpubiuctrl_block + cpu_rst_cfg_reg);
+}
+
+static void cpu_set_boot_addr(int cpu, unsigned long boot_addr)
+{
+ const int reg_ofs = cpu * 8;
And here.
quoted
+ writel_relaxed(0, hif_cont_block + hif_cont_reg + reg_ofs);
+ writel_relaxed(boot_addr, hif_cont_block + hif_cont_reg + 4 + reg_ofs);
+}
+
+void brcmstb_cpu_boot(unsigned int cpu)
+{
+ pr_info("SMP: Booting CPU%d...\n", cpu);
+
+ /*
+ * set the reset vector to point to the secondary_startup
+ * routine
+ */
+ cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
+
+ flush_cache_all();
Why? What does the new CPU need before its caches are coherent and up?
quoted
+
+ /* unhalt the cpu */
+ cpu_rst_cfg_set(cpu, 0);
+}
+
+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_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
+
+ /* Wait for the power up FSM to complete */
+ do {
+ tmp = pwr_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
+
+ per_cpu(per_cpu_sw_state, cpu) = 1;
+}
+
+int brcmstb_cpu_get_power_state(unsigned int cpu)
+{
+ int tmp = pwr_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 */
+ );
This is odd. Why not allow GCC to allocate the register?
quoted
+
+ /*
+ * Instruction barrier to ensure cache is really disabled before
+ * cleaning/invalidating the caches
+ */
+ isb();
I think you could use:
set_cr(get_cr() & ~CR_C))
Which would do all of the above (including the isb), and will get GCC to
allocate the register.
quoted
+
+ 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();
Surely you can use an output operand to get GCC to allocate the register
for you?
quoted
+
+ /* Disable all IRQs for this CPU */
+ arch_local_irq_disable();
+
+ per_cpu(per_cpu_sw_state, cpu) = 0;
Your caches are off at this point, so this could be going straight to
memory. Yet readers of this value aren't cleaning their caches before
reading this, so they could hit a stale cached copy.
quoted
+
+ /*
+ * 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();
Why the nop first?
quoted
+ panic("Spurious interrupt on CPU %d received!\n", cpu);
+}
+
+int brcmstb_cpu_kill(unsigned int cpu)
+{
+ u32 tmp;
+
+ pr_info("SMP: Powering down CPU%d...\n", cpu);
+
+ while (per_cpu(per_cpu_sw_state, cpu))
+ ;
As this was written to with caches disabled, the cached copy of the
value (which this is reading) could be stale. Surely you need to
clean+invalidate the line for this value each time you read it to give
it a chance to update?
quoted
+
+ /* Program zone reset */
+ pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
+ ZONE_PWR_DN_REQ_MASK);
+
+ /* Verify zone reset */
+ tmp = pwr_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_ctrl_rd(cpu);
+ } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
+
+ /* Settle-time from Broadcom-internal DVT reference code */
+ udelay(7);
+
+ /* Assert reset on the CPU */
+ cpu_rst_cfg_set(cpu, 1);
+
+ return 1;
+}
+
+static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
+{
+ int rc = 0;
+ char *name;
+ int index;
+ struct device_node *syscon_np = NULL;
+
+ name = "syscon-cpu";
+
+ syscon_np = of_parse_phandle(np, name, 0);
+ if (!syscon_np) {
+ pr_err("can't find phandle %s\n", name);
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ cpubiuctrl_block = of_iomap(syscon_np, 0);
+ if (!cpubiuctrl_block) {
+ pr_err("iomap failed for cpubiuctrl_block\n");
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ index = 1;
+ rc = of_property_read_u32_index(np, name, index,
+ &cpu0_pwr_zone_ctrl_reg);
The index variable seems rather pointless. Why not just use the value
in-place?
quoted
+ if (rc) {
+ pr_err("failed to read %d from %s property (%d)\n", index, name,
+ rc);
It might be better to state _what_ you're looking for (what does the
value represent?).
+reboot
+-------
+Required properties
+
+ - compatible
+ The string property "brcm,brcmstb-reboot".
+
+ - syscon
+ A phandle / integer array that points to the syscon node which describes
+ the general system reset registers.
+ o a phandle to "sun_top_ctrl"
+ o offset to the "reset source enable" register
+ o offset to the "software master reset" register
How variable are these values?
Very much so. Future chips will have different register maps. Because of this, Arnd
suggested that we use 'syscon' and 'regmap' to alleviate this maintenance burden.
Sure. Our H/W designers unfortunately didn't put the boot and restart registers into a
logical grouping, or standard register interface. Instead, they're all over the place.
How do you suggest naming the nodes to indicate this?
Thanks,
Marc C
On 01/24/2014 03:03 AM, Mark Rutland wrote:
On Wed, Jan 22, 2014 at 03:30:50AM +0000, Marc Carino wrote:
quoted
Document the bindings that the Broadcom STB platform needs
for proper bootup.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
.../devicetree/bindings/arm/brcm-brcmstb.txt | 95 ++++++++++++++++++++
1 files changed, 95 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/brcm-brcmstb.txt
@@ -0,0 +1,95 @@+ARM Broadcom STB platforms Device Tree Bindings+-----------------------------------------------+Boards with Broadcom Brahma15 ARM-based BCMxxxx (generally BCM7xxx variants)+SoC shall have the following DT organization:++Required root node properties:+ - compatible: "brcm,bcm<chip_id>", "brcm,brcmstb"++example:+/ {+ #address-cells = <2>;+ #size-cells = <2>;+ model = "Broadcom STB (bcm7445)";+ compatible = "brcm,bcm7445", "brcm,brcmstb";++Further, syscon nodes that map platform-specific registers used for general+system control is required:++ - compatible: "brcm,bcm<chip_id>-sun-top-ctrl", "syscon"+ - compatible: "brcm,bcm<chip_id>-hif-cpubiuctrl", "syscon"+ - compatible: "brcm,bcm<chip_id>-hif-continuation", "syscon"++example:+ rdb {+ #address-cells = <1>;+ #size-cells = <1>;+ compatible = "simple-bus";+ ranges = <0 0x00 0xf0000000 0x1000000>;++ sun_top_ctrl: syscon at 404000 {+ compatible = "brcm,bcm7445-sun-top-ctrl", "syscon";+ reg = <0x404000 0x51c>;+ };++ hif_cpubiuctrl: syscon at 3e2400 {+ compatible = "brcm,bcm7445-hif-cpubiuctrl", "syscon";+ reg = <0x3e2400 0x5b4>;+ };++ hif_continuation: syscon at 452000 {+ compatible = "brcm,bcm7445-hif-continuation", "syscon";+ reg = <0x452000 0x100>;+ };+ };++Lastly, nodes that allow for support of SMP initialization and reboot are+required:++smpboot+-------+Required properties:++ - compatible+ The string "brcm,brcmstb-smpboot".++ - syscon-cpu+ A phandle / integer array property which lets the BSP know the location+ of certain CPU power-on registers.++ The layout of the property is as follows:+ o a phandle to the "hif_cpubiuctrl" syscon node+ o offset to the base CPU power zone register+ o offset to the base CPU reset register
How variable are these values?
quoted
+
+ - syscon-cont
+ A phandle pointing to the syscon node which describes the CPU boot
+ continuation registers.
+ o a phandle to the "hif_continuation" syscon node
+
+example:
+ smpboot {
+ compatible = "brcm,brcmstb-smpboot";
+ syscon-cpu = <&hif_cpubiuctrl 0x88 0x178>;
+ syscon-cont = <&hif_continuation>;
+ };
This looks odd. This doesn't seem like a device, but rather a grouping
of disparate devices used for a particular software purpose.
quoted
+
+reboot
+-------
+Required properties
+
+ - compatible
+ The string property "brcm,brcmstb-reboot".
+
+ - syscon
+ A phandle / integer array that points to the syscon node which describes
+ the general system reset registers.
+ o a phandle to "sun_top_ctrl"
+ o offset to the "reset source enable" register
+ o offset to the "software master reset" register
As I commented on v3 [1], these are contiguous and can be described with
a single entry:
memory {
device_type = "memory";
reg = <0x0 0x00000000 0x0 0xc0000000>;
};
Is there any reason to have three entries?
Oopsies, sorry for missing that.
On BCM7445 and derivatives, there are 3 memory controllers. For each memory controller,
the first 1GB of physical DRAM is mapped to:
* 0x00_0000_0000
* 0x00_4000_0000
* 0x00_8000_0000
The memory controllers aren't interleaved. So, it's possible for the SoC to have a
discontiguous memory-mapping, where a designer chooses not to populate physical DRAM in
the middle.
The 'reg' property was broken-up to have each chunk of memory given a dedicated memblock.
All that said, if you like, I can rework the patch as you've suggested.
Thanks,
Marc C
On 01/24/2014 03:09 AM, Mark Rutland wrote:
On Wed, Jan 22, 2014 at 03:30:52AM +0000, Marc Carino wrote:
quoted
Add a sample DTS which will allow bootup of a board populated
with the BCM7445 chip.
Signed-off-by: Marc Carino <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
arch/arm/boot/dts/bcm7445.dts | 111 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 111 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/boot/dts/bcm7445.dts