Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / arch / arm / mach-bcmbca / bcm6878 / cpu.c
diff --git a/arch/arm/mach-bcmbca/bcm6878/cpu.c b/arch/arm/mach-bcmbca/bcm6878/cpu.c
new file mode 100644 (file)
index 0000000..521335e
--- /dev/null
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 Broadcom Ltd.
+ */
+
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/ddr.h>
+#include <spl.h>
+#if defined(CONFIG_BCMBCA_PMC)
+#include "pmc_drv.h"
+#include "asm/arch/BPCM.h"
+#include "clk_rst.h"
+#endif
+
+#if defined(CONFIG_TPL_BUILD)
+#define CLOCK_RESET_XTAL_CONTROL_BIT_PD_DRV (2)
+#define CLOCK_RESET_XTAL_CONTROL_BIT_PWRON  (27)
+#define CLOCK_RESET_XTAL_CONTROL2_BIT_PD    (0)
+
+static void disable_xtal_clk(void)
+{
+    uint32_t data;
+    int ret;
+
+    ret = ReadBPCMRegister(PMB_ADDR_CHIP_CLKRST,
+                   CLKRSTBPCMRegOffset(pmd_xtal_cntl), &data);
+
+    data |= (0x1 << CLOCK_RESET_XTAL_CONTROL_BIT_PD_DRV);
+    data &= ~(0x1 << CLOCK_RESET_XTAL_CONTROL_BIT_PWRON);
+
+    ret |= WriteBPCMRegister(PMB_ADDR_CHIP_CLKRST,
+                CLKRSTBPCMRegOffset(pmd_xtal_cntl), data);
+
+    ret |= ReadBPCMRegister(PMB_ADDR_CHIP_CLKRST,
+                 CLKRSTBPCMRegOffset(pmd_xtal_cntl2), &data);
+
+    data |= (0x1 << CLOCK_RESET_XTAL_CONTROL2_BIT_PD);
+
+    ret |= WriteBPCMRegister(PMB_ADDR_CHIP_CLKRST,
+                CLKRSTBPCMRegOffset(pmd_xtal_cntl2), data);
+
+    if (ret)
+        printf("Failed to disable xtal clk\n");
+}
+#endif
+
+int arch_cpu_init(void)
+{
+#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
+    u32 frq = COUNTER_FREQUENCY;
+
+    // set arch timer frequency
+    asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (frq));
+
+    // enable system timer
+    BIUCFG->TSO_CNTCR |= 1;
+
+    /* enable unalgined access */    
+    set_cr(get_cr() & ~CR_A);
+#endif
+
+    return 0;
+}
+
+void boost_cpu_clock(void)
+{
+    unsigned int clk_index, cpu_clock;
+    int stat;
+    PLL_CTRL_REG ctrl_reg;
+
+    if ( !bcm_otp_get_cpu_clk(&clk_index) )
+    {
+        switch (clk_index) {
+            case 0:
+            case 1:
+                cpu_clock = 1200;
+                break;
+            case 2:
+                cpu_clock = 800;
+                break;
+            default:
+                cpu_clock = 0;
+            }
+    }
+    else
+        printf("ERROR: failed to read cpu clock\n");
+
+    stat = ReadBPCMRegister(PMB_ADDR_BIU_PLL, PLLBPCMRegOffset(resets), &ctrl_reg.Reg32);
+    ctrl_reg.Bits.byp_wait = 0;
+    stat |= WriteBPCMRegister(PMB_ADDR_BIU_PLL, PLLBPCMRegOffset(resets), ctrl_reg.Reg32);
+
+    if (stat)
+        printf("ERROR: failed to set cpu fast clock\n");
+    else
+        printf("CPU Clock: %dMHz\n", cpu_clock);
+
+    disable_xtal_clk();
+}
+
+#if !defined(CONFIG_SPL_BUILD)
+void print_chipinfo(void)
+{
+       char *mktname = NULL;
+       unsigned int cpu_speed, rdp_speed;
+       unsigned int chipId = (PERF->RevID & CHIP_ID_MASK) >> CHIP_ID_SHIFT;
+       unsigned int revId = PERF->RevID & REV_ID_MASK;
+
+       switch (chipId) {
+       case(0x6878A):
+               mktname = "68782G";
+               break;
+       case(0x68789):
+               mktname = "68781H";
+               break;
+       case(0x6878C):
+               mktname = "68789";
+               break;
+       case(0x6878E):
+               mktname = "68782N";
+               break;
+       case(0x6878D):
+               mktname = "68781G";
+               break;
+       default:
+               mktname = NULL;
+       }
+
+       if (mktname == NULL)
+               printf("Chip ID: BCM%X_%X\n",chipId,revId);
+       else
+               printf("Chip ID: BCM%s_%X\n",mktname,revId);
+
+       pll_ch_freq_get(PMB_ADDR_BIU_PLL, 0, &cpu_speed);
+       get_rdp_freq(&rdp_speed);
+
+       printf("ARM Cortex A7 Dual Core: %dMHz\n",cpu_speed);
+       printf("RDP: %dMHz\n",rdp_speed);
+}
+#endif
+
+int bcmbca_get_boot_device(void)
+{
+       if ((MISC->miscStrapBus&MISC_STRAP_BUS_BOOT_SEL_NAND_MASK) == MISC_STRAP_BUS_BOOT_NAND)
+               return BOOT_DEVICE_NAND;
+
+       if ((MISC->miscStrapBus&MISC_STRAP_BUS_BOOT_SEL_MASK) == MISC_STRAP_BUS_BOOT_SPI_NAND)
+               return BOOT_DEVICE_SPI;
+
+       printf("Error: boot_sel straps are not set correctly\n");
+
+       return BOOT_DEVICE_NONE;
+}
+
+#if !defined(CONFIG_TPL_ATF)
+void boot_secondary_cpu(unsigned long vector)
+{
+    uint32_t cpu = 1;
+    uint32_t nr_cpus = 2;
+    ARM_CONTROL_REG ctrl_reg;
+    uint64_t rvbar = vector;
+    int stat;
+
+    printf("boot secondary cpu from 0x%lx\n", vector);
+
+    *(volatile uint32_t*)(BOOTLUT_BASE+0x20) = vector;
+
+    BIUCFG->cluster[0].rvbar_addr[cpu] = rvbar;
+
+    stat = PowerOnDevice(PMB_ADDR_ORION_CPU0 + cpu);
+        if (stat != kPMC_NO_ERROR)
+            printf("failed to power on secondary cpu %d - sts %d\n", cpu, stat);
+
+    while (cpu < nr_cpus) 
+    {
+        stat = ReadBPCMRegister(PMB_ADDR_BIU_BPCM, ARMBPCMRegOffset(arm_control), &ctrl_reg.Reg32);
+        ctrl_reg.Bits.cpu_reset_n &= ~(0x1 << cpu);
+        stat |= WriteBPCMRegister(PMB_ADDR_BIU_BPCM, ARMBPCMRegOffset(arm_control), ctrl_reg.Reg32);
+        if (stat != kPMC_NO_ERROR)
+            printf("failed to boot secondary cpu %d - sts %d\n", cpu, stat);
+        cpu++;
+    }
+
+    return;
+}
+#endif
+