/* * (C) Copyright 2018-2020 * Allwinner Technology Co., Ltd. * wangwei * */ #include #include #include #include #include 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); }