]> git.karo-electronics.de Git - karo-tx-uboot.git/commitdiff
arm: iproc: Initial commit of iproc architecture code
authorScott Branden <sbranden@broadcom.com>
Mon, 11 Aug 2014 20:58:22 +0000 (13:58 -0700)
committerTom Rini <trini@ti.com>
Sat, 30 Aug 2014 11:46:40 +0000 (07:46 -0400)
The iproc architecture code is present in several Broadcom
chip architectures, including Cygnus and NSP.

Signed-off-by: Scott Branden <sbranden@broadcom.com>
Signed-off-by: Steve Rae <srae@broadcom.com>
arch/arm/cpu/armv7/Makefile
arch/arm/cpu/armv7/iproc-common/Makefile [new file with mode: 0644]
arch/arm/cpu/armv7/iproc-common/armpll.c [new file with mode: 0644]
arch/arm/cpu/armv7/iproc-common/hwinit-common.c [new file with mode: 0644]
arch/arm/cpu/armv7/iproc-common/timer.c [new file with mode: 0644]
arch/arm/include/asm/iproc-common/armpll.h [new file with mode: 0644]
arch/arm/include/asm/iproc-common/sysmap.h [new file with mode: 0644]
arch/arm/include/asm/iproc-common/timer.h [new file with mode: 0644]

index 703ce8c640aa09c85d53e40dae55371e9bd512ac..afeed4dad84bdddd4557604d6978549879e2dc59 100644 (file)
@@ -28,6 +28,7 @@ ifneq ($(CONFIG_ARMV7_PSCI),)
 obj-y  += psci.o
 endif
 
+obj-$(CONFIG_IPROC) += iproc-common/
 obj-$(CONFIG_KONA) += kona-common/
 obj-$(CONFIG_OMAP_COMMON) += omap-common/
 obj-$(CONFIG_SYS_ARCH_TIMER) += arch_timer.o
