mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 05:01:30 +00:00
arm: iproc: Initial commit of iproc architecture code
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>
This commit is contained in:
parent
b0e31c7b66
commit
c4b4500910
8 changed files with 423 additions and 0 deletions
|
@ -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
|
||||
|
|
9
arch/arm/cpu/armv7/iproc-common/Makefile
Normal file
9
arch/arm/cpu/armv7/iproc-common/Makefile
Normal file
|
@ -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
|
170
arch/arm/cpu/armv7/iproc-common/armpll.c
Normal file
170
arch/arm/cpu/armv7/iproc-common/armpll.c
Normal file
|
@ -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;
|
||||
}
|
15
arch/arm/cpu/armv7/iproc-common/hwinit-common.c
Normal file
15
arch/arm/cpu/armv7/iproc-common/hwinit-common.c
Normal file
|
@ -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
|
130
arch/arm/cpu/armv7/iproc-common/timer.c
Normal file
130
arch/arm/cpu/armv7/iproc-common/timer.c
Normal file
|
@ -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;
|
||||
}
|
14
arch/arm/include/asm/iproc-common/armpll.h
Normal file
14
arch/arm/include/asm/iproc-common/armpll.h
Normal file
|
@ -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 */
|
47
arch/arm/include/asm/iproc-common/sysmap.h
Normal file
47
arch/arm/include/asm/iproc-common/sysmap.h
Normal file
|
@ -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 */
|
37
arch/arm/include/asm/iproc-common/timer.h
Normal file
37
arch/arm/include/asm/iproc-common/timer.h
Normal file
|
@ -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 */
|
Loading…
Add table
Reference in a new issue