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>master
parent
b0e31c7b66
commit
c4b4500910
@ -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
|
@ -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; |
||||
} |
@ -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 |
@ -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; |
||||
} |
@ -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 */ |
@ -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 */ |
@ -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…
Reference in new issue