sdk-hwV1.3/lichee/brandy-2.0/spl/board/sun8iw21p1/clock.c

380 lines
9.0 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
/*
* (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);
}