1 2 /* 3 * sun9i specific clock code 4 * 5 * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com> 6 * 7 * (C) Copyright 2016 Theobroma Systems Design und Consulting GmbH 8 * Philipp Tomsich <philipp.tomsich@theobroma-systems.com> 9 * 10 * SPDX-License-Identifier: GPL-2.0+ 11 */ 12 13 #include <common.h> 14 #include <asm/io.h> 15 #include <asm/arch/clock.h> 16 #include <asm/arch/prcm.h> 17 #include <asm/arch/sys_proto.h> 18 19 20 #ifdef CONFIG_SPL_BUILD 21 22 void clock_init_safe(void) 23 { 24 struct sunxi_ccm_reg * const ccm = 25 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 26 27 /* Set up PLL12 (peripheral 1) */ 28 clock_set_pll12(1200000000); 29 30 /* Set up PLL1 (cluster 0) and PLL2 (cluster 1) */ 31 clock_set_pll1(408000000); 32 clock_set_pll2(408000000); 33 34 /* Set up PLL4 (peripheral 0) */ 35 clock_set_pll4(960000000); 36 37 /* Set up dividers for AXI0 and APB0 on cluster 0: PLL1 / 2 = 204MHz */ 38 writel(C0_CFG_AXI0_CLK_DIV_RATIO(2) | 39 C0_CFG_APB0_CLK_DIV_RATIO(2), &ccm->c0_cfg); 40 41 /* AHB0: 120 MHz (PLL_PERIPH0 / 8) */ 42 writel(AHBx_SRC_PLL_PERIPH0 | AHBx_CLK_DIV_RATIO(8), 43 &ccm->ahb0_cfg); 44 /* AHB1: 240 MHz (PLL_PERIPH0 / 4) */ 45 writel(AHBx_SRC_PLL_PERIPH0 | AHBx_CLK_DIV_RATIO(4), 46 &ccm->ahb1_cfg); 47 /* AHB2: 120 MHz (PLL_PERIPH0 / 8) */ 48 writel(AHBx_SRC_PLL_PERIPH0 | AHBx_CLK_DIV_RATIO(8), 49 &ccm->ahb2_cfg); 50 /* APB0: 120 MHz (PLL_PERIPH0 / 8) */ 51 writel(APB0_SRC_PLL_PERIPH0 | APB0_CLK_DIV_RATIO(8), 52 &ccm->apb0_cfg); 53 54 /* GTBUS: 400MHz (PERIPH0 div 3) */ 55 writel(GTBUS_SRC_PLL_PERIPH1 | GTBUS_CLK_DIV_RATIO(3), 56 &ccm->gtbus_cfg); 57 /* CCI400: 480MHz (PERIPH1 div 2) */ 58 writel(CCI400_SRC_PLL_PERIPH0 | CCI400_CLK_DIV_RATIO(2), 59 &ccm->cci400_cfg); 60 61 /* Deassert DMA reset and open clock gating for DMA */ 62 setbits_le32(&ccm->ahb_reset1_cfg, (1 << 24)); 63 setbits_le32(&ccm->apb1_gate, (1 << 24)); 64 65 /* set enable-bit in TSTAMP_CTRL_REG */ 66 writel(1, 0x01720000); 67 } 68 #endif 69 70 void clock_init_uart(void) 71 { 72 struct sunxi_ccm_reg *const ccm = 73 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 74 75 /* open the clock for uart */ 76 setbits_le32(&ccm->apb1_gate, 77 CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT + 78 CONFIG_CONS_INDEX - 1)); 79 /* deassert uart reset */ 80 setbits_le32(&ccm->apb1_reset_cfg, 81 1 << (APB1_RESET_UART_SHIFT + 82 CONFIG_CONS_INDEX - 1)); 83 } 84 85 #ifdef CONFIG_SPL_BUILD 86 void clock_set_pll1(unsigned int clk) 87 { 88 struct sunxi_ccm_reg * const ccm = 89 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 90 const int p = 0; 91 92 /* Switch cluster 0 to 24MHz clock while changing PLL1 */ 93 clrsetbits_le32(&ccm->cpu_clk_source, C0_CPUX_CLK_SRC_MASK, 94 C0_CPUX_CLK_SRC_OSC24M); 95 96 writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) | 97 CCM_PLL1_CLOCK_TIME_2 | 98 CCM_PLL1_CTRL_N(clk / 24000000), 99 &ccm->pll1_c0_cfg); 100 /* 101 * Don't bother with the stable-time registers, as it doesn't 102 * wait until the PLL is stable. Note, that even Allwinner 103 * just uses a delay loop (or rather the AVS timer) for this 104 * instead of the PLL_STABLE_STATUS register. 105 */ 106 sdelay(2000); 107 108 /* Switch cluster 0 back to PLL1 */ 109 clrsetbits_le32(&ccm->cpu_clk_source, C0_CPUX_CLK_SRC_MASK, 110 C0_CPUX_CLK_SRC_PLL1); 111 } 112 113 void clock_set_pll2(unsigned int clk) 114 { 115 struct sunxi_ccm_reg * const ccm = 116 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 117 const int p = 0; 118 119 /* Switch cluster 1 to 24MHz clock while changing PLL2 */ 120 clrsetbits_le32(&ccm->cpu_clk_source, C1_CPUX_CLK_SRC_MASK, 121 C1_CPUX_CLK_SRC_OSC24M); 122 123 writel(CCM_PLL2_CTRL_EN | CCM_PLL2_CTRL_P(p) | 124 CCM_PLL2_CLOCK_TIME_2 | CCM_PLL2_CTRL_N(clk / 24000000), 125 &ccm->pll2_c1_cfg); 126 127 sdelay(2000); 128 129 /* Switch cluster 1 back to PLL2 */ 130 clrsetbits_le32(&ccm->cpu_clk_source, C1_CPUX_CLK_SRC_MASK, 131 C1_CPUX_CLK_SRC_PLL2); 132 } 133 134 void clock_set_pll6(unsigned int clk) 135 { 136 struct sunxi_ccm_reg * const ccm = 137 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 138 const int p = 0; 139 140 writel(CCM_PLL6_CTRL_EN | CCM_PLL6_CFG_UPDATE | CCM_PLL6_CTRL_P(p) 141 | CCM_PLL6_CTRL_N(clk / 24000000), 142 &ccm->pll6_ddr_cfg); 143 do { } while (!(readl(&ccm->pll_stable_status) & PLL_DDR_STATUS)); 144 145 sdelay(2000); 146 } 147 148 void clock_set_pll12(unsigned int clk) 149 { 150 struct sunxi_ccm_reg * const ccm = 151 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 152 153 if (readl(&ccm->pll12_periph1_cfg) & CCM_PLL12_CTRL_EN) 154 return; 155 156 writel(CCM_PLL12_CTRL_EN | CCM_PLL12_CTRL_N(clk / 24000000), 157 &ccm->pll12_periph1_cfg); 158 159 sdelay(2000); 160 } 161 162 163 void clock_set_pll4(unsigned int clk) 164 { 165 struct sunxi_ccm_reg * const ccm = 166 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 167 168 writel(CCM_PLL4_CTRL_EN | CCM_PLL4_CTRL_N(clk / 24000000), 169 &ccm->pll4_periph0_cfg); 170 171 sdelay(2000); 172 } 173 #endif 174 175 int clock_twi_onoff(int port, int state) 176 { 177 struct sunxi_ccm_reg *const ccm = 178 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 179 180 if (port > 4) 181 return -1; 182 183 /* set the apb reset and clock gate for twi */ 184 if (state) { 185 setbits_le32(&ccm->apb1_gate, 186 CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port)); 187 setbits_le32(&ccm->apb1_reset_cfg, 188 1 << (APB1_RESET_TWI_SHIFT + port)); 189 } else { 190 clrbits_le32(&ccm->apb1_reset_cfg, 191 1 << (APB1_RESET_TWI_SHIFT + port)); 192 clrbits_le32(&ccm->apb1_gate, 193 CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT + port)); 194 } 195 196 return 0; 197 } 198 199 unsigned int clock_get_pll4_periph0(void) 200 { 201 struct sunxi_ccm_reg *const ccm = 202 (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; 203 uint32_t rval = readl(&ccm->pll4_periph0_cfg); 204 int n = ((rval & CCM_PLL4_CTRL_N_MASK) >> CCM_PLL4_CTRL_N_SHIFT); 205 int p = ((rval & CCM_PLL4_CTRL_P_MASK) >> CCM_PLL4_CTRL_P_SHIFT); 206 int m = ((rval & CCM_PLL4_CTRL_M_MASK) >> CCM_PLL4_CTRL_M_SHIFT) + 1; 207 const int k = 1; 208 209 return ((24000000 * n * k) >> p) / m; 210 } 211