380 lines
9.0 KiB
C
380 lines
9.0 KiB
C
|
/*
|
||
|
* (C) Copyright 2018-2020
|
||
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||
|
* wangwei <wangwei@allwinnertech.com>
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <common.h>
|
||
|
#include <asm/io.h>
|
||
|
#include <arch/clock.h>
|
||
|
#include <arch/uart.h>
|
||
|
#include <arch/efuse.h>
|
||
|
|
||
|
int sunxi_gpadc_init(void);
|
||
|
|
||
|
static void set_pll_cpux_axi(void)
|
||
|
{
|
||
|
u32 reg_val;
|
||
|
/* select CPUX clock src: OSC24M,AXI divide ratio is 2, system apb clk ratio is 4 */
|
||
|
writel((0 << 24) | (3 << 8) | (1 << 0), CCMU_CPUX_AXI_CFG_REG);
|
||
|
udelay(1);
|
||
|
|
||
|
/* disable pll gating*/
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val &= ~(1 << 27);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
|
||
|
#if (defined CFG_CPU_1G) && (defined CFG_BOOT0_LOAD_KERNEL)
|
||
|
/* set default val: clk is 1008M ,PLL_OUTPUT= 24M*N/P*/
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val &= ~((0x3 << 16) | (0xff << 8) | (0x3 << 0));
|
||
|
reg_val |= (41 << 8);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
|
||
|
reg_val = readl(CCMU_CPUX_AXI_CFG_REG);
|
||
|
reg_val &= ~(0x03 << 16);
|
||
|
reg_val |= (0x00 << 16);
|
||
|
writel(reg_val, CCMU_CPUX_AXI_CFG_REG);
|
||
|
#else
|
||
|
/* set default val: clk is 900M ,PLL_OUTPUT= 24M*N/P*/
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val &= ~((0x3 << 16) | (0xff << 8) | (0x3 << 0));
|
||
|
reg_val |= (74 << 8);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
|
||
|
reg_val = readl(CCMU_CPUX_AXI_CFG_REG);
|
||
|
reg_val &= ~(0x03 << 16);
|
||
|
reg_val |= (0x01 << 16);
|
||
|
writel(reg_val, CCMU_CPUX_AXI_CFG_REG);
|
||
|
#endif
|
||
|
|
||
|
/* lock enable */
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val |= (1 << 29);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val |= (0x1U << 30);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
udelay(5);
|
||
|
|
||
|
/*wait PLL_CPUX stable*/
|
||
|
#ifndef FPGA_PLATFORM
|
||
|
while (!(readl(CCMU_PLL_CPUX_CTRL_REG) & (0x1 << 28)))
|
||
|
;
|
||
|
udelay(20);
|
||
|
#endif
|
||
|
|
||
|
/* enable pll gating*/
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val |= (1 << 27);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
|
||
|
/* lock disable */
|
||
|
reg_val = readl(CCMU_PLL_CPUX_CTRL_REG);
|
||
|
reg_val &= ~(1 << 29);
|
||
|
writel(reg_val, CCMU_PLL_CPUX_CTRL_REG);
|
||
|
|
||
|
/*set and change cpu clk src to PLL_CPUX, PLL_CPUX:AXI0 = 408M:136M*/
|
||
|
reg_val = readl(CCMU_CPUX_AXI_CFG_REG);
|
||
|
reg_val &= ~(0x07 << 24 | 0x3 << 8 | 0x3 << 0);
|
||
|
reg_val |= (0x03 << 24 | 0x3 << 8 | 0x1 << 0);
|
||
|
writel(reg_val, CCMU_CPUX_AXI_CFG_REG);
|
||
|
udelay(1);
|
||
|
}
|
||
|
|
||
|
static void set_pll_periph0(void)
|
||
|
{
|
||
|
u32 reg_val;
|
||
|
|
||
|
if ((1U << 31) & readl(CCMU_PLL_PERI0_CTRL_REG)) {
|
||
|
/*fel has enable pll_periph0*/
|
||
|
printf("periph0 has been enabled\n");
|
||
|
return;
|
||
|
}
|
||
|
/*change psi/ahb src to OSC24M before set pll6
|
||
|
reg_val = readl(CCMU_PSI_AHB1_AHB2_CFG_REG);
|
||
|
reg_val &= (~(0x3<<24));
|
||
|
writel(reg_val,CCMU_PSI_AHB1_AHB2_CFG_REG) */;
|
||
|
|
||
|
/* disable pll gating*/
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val &= ~(1 << 27);
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
|
||
|
/* set default val*/
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val &= ~(1 << 1 | 0xff << 8 | 0x7 << 16 | 0x7 << 20);
|
||
|
reg_val |= (0x63 << 8 | 0x1 << 16 | 0x2 << 20);
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
|
||
|
/* lock enable */
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val |= (1 << 29);
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val |= (1 << 30);
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
|
||
|
/* enabe PLL: 600M(1X) 1200M(2x)*/
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val |= (1 << 31);
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
|
||
|
#ifndef FPGA_PLATFORM
|
||
|
while (!(readl(CCMU_PLL_PERI0_CTRL_REG) & (0x1 << 28)))
|
||
|
;
|
||
|
udelay(20);
|
||
|
#endif
|
||
|
|
||
|
/* enable pll gating*/
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val |= (1 << 27);
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
|
||
|
/* lock disable */
|
||
|
reg_val = readl(CCMU_PLL_PERI0_CTRL_REG);
|
||
|
reg_val &= (~(1 << 29));
|
||
|
writel(reg_val, CCMU_PLL_PERI0_CTRL_REG);
|
||
|
}
|
||
|
|
||
|
static void set_ahb(void)
|
||
|
{
|
||
|
/* PLL6:AHB1:AHB2 = 600M:200M:200M */
|
||
|
writel((2 << 0) | (0 << 8), CCMU_PSI_AHB1_AHB2_CFG_REG);
|
||
|
writel((0x03 << 24) | readl(CCMU_PSI_AHB1_AHB2_CFG_REG),
|
||
|
CCMU_PSI_AHB1_AHB2_CFG_REG);
|
||
|
udelay(1);
|
||
|
}
|
||
|
|
||
|
static void set_apb(void)
|
||
|
{
|
||
|
/*PLL6:APB1 = 600M:100M */
|
||
|
writel((2 << 0) | (1 << 8), CCMU_APB1_CFG_GREG);
|
||
|
writel((0x03 << 24) | readl(CCMU_APB1_CFG_GREG), CCMU_APB1_CFG_GREG);
|
||
|
udelay(1);
|
||
|
}
|
||
|
|
||
|
static void set_pll_dma(void)
|
||
|
{
|
||
|
/*dma reset*/
|
||
|
writel(readl(CCMU_DMA_BGR_REG) | (1 << 16), CCMU_DMA_BGR_REG);
|
||
|
udelay(20);
|
||
|
/*gating clock for dma pass*/
|
||
|
writel(readl(CCMU_DMA_BGR_REG) | (1 << 0), CCMU_DMA_BGR_REG);
|
||
|
}
|
||
|
|
||
|
static void set_pll_mbus(void)
|
||
|
{
|
||
|
u32 reg_val;
|
||
|
|
||
|
/*reset mbus domain*/
|
||
|
reg_val = readl(CCMU_MBUS_CFG_REG);
|
||
|
reg_val |= (0x1 << 30);
|
||
|
writel(reg_val, CCMU_MBUS_CFG_REG);
|
||
|
udelay(1);
|
||
|
}
|
||
|
#if 0
|
||
|
static void set_modules_clock(void)
|
||
|
{
|
||
|
u32 reg_val, i;
|
||
|
unsigned long ccmu_pll_addr[] = {
|
||
|
CCMU_PLL_PERI0_CTRL_REG,
|
||
|
CCMU_PLL_VIDE00_CTRL_REG,
|
||
|
CCMU_PLL_VIDE01_CTRL_REG,
|
||
|
CCMU_PLL_VE_CTRL_REG,
|
||
|
CCMU_PLL_AUDIO0_CTRL_REG,
|
||
|
CCMU_PLL_AUDIO1_CTRL_REG,
|
||
|
};
|
||
|
|
||
|
for (i = 0; i < sizeof(ccmu_pll_addr)/sizeof(ccmu_pll_addr[0]); i++) {
|
||
|
reg_val = readl((const volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
if (!(reg_val & (1 << 31))) {
|
||
|
writel(reg_val, (volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
|
||
|
reg_val = readl((const volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
writel(reg_val | (1 << 31) | (1 << 30), (volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
#ifndef FPGA_PLATFORM
|
||
|
/* lock enable */
|
||
|
reg_val = readl((const volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
reg_val |= (1 << 29);
|
||
|
writel(reg_val, (volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
|
||
|
while (!(readl((const volatile void __iomem *)ccmu_pll_addr[i]) & (0x1 << 28)))
|
||
|
;
|
||
|
udelay(20);
|
||
|
|
||
|
reg_val = readl((const volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
reg_val &= ~(1 << 29);
|
||
|
writel(reg_val, (volatile void __iomem *)ccmu_pll_addr[i]);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void sunxi_board_pll_init(void)
|
||
|
{
|
||
|
printf("set pll start\n");
|
||
|
set_pll_cpux_axi();
|
||
|
set_pll_periph0();
|
||
|
set_ahb();
|
||
|
set_apb();
|
||
|
set_pll_dma();
|
||
|
set_pll_mbus();
|
||
|
/*set_modules_clock();*/
|
||
|
#ifdef CFG_GPADC_KEY
|
||
|
sunxi_gpadc_init();
|
||
|
#endif
|
||
|
printf("set pll end\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void sunxi_board_clock_reset(void)
|
||
|
{
|
||
|
u32 reg_val;
|
||
|
|
||
|
/*set ahb,apb to default, use OSC24M*/
|
||
|
reg_val = readl(CCMU_PSI_AHB1_AHB2_CFG_REG);
|
||
|
reg_val &= (~((0x3 << 24) | (0x3 << 8) | (0x3)));
|
||
|
writel(reg_val, CCMU_PSI_AHB1_AHB2_CFG_REG);
|
||
|
|
||
|
reg_val = readl(CCMU_APB1_CFG_GREG);
|
||
|
reg_val &= (~((0x3 << 24) | (0x3 << 8) | (0x3)));
|
||
|
writel(reg_val, CCMU_APB1_CFG_GREG);
|
||
|
|
||
|
/*set cpux pll to default,use OSC24M*/
|
||
|
writel(0x0301, CCMU_CPUX_AXI_CFG_REG);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int sunxi_clock_init_key(void)
|
||
|
{
|
||
|
uint reg_val = 0;
|
||
|
|
||
|
/* reset */
|
||
|
reg_val = readl(CCMU_GPADC_BGR_REG);
|
||
|
reg_val &= ~(1 << 16);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
udelay(2);
|
||
|
|
||
|
reg_val |= (1 << 16);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
/* enable KEYADC gating */
|
||
|
reg_val = readl(CCMU_GPADC_BGR_REG);
|
||
|
reg_val |= (1 << 0);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int sunxi_clock_exit_key(void)
|
||
|
{
|
||
|
uint reg_val = 0;
|
||
|
|
||
|
/* disable KEYADC gating */
|
||
|
reg_val = readl(CCMU_GPADC_BGR_REG);
|
||
|
reg_val &= ~(1 << 0);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void sunxi_clock_init_uart(int port)
|
||
|
{
|
||
|
u32 i, reg;
|
||
|
|
||
|
/* reset */
|
||
|
reg = readl(CCMU_UART_BGR_REG);
|
||
|
reg &= ~(1<<(CCM_UART_RST_OFFSET + port));
|
||
|
writel(reg, CCMU_UART_BGR_REG);
|
||
|
for (i = 0; i < 100; i++)
|
||
|
;
|
||
|
reg |= (1 << (CCM_UART_RST_OFFSET + port));
|
||
|
writel(reg, CCMU_UART_BGR_REG);
|
||
|
/* gate */
|
||
|
reg = readl(CCMU_UART_BGR_REG);
|
||
|
reg &= ~(1<<(CCM_UART_GATING_OFFSET + port));
|
||
|
writel(reg, CCMU_UART_BGR_REG);
|
||
|
for (i = 0; i < 100; i++)
|
||
|
;
|
||
|
reg |= (1 << (CCM_UART_GATING_OFFSET + port));
|
||
|
writel(reg, CCMU_UART_BGR_REG);
|
||
|
}
|
||
|
|
||
|
int sunxi_clock_init_gpadc(void)
|
||
|
{
|
||
|
uint reg_val = 0;
|
||
|
/* reset */
|
||
|
reg_val = readl(CCMU_GPADC_BGR_REG);
|
||
|
reg_val &= ~(1 << 16);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
udelay(2);
|
||
|
|
||
|
reg_val |= (1 << 16);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
reg_val = readl(GPADC_CLK_SEL_REG);
|
||
|
reg_val &= ~(GPADC_CLK_SRC_MASK << GPADC_CLK_SRC_SEL_BIT);
|
||
|
reg_val |= (GPADC_CLK_SRC << 20);
|
||
|
writel(reg_val, GPADC_CLK_SEL_REG);
|
||
|
/* enable KEYADC gating */
|
||
|
reg_val = readl(CCMU_GPADC_BGR_REG);
|
||
|
reg_val |= (1 << 0);
|
||
|
writel(reg_val, CCMU_GPADC_BGR_REG);
|
||
|
|
||
|
reg_val = readl(0x02001f04);
|
||
|
/* printf("gpadc clk select: 0x%x\n", reg_val); */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void sunxi_e907_clock_init(uint32_t addr)
|
||
|
{
|
||
|
uint32_t reg_val;
|
||
|
|
||
|
/* de-reset */
|
||
|
reg_val = readl(RISCV_CFG_BGR_REG);
|
||
|
reg_val |= RISCV_CFG_RST;
|
||
|
reg_val |= RISCV_CFG_GATING;
|
||
|
writel(reg_val, RISCV_CFG_BGR_REG);
|
||
|
|
||
|
/* set start addr */
|
||
|
reg_val = addr;
|
||
|
writel(reg_val, RISCV_STA_ADD_REG);
|
||
|
|
||
|
/* set e907 clock */
|
||
|
reg_val = readl(RISCV_CLK_REG);
|
||
|
reg_val &= ~(RISCV_CLK_MASK);
|
||
|
reg_val |= RISCV_CLK_PERI_600M;
|
||
|
writel(reg_val, RISCV_CLK_REG);
|
||
|
|
||
|
/* turn on clock gating reset */
|
||
|
reg_val = readl(RISCV_GATING_RST_REG);
|
||
|
reg_val |= RISCV_CLK_GATING;
|
||
|
reg_val |= RISCV_SOFT_RSTN;
|
||
|
reg_val |= RISCV_SYS_APB_SOFT_RSTN;
|
||
|
reg_val |= RISCV_GATING_RST_FIELD;
|
||
|
writel(reg_val, RISCV_GATING_RST_REG);
|
||
|
}
|
||
|
|
||
|
void sunxi_e907_clock_reset(void)
|
||
|
{
|
||
|
uint32_t reg_val;
|
||
|
|
||
|
/* turn off clk gating */
|
||
|
reg_val = 0;
|
||
|
reg_val |= RISCV_GATING_RST_FIELD;
|
||
|
writel(reg_val, RISCV_GATING_RST_REG);
|
||
|
|
||
|
/* assert */
|
||
|
reg_val = readl(RISCV_CFG_BGR_REG);
|
||
|
reg_val &= ~(RISCV_CFG_RST);
|
||
|
reg_val &= ~(RISCV_CFG_GATING);
|
||
|
writel(reg_val, RISCV_CFG_BGR_REG);
|
||
|
}
|