diff --git a/arch/arm/cpu/armv7/iproc-common/Makefile b/arch/arm/cpu/armv7/iproc-common/Makefile
new file mode 100644 (file)
index 0000000..c071a17
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Copyright 2014 Broadcom Corporation.
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += armpll.o
+obj-y  += hwinit-common.o
+obj-y  += timer.o
diff --git a/arch/arm/cpu/armv7/iproc-common/armpll.c b/arch/arm/cpu/armv7/iproc-common/armpll.c
new file mode 100644 (file)
index 0000000..49b61bf
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/iproc-common/armpll.h>
+#include <asm/iproc-common/sysmap.h>
+
+#define NELEMS(x)      (sizeof(x) / sizeof(x[0]))
+
+struct armpll_parameters {
+       unsigned int mode;
+       unsigned int ndiv_int;
+       unsigned int ndiv_frac;
+       unsigned int pdiv;
+       unsigned int freqid;
+};
+
+struct armpll_parameters armpll_clk_tab[] = {
+       {   25, 64,      1, 1, 0},
+       {  100, 64,      1, 1, 2},
+       {  400, 64,      1, 1, 6},
+       {  448, 71, 713050, 1, 6},
+       {  500, 80,      1, 1, 6},
+       {  560, 89, 629145, 1, 6},
+       {  600, 96,      1, 1, 6},
+       {  800, 64,      1, 1, 7},
+       {  896, 71, 713050, 1, 7},
+       { 1000, 80,      1, 1, 7},
+       { 1100, 88,      1, 1, 7},
+       { 1120, 89, 629145, 1, 7},
+       { 1200, 96,      1, 1, 7},
+};
+
+uint32_t armpll_config(uint32_t clkmhz)
+{
+       uint32_t freqid;
+       uint32_t ndiv_frac;
+       uint32_t pll;
+       uint32_t status = 1;
+       uint32_t timeout_countdown;
+       int i;
+
+       for (i = 0; i < NELEMS(armpll_clk_tab); i++) {
+               if (armpll_clk_tab[i].mode == clkmhz) {
+                       status = 0;
+                       break;
+               }
+       }
+
+       if (status) {
+               printf("Error: Clock configuration not supported\n");
+               goto armpll_config_done;
+       }
+
+       /* Enable write access */
+       writel(IPROC_REG_WRITE_ACCESS, IHOST_PROC_CLK_WR_ACCESS);
+
+       if (clkmhz == 25)
+               freqid = 0;
+       else
+               freqid = 2;
+
+       /* Bypass ARM clock and run on sysclk */
+       writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE |
+              freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R |
+              freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R |
+              freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R |
+              freqid << IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R,
+              IHOST_PROC_CLK_POLICY_FREQ);
+
+       writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO |
+              1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC,
+              IHOST_PROC_CLK_POLICY_CTL);
+
+       /* Poll CCU until operation complete */
+       timeout_countdown = 0x100000;
+       while (readl(IHOST_PROC_CLK_POLICY_CTL) &
+              (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) {
+               timeout_countdown--;
+               if (timeout_countdown == 0) {
+                       printf("CCU polling timedout\n");
+                       status = 1;
+                       goto armpll_config_done;
+               }
+       }
+
+       if (clkmhz == 25 || clkmhz == 100) {
+               status = 0;
+               goto armpll_config_done;
+       }
+
+       /* Now it is safe to program the PLL */
+       pll = readl(IHOST_PROC_CLK_PLLARMB);
+       pll &= ~((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1);
+       ndiv_frac =
+               ((1 << IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH) - 1) &
+                (armpll_clk_tab[i].ndiv_frac <<
+                IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_R);
+       pll |= ndiv_frac;
+       writel(pll, IHOST_PROC_CLK_PLLARMB);
+
+       writel(1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK |
+              armpll_clk_tab[i].ndiv_int <<
+                       IHOST_PROC_CLK_PLLARMA__PLLARM_NDIV_INT_R |
+              armpll_clk_tab[i].pdiv <<
+                       IHOST_PROC_CLK_PLLARMA__PLLARM_PDIV_R |
+              1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_RESETB,
+              IHOST_PROC_CLK_PLLARMA);
+
+       /* Poll ARM PLL Lock until operation complete */
+       timeout_countdown = 0x100000;
+       while (readl(IHOST_PROC_CLK_PLLARMA) &
+              (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK)) {
+               timeout_countdown--;
+               if (timeout_countdown == 0) {
+                       printf("ARM PLL lock failed\n");
+                       status = 1;
+                       goto armpll_config_done;
+               }
+       }
+
+       pll = readl(IHOST_PROC_CLK_PLLARMA);
+       pll |= (1 << IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB);
+       writel(pll, IHOST_PROC_CLK_PLLARMA);
+
+       /* Set the policy */
+       writel(1 << IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE |
+              armpll_clk_tab[i].freqid <<
+                       IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R |
+              armpll_clk_tab[i].freqid <<
+                       IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R |
+              armpll_clk_tab[i].freqid <<
+                       IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R |
+              armpll_clk_tab[i+4].freqid <<
+                       IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R,
+              IHOST_PROC_CLK_POLICY_FREQ);
+
+       writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE0_CLKGATE);
+       writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_CORE1_CLKGATE);
+       writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_SWITCH_CLKGATE);
+       writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_ARM_PERIPH_CLKGATE);
+       writel(IPROC_CLKCT_HDELAY_SW_EN, IHOST_PROC_CLK_APB0_CLKGATE);
+
+       writel(1 << IHOST_PROC_CLK_POLICY_CTL__GO |
+              1 << IHOST_PROC_CLK_POLICY_CTL__GO_AC,
+              IHOST_PROC_CLK_POLICY_CTL);
+
+       /* Poll CCU until operation complete */
+       timeout_countdown = 0x100000;
+       while (readl(IHOST_PROC_CLK_POLICY_CTL) &
+              (1 << IHOST_PROC_CLK_POLICY_CTL__GO)) {
+               timeout_countdown--;
+               if (timeout_countdown == 0) {
+                       printf("CCU polling failed\n");
+                       status = 1;
+                       goto armpll_config_done;
+               }
+       }
+
+       status = 0;
+armpll_config_done:
+       /* Disable access to PLL registers */
+       writel(0, IHOST_PROC_CLK_WR_ACCESS);
+
+       return status;
+}
diff --git a/arch/arm/cpu/armv7/iproc-common/hwinit-common.c b/arch/arm/cpu/armv7/iproc-common/hwinit-common.c
new file mode 100644 (file)
index 0000000..7131524
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+       /* Enable D-cache. I-cache is already enabled in start.S */
+       dcache_enable();
+}
+#endif
diff --git a/arch/arm/cpu/armv7/iproc-common/timer.c b/arch/arm/cpu/armv7/iproc-common/timer.c
new file mode 100644 (file)
index 0000000..373d8ec
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <asm/io.h>
+#include <asm/iproc-common/timer.h>
+#include <asm/iproc-common/sysmap.h>
+
+static inline uint64_t timer_global_read(void)
+{
+       uint64_t cur_tick;
+       uint32_t count_h;
+       uint32_t count_l;
+
+       do {
+               count_h = readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+                               TIMER_GLB_HI_OFFSET);
+               count_l = readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+                               TIMER_GLB_LOW_OFFSET);
+               cur_tick = readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+                                TIMER_GLB_HI_OFFSET);
+       } while (cur_tick != count_h);
+
+       return (cur_tick << 32) + count_l;
+}
+
+void timer_global_init(void)
+{
+       writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_CTRL_OFFSET);
+       writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_LOW_OFFSET);
+       writel(0, IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_HI_OFFSET);
+       writel(TIMER_GLB_TIM_CTRL_TIM_EN,
+              IPROC_PERIPH_GLB_TIM_REG_BASE + TIMER_GLB_CTRL_OFFSET);
+}
+
+int timer_init(void)
+{
+       timer_global_init();
+       return 0;
+}
+
+unsigned long get_timer(unsigned long base)
+{
+       uint64_t count;
+       uint64_t ret;
+       uint64_t tim_clk;
+       uint64_t periph_clk;
+
+       count = timer_global_read();
+
+       /* default arm clk is 1GHz, periph_clk=arm_clk/2, tick per msec */
+       periph_clk = 500000;
+       tim_clk = lldiv(periph_clk,
+                       (((readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+                                TIMER_GLB_CTRL_OFFSET) &
+                       TIMER_GLB_TIM_CTRL_PRESC_MASK) >> 8) + 1));
+
+       ret = lldiv(count, (uint32_t)tim_clk);
+
+       /* returns msec */
+       return ret - base;
+}
+
+void __udelay(unsigned long usec)
+{
+       uint64_t cur_tick, end_tick;
+       uint64_t tim_clk;
+       uint64_t periph_clk;
+
+       /* default arm clk is 1GHz, periph_clk=arm_clk/2, tick per usec */
+       periph_clk = 500;
+
+       tim_clk = lldiv(periph_clk,
+                       (((readl(IPROC_PERIPH_GLB_TIM_REG_BASE +
+                                TIMER_GLB_CTRL_OFFSET) &
+                       TIMER_GLB_TIM_CTRL_PRESC_MASK) >> 8) + 1));
+
+       cur_tick = timer_global_read();
+
+       end_tick = tim_clk;
+       end_tick *= usec;
+       end_tick += cur_tick;
+
+       do {
+               cur_tick = timer_global_read();
+
+       } while (cur_tick < end_tick);
+}
+
+void timer_systick_init(uint32_t tick_ms)
+{
+       /* Disable timer and clear interrupt status*/
+       writel(0, IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_CTRL_OFFSET);
+       writel(TIMER_PVT_TIM_INT_STATUS_SET,
+              IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_STATUS_OFFSET);
+       writel((PLL_AXI_CLK/1000) * tick_ms,
+              IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_LOAD_OFFSET);
+       writel(TIMER_PVT_TIM_CTRL_INT_EN |
+              TIMER_PVT_TIM_CTRL_AUTO_RELD |
+              TIMER_PVT_TIM_CTRL_TIM_EN,
+              IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_CTRL_OFFSET);
+}
+
+void timer_systick_isr(void *data)
+{
+       writel(TIMER_PVT_TIM_INT_STATUS_SET,
+              IPROC_PERIPH_PVT_TIM_REG_BASE + TIMER_PVT_STATUS_OFFSET);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value in msec.
+ */
+unsigned long long get_ticks(void)
+{
+       return get_timer(0);
+}
+
+/*
+ * This is used in conjuction with get_ticks, which returns msec as ticks.
+ * Here we just return ticks/sec = msec/sec = 1000
+ */
+ulong get_tbclk(void)
+{
+       return 1000;
+}
diff --git a/arch/arm/include/asm/iproc-common/armpll.h b/arch/arm/include/asm/iproc-common/armpll.h
new file mode 100644 (file)
index 0000000..1bee350
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __ARMPLL_H
+#define __ARMPLL_H
+
+#include <linux/types.h>
+
+uint32_t armpll_config(uint32_t clkmhz);
+
+#endif /*__ARMPLL_H */
diff --git a/arch/arm/include/asm/iproc-common/sysmap.h b/arch/arm/include/asm/iproc-common/sysmap.h
new file mode 100644 (file)
index 0000000..5766dc9
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __SYSMAP_H
+#define __SYSMAP_H
+
+#define IHOST_PROC_CLK_PLLARMA                                 0X19000C00
+#define IHOST_PROC_CLK_PLLARMB                                 0X19000C04
+#define IHOST_PROC_CLK_PLLARMA__PLLARM_PDIV_R                          24
+
+#define IHOST_PROC_CLK_WR_ACCESS                               0X19000000
+#define IHOST_PROC_CLK_POLICY_FREQ                             0X19000008
+#define IHOST_PROC_CLK_POLICY_FREQ__PRIV_ACCESS_MODE                   31
+#define IHOST_PROC_CLK_POLICY_FREQ__POLICY3_FREQ_R                     24
+#define IHOST_PROC_CLK_POLICY_FREQ__POLICY2_FREQ_R                     16
+#define IHOST_PROC_CLK_POLICY_FREQ__POLICY1_FREQ_R                      8
+#define IHOST_PROC_CLK_POLICY_CTL                              0X1900000C
+#define IHOST_PROC_CLK_POLICY_CTL__GO                                   0
+#define IHOST_PROC_CLK_POLICY_CTL__GO_AC                                1
+#define IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_R                      0
+#define IHOST_PROC_CLK_PLLARMB__PLLARM_NDIV_FRAC_WIDTH                 20
+#define IHOST_PROC_CLK_PLLARMA__PLLARM_LOCK                            28
+#define IHOST_PROC_CLK_POLICY_FREQ__POLICY0_FREQ_R                      0
+#define IHOST_PROC_CLK_PLLARMA__PLLARM_NDIV_INT_R                       8
+#define IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_POST_RESETB                         1
+#define IHOST_PROC_CLK_PLLARMA__PLLARM_SOFT_RESETB                      0
+#define IHOST_PROC_CLK_CORE0_CLKGATE                           0X19000200
+#define IHOST_PROC_CLK_CORE1_CLKGATE                           0X19000204
+#define IHOST_PROC_CLK_ARM_SWITCH_CLKGATE                      0X19000210
+#define IHOST_PROC_CLK_ARM_PERIPH_CLKGATE                      0X19000300
+#define IHOST_PROC_CLK_APB0_CLKGATE                            0X19000400
+#define IPROC_CLKCT_HDELAY_SW_EN                               0x00000303
+
+#define IPROC_REG_WRITE_ACCESS                                 0x00a5a501
+
+#define IPROC_PERIPH_BASE                                      0x19020000
+#define IPROC_PERIPH_INT_CTRL_REG_BASE         (IPROC_PERIPH_BASE +  0x100)
+#define IPROC_PERIPH_GLB_TIM_REG_BASE          (IPROC_PERIPH_BASE +  0x200)
+#define IPROC_PERIPH_PVT_TIM_REG_BASE          (IPROC_PERIPH_BASE +  0x600)
+#define IPROC_PERIPH_INT_DISTR_REG_BASE                (IPROC_PERIPH_BASE + 0x1000)
+
+#define PLL_AXI_CLK                                            0x1DCD6500
+
+#endif /* __SYSMAP_H */
diff --git a/arch/arm/include/asm/iproc-common/timer.h b/arch/arm/include/asm/iproc-common/timer.h
new file mode 100644 (file)
index 0000000..2bc2322
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __TIMER_H
+#define __TIMER_H
+
+#include <linux/types.h>
+
+void timer_systick_init(uint32_t tick_ms);
+void timer_global_init(void);
+
+/* ARM A9 Private Timer */
+#define TIMER_PVT_LOAD_OFFSET                  0x00000000
+#define TIMER_PVT_COUNTER_OFFSET               0x00000004
+#define TIMER_PVT_CTRL_OFFSET                  0x00000008
+#define TIMER_PVT_STATUS_OFFSET                        0x0000000C
+#define TIMER_PVT_TIM_CTRL_TIM_EN              0x00000001
+#define TIMER_PVT_TIM_CTRL_AUTO_RELD           0x00000002
+#define TIMER_PVT_TIM_CTRL_INT_EN              0x00000004
+#define TIMER_PVT_TIM_CTRL_PRESC_MASK          0x0000FF00
+#define TIMER_PVT_TIM_INT_STATUS_SET           0x00000001
+
+/* Global timer */
+#define TIMER_GLB_LOW_OFFSET                   0x00000000
+#define TIMER_GLB_HI_OFFSET                    0x00000004
+#define TIMER_GLB_CTRL_OFFSET                  0x00000008
+#define TIMER_GLB_TIM_CTRL_TIM_EN              0x00000001
+#define TIMER_GLB_TIM_CTRL_COMP_EN             0x00000002
+#define TIMER_GLB_TIM_CTRL_INT_EN              0x00000004
+#define TIMER_GLB_TIM_CTRL_AUTO_INC            0x00000008
+#define TIMER_GLB_TIM_CTRL_PRESC_MASK          0x0000FF00
+#define TIMER_GLB_TIM_INT_STATUS_SET           0x00000001
+
+#endif /*__TIMER_H */