1 /* 2 * Clock drivers for Qualcomm APQ8016 3 * 4 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> 5 * 6 * Based on Little Kernel driver, simplified 7 * 8 * SPDX-License-Identifier: BSD-3-Clause 9 */ 10 11 #include <common.h> 12 #include <clk-uclass.h> 13 #include <dm.h> 14 #include <errno.h> 15 #include <asm/io.h> 16 #include <linux/bitops.h> 17 18 /* GPLL0 clock control registers */ 19 #define GPLL0_STATUS 0x2101C 20 #define GPLL0_STATUS_ACTIVE BIT(17) 21 22 #define APCS_GPLL_ENA_VOTE 0x45000 23 #define APCS_GPLL_ENA_VOTE_GPLL0 BIT(0) 24 25 /* vote reg for blsp1 clock */ 26 #define APCS_CLOCK_BRANCH_ENA_VOTE 0x45004 27 #define APCS_CLOCK_BRANCH_ENA_VOTE_BLSP1 BIT(10) 28 29 /* SDC(n) clock control registers; n=1,2 */ 30 31 /* block control register */ 32 #define SDCC_BCR(n) ((n * 0x1000) + 0x41000) 33 /* cmd */ 34 #define SDCC_CMD_RCGR(n) ((n * 0x1000) + 0x41004) 35 /* cfg */ 36 #define SDCC_CFG_RCGR(n) ((n * 0x1000) + 0x41008) 37 /* m */ 38 #define SDCC_M(n) ((n * 0x1000) + 0x4100C) 39 /* n */ 40 #define SDCC_N(n) ((n * 0x1000) + 0x41010) 41 /* d */ 42 #define SDCC_D(n) ((n * 0x1000) + 0x41014) 43 /* branch control */ 44 #define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018) 45 #define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C) 46 47 /* BLSP1 AHB clock (root clock for BLSP) */ 48 #define BLSP1_AHB_CBCR 0x1008 49 50 /* Uart clock control registers */ 51 #define BLSP1_UART2_BCR 0x3028 52 #define BLSP1_UART2_APPS_CBCR 0x302C 53 #define BLSP1_UART2_APPS_CMD_RCGR 0x3034 54 #define BLSP1_UART2_APPS_CFG_RCGR 0x3038 55 #define BLSP1_UART2_APPS_M 0x303C 56 #define BLSP1_UART2_APPS_N 0x3040 57 #define BLSP1_UART2_APPS_D 0x3044 58 59 /* CBCR register fields */ 60 #define CBCR_BRANCH_ENABLE_BIT BIT(0) 61 #define CBCR_BRANCH_OFF_BIT BIT(31) 62 63 struct msm_clk_priv { 64 phys_addr_t base; 65 }; 66 67 /* Enable clock controlled by CBC soft macro */ 68 static void clk_enable_cbc(phys_addr_t cbcr) 69 { 70 setbits_le32(cbcr, CBCR_BRANCH_ENABLE_BIT); 71 72 while (readl(cbcr) & CBCR_BRANCH_OFF_BIT) 73 ; 74 } 75 76 /* clock has 800MHz */ 77 static void clk_enable_gpll0(phys_addr_t base) 78 { 79 if (readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) 80 return; /* clock already enabled */ 81 82 setbits_le32(base + APCS_GPLL_ENA_VOTE, APCS_GPLL_ENA_VOTE_GPLL0); 83 84 while ((readl(base + GPLL0_STATUS) & GPLL0_STATUS_ACTIVE) == 0) 85 ; 86 } 87 88 #define APPS_CMD_RGCR_UPDATE BIT(0) 89 90 /* Update clock command via CMD_RGCR */ 91 static void clk_bcr_update(phys_addr_t apps_cmd_rgcr) 92 { 93 setbits_le32(apps_cmd_rgcr, APPS_CMD_RGCR_UPDATE); 94 95 /* Wait for frequency to be updated. */ 96 while (readl(apps_cmd_rgcr) & APPS_CMD_RGCR_UPDATE) 97 ; 98 } 99 100 struct bcr_regs { 101 uintptr_t cfg_rcgr; 102 uintptr_t cmd_rcgr; 103 uintptr_t M; 104 uintptr_t N; 105 uintptr_t D; 106 }; 107 108 /* RCGR_CFG register fields */ 109 #define CFG_MODE_DUAL_EDGE (0x2 << 12) /* Counter mode */ 110 111 /* sources */ 112 #define CFG_CLK_SRC_CXO (0 << 8) 113 #define CFG_CLK_SRC_GPLL0 (1 << 8) 114 #define CFG_CLK_SRC_MASK (7 << 8) 115 116 /* Mask for supported fields */ 117 #define CFG_MASK 0x3FFF 118 119 #define CFG_DIVIDER_MASK 0x1F 120 121 /* root set rate for clocks with half integer and MND divider */ 122 static void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, 123 int div, int m, int n, int source) 124 { 125 uint32_t cfg; 126 /* M value for MND divider. */ 127 uint32_t m_val = m; 128 /* NOT(N-M) value for MND divider. */ 129 uint32_t n_val = ~((n)-(m)) * !!(n); 130 /* NOT 2D value for MND divider. */ 131 uint32_t d_val = ~(n); 132 133 /* Program MND values */ 134 writel(m_val, base + regs->M); 135 writel(n_val, base + regs->N); 136 writel(d_val, base + regs->D); 137 138 /* setup src select and divider */ 139 cfg = readl(base + regs->cfg_rcgr); 140 cfg &= ~CFG_MASK; 141 cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */ 142 143 /* Set the divider; HW permits fraction dividers (+0.5), but 144 for simplicity, we will support integers only */ 145 if (div) 146 cfg |= (2 * div - 1) & CFG_DIVIDER_MASK; 147 148 if (n_val) 149 cfg |= CFG_MODE_DUAL_EDGE; 150 151 writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */ 152 153 /* Inform h/w to start using the new config. */ 154 clk_bcr_update(base + regs->cmd_rcgr); 155 } 156 157 static const struct bcr_regs sdc_regs[] = { 158 { 159 .cfg_rcgr = SDCC_CFG_RCGR(1), 160 .cmd_rcgr = SDCC_CMD_RCGR(1), 161 .M = SDCC_M(1), 162 .N = SDCC_N(1), 163 .D = SDCC_D(1), 164 }, 165 { 166 .cfg_rcgr = SDCC_CFG_RCGR(2), 167 .cmd_rcgr = SDCC_CMD_RCGR(2), 168 .M = SDCC_M(2), 169 .N = SDCC_N(2), 170 .D = SDCC_D(2), 171 } 172 }; 173 174 /* Init clock for SDHCI controller */ 175 static int clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate) 176 { 177 int div = 8; /* 100MHz default */ 178 179 if (rate == 200000000) 180 div = 4; 181 182 clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot)); 183 /* 800Mhz/div, gpll0 */ 184 clk_rcg_set_rate_mnd(priv->base, &sdc_regs[slot], div, 0, 0, 185 CFG_CLK_SRC_GPLL0); 186 clk_enable_gpll0(priv->base); 187 clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot)); 188 189 return rate; 190 } 191 192 static const struct bcr_regs uart2_regs = { 193 .cfg_rcgr = BLSP1_UART2_APPS_CFG_RCGR, 194 .cmd_rcgr = BLSP1_UART2_APPS_CMD_RCGR, 195 .M = BLSP1_UART2_APPS_M, 196 .N = BLSP1_UART2_APPS_N, 197 .D = BLSP1_UART2_APPS_D, 198 }; 199 200 /* Init UART clock, 115200 */ 201 static int clk_init_uart(struct msm_clk_priv *priv) 202 { 203 /* Enable iface clk */ 204 clk_enable_cbc(priv->base + BLSP1_AHB_CBCR); 205 /* 7372800 uart block clock @ GPLL0 */ 206 clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625, 207 CFG_CLK_SRC_GPLL0); 208 clk_enable_gpll0(priv->base); 209 /* Enable core clk */ 210 clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); 211 212 return 0; 213 } 214 215 ulong msm_set_rate(struct clk *clk, ulong rate) 216 { 217 struct msm_clk_priv *priv = dev_get_priv(clk->dev); 218 219 switch (clk->id) { 220 case 0: /* SDC1 */ 221 return clk_init_sdc(priv, 0, rate); 222 break; 223 case 1: /* SDC2 */ 224 return clk_init_sdc(priv, 1, rate); 225 break; 226 case 4: /* UART2 */ 227 return clk_init_uart(priv); 228 break; 229 default: 230 return 0; 231 } 232 } 233 234 static int msm_clk_probe(struct udevice *dev) 235 { 236 struct msm_clk_priv *priv = dev_get_priv(dev); 237 238 priv->base = dev_get_addr(dev); 239 if (priv->base == FDT_ADDR_T_NONE) 240 return -EINVAL; 241 242 return 0; 243 } 244 245 static struct clk_ops msm_clk_ops = { 246 .set_rate = msm_set_rate, 247 }; 248 249 static const struct udevice_id msm_clk_ids[] = { 250 { .compatible = "qcom,gcc-msm8916" }, 251 { .compatible = "qcom,gcc-apq8016" }, 252 { } 253 }; 254 255 U_BOOT_DRIVER(clk_msm) = { 256 .name = "clk_msm", 257 .id = UCLASS_CLK, 258 .of_match = msm_clk_ids, 259 .ops = &msm_clk_ops, 260 .priv_auto_alloc_size = sizeof(struct msm_clk_priv), 261 .probe = msm_clk_probe, 262 }; 263