1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2018 Marek Vasut <marex@denx.de> 4 */ 5 6 #include <common.h> 7 #include <asm/io.h> 8 #include <clk-uclass.h> 9 #include <dm.h> 10 #include <dm/lists.h> 11 #include <dm/util.h> 12 13 #include <asm/arch/clock_manager.h> 14 15 enum socfpga_a10_clk_type { 16 SOCFPGA_A10_CLK_MAIN_PLL, 17 SOCFPGA_A10_CLK_PER_PLL, 18 SOCFPGA_A10_CLK_PERIP_CLK, 19 SOCFPGA_A10_CLK_GATE_CLK, 20 SOCFPGA_A10_CLK_UNKNOWN_CLK, 21 }; 22 23 struct socfpga_a10_clk_platdata { 24 enum socfpga_a10_clk_type type; 25 struct clk_bulk clks; 26 u32 regs; 27 /* Fixed divider */ 28 u16 fix_div; 29 /* Control register */ 30 u16 ctl_reg; 31 /* Divider register */ 32 u16 div_reg; 33 u8 div_len; 34 u8 div_off; 35 /* Clock gating register */ 36 u16 gate_reg; 37 u8 gate_bit; 38 }; 39 40 static int socfpga_a10_clk_get_upstream(struct clk *clk, struct clk **upclk) 41 { 42 struct socfpga_a10_clk_platdata *plat = dev_get_platdata(clk->dev); 43 u32 reg, maxval; 44 45 if (plat->clks.count == 0) 46 return 0; 47 48 if (plat->clks.count == 1) { 49 *upclk = &plat->clks.clks[0]; 50 return 0; 51 } 52 53 if (!plat->ctl_reg) { 54 dev_err(clk->dev, "Invalid control register\n"); 55 return -EINVAL; 56 } 57 58 reg = readl(plat->regs + plat->ctl_reg); 59 60 /* Assume PLLs are ON for now */ 61 if (plat->type == SOCFPGA_A10_CLK_MAIN_PLL) { 62 reg = (reg >> 8) & 0x3; 63 maxval = 2; 64 } else if (plat->type == SOCFPGA_A10_CLK_PER_PLL) { 65 reg = (reg >> 8) & 0x3; 66 maxval = 3; 67 } else { 68 reg = (reg >> 16) & 0x7; 69 maxval = 4; 70 } 71 72 if (reg > maxval) { 73 dev_err(clk->dev, "Invalid clock source\n"); 74 return -EINVAL; 75 } 76 77 *upclk = &plat->clks.clks[reg]; 78 return 0; 79 } 80 81 static int socfpga_a10_clk_endisable(struct clk *clk, bool enable) 82 { 83 struct socfpga_a10_clk_platdata *plat = dev_get_platdata(clk->dev); 84 struct clk *upclk = NULL; 85 int ret; 86 87 if (!enable && plat->gate_reg) 88 clrbits_le32(plat->regs + plat->gate_reg, BIT(plat->gate_bit)); 89 90 ret = socfpga_a10_clk_get_upstream(clk, &upclk); 91 if (ret) 92 return ret; 93 94 if (upclk) { 95 if (enable) 96 clk_enable(upclk); 97 else 98 clk_disable(upclk); 99 } 100 101 if (enable && plat->gate_reg) 102 setbits_le32(plat->regs + plat->gate_reg, BIT(plat->gate_bit)); 103 104 return 0; 105 } 106 107 static int socfpga_a10_clk_enable(struct clk *clk) 108 { 109 return socfpga_a10_clk_endisable(clk, true); 110 } 111 112 static int socfpga_a10_clk_disable(struct clk *clk) 113 { 114 return socfpga_a10_clk_endisable(clk, false); 115 } 116 117 static ulong socfpga_a10_clk_get_rate(struct clk *clk) 118 { 119 struct socfpga_a10_clk_platdata *plat = dev_get_platdata(clk->dev); 120 struct clk *upclk = NULL; 121 ulong rate = 0, reg, numer, denom; 122 int ret; 123 124 ret = socfpga_a10_clk_get_upstream(clk, &upclk); 125 if (ret || !upclk) 126 return 0; 127 128 rate = clk_get_rate(upclk); 129 130 if (plat->type == SOCFPGA_A10_CLK_MAIN_PLL) { 131 reg = readl(plat->regs + plat->ctl_reg + 4); /* VCO1 */ 132 numer = reg & CLKMGR_MAINPLL_VCO1_NUMER_MSK; 133 denom = (reg >> CLKMGR_MAINPLL_VCO1_DENOM_LSB) & 134 CLKMGR_MAINPLL_VCO1_DENOM_MSK; 135 136 rate /= denom + 1; 137 rate *= numer + 1; 138 } else if (plat->type == SOCFPGA_A10_CLK_PER_PLL) { 139 reg = readl(plat->regs + plat->ctl_reg + 4); /* VCO1 */ 140 numer = reg & CLKMGR_PERPLL_VCO1_NUMER_MSK; 141 denom = (reg >> CLKMGR_PERPLL_VCO1_DENOM_LSB) & 142 CLKMGR_PERPLL_VCO1_DENOM_MSK; 143 144 rate /= denom + 1; 145 rate *= numer + 1; 146 } else { 147 rate /= plat->fix_div; 148 149 if (plat->fix_div == 1 && plat->ctl_reg) { 150 reg = readl(plat->regs + plat->ctl_reg); 151 reg &= 0x7ff; 152 rate /= reg + 1; 153 } 154 155 if (plat->div_reg) { 156 reg = readl(plat->regs + plat->div_reg); 157 reg >>= plat->div_off; 158 reg &= (1 << plat->div_len) - 1; 159 if (plat->type == SOCFPGA_A10_CLK_PERIP_CLK) 160 rate /= reg + 1; 161 if (plat->type == SOCFPGA_A10_CLK_GATE_CLK) 162 rate /= 1 << reg; 163 } 164 } 165 166 return rate; 167 } 168 169 static struct clk_ops socfpga_a10_clk_ops = { 170 .enable = socfpga_a10_clk_enable, 171 .disable = socfpga_a10_clk_disable, 172 .get_rate = socfpga_a10_clk_get_rate, 173 }; 174 175 /* 176 * This workaround tries to fix the massively broken generated "handoff" DT, 177 * which contains duplicate clock nodes without any connection to the clock 178 * manager DT node. Yet, those "handoff" DT nodes contain configuration of 179 * the fixed input clock of the Arria10 which are missing from the base DT 180 * for Arria10. 181 * 182 * This workaround sets up upstream clock for the fixed input clocks of the 183 * A10 described in the base DT such that they map to the fixed clock from 184 * the "handoff" DT. This does not fully match how the clock look on the 185 * A10, but it is the least intrusive way to fix this mess. 186 */ 187 static void socfpga_a10_handoff_workaround(struct udevice *dev) 188 { 189 struct socfpga_a10_clk_platdata *plat = dev_get_platdata(dev); 190 const void *fdt = gd->fdt_blob; 191 struct clk_bulk *bulk = &plat->clks; 192 int i, ret, offset = dev_of_offset(dev); 193 static const char * const socfpga_a10_fixedclk_map[] = { 194 "osc1", "altera_arria10_hps_eosc1", 195 "cb_intosc_ls_clk", "altera_arria10_hps_cb_intosc_ls", 196 "f2s_free_clk", "altera_arria10_hps_f2h_free", 197 }; 198 199 if (fdt_node_check_compatible(fdt, offset, "fixed-clock")) 200 return; 201 202 for (i = 0; i < ARRAY_SIZE(socfpga_a10_fixedclk_map); i += 2) 203 if (!strcmp(dev->name, socfpga_a10_fixedclk_map[i])) 204 break; 205 206 if (i == ARRAY_SIZE(socfpga_a10_fixedclk_map)) 207 return; 208 209 ret = uclass_get_device_by_name(UCLASS_CLK, 210 socfpga_a10_fixedclk_map[i + 1], &dev); 211 if (ret) 212 return; 213 214 bulk->count = 1; 215 bulk->clks = devm_kcalloc(dev, bulk->count, 216 sizeof(struct clk), GFP_KERNEL); 217 if (!bulk->clks) 218 return; 219 220 ret = clk_request(dev, &bulk->clks[0]); 221 if (ret) 222 free(bulk->clks); 223 } 224 225 static int socfpga_a10_clk_bind(struct udevice *dev) 226 { 227 const void *fdt = gd->fdt_blob; 228 int offset = dev_of_offset(dev); 229 bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC); 230 const char *name; 231 int ret; 232 233 for (offset = fdt_first_subnode(fdt, offset); 234 offset > 0; 235 offset = fdt_next_subnode(fdt, offset)) { 236 name = fdt_get_name(fdt, offset, NULL); 237 if (!name) 238 return -EINVAL; 239 240 if (!strcmp(name, "clocks")) { 241 offset = fdt_first_subnode(fdt, offset); 242 name = fdt_get_name(fdt, offset, NULL); 243 if (!name) 244 return -EINVAL; 245 } 246 247 /* Filter out supported sub-clock */ 248 if (fdt_node_check_compatible(fdt, offset, 249 "altr,socfpga-a10-pll-clock") && 250 fdt_node_check_compatible(fdt, offset, 251 "altr,socfpga-a10-perip-clk") && 252 fdt_node_check_compatible(fdt, offset, 253 "altr,socfpga-a10-gate-clk") && 254 fdt_node_check_compatible(fdt, offset, "fixed-clock")) 255 continue; 256 257 if (pre_reloc_only && !dm_fdt_pre_reloc(fdt, offset)) 258 continue; 259 260 ret = device_bind_driver_to_node(dev, "clk-a10", name, 261 offset_to_ofnode(offset), 262 NULL); 263 if (ret) 264 return ret; 265 } 266 267 return 0; 268 } 269 270 static int socfpga_a10_clk_probe(struct udevice *dev) 271 { 272 struct socfpga_a10_clk_platdata *plat = dev_get_platdata(dev); 273 const void *fdt = gd->fdt_blob; 274 int offset = dev_of_offset(dev); 275 276 clk_get_bulk(dev, &plat->clks); 277 278 socfpga_a10_handoff_workaround(dev); 279 280 if (!fdt_node_check_compatible(fdt, offset, 281 "altr,socfpga-a10-pll-clock")) { 282 /* Main PLL has 3 upstream clock */ 283 if (plat->clks.count == 3) 284 plat->type = SOCFPGA_A10_CLK_MAIN_PLL; 285 else 286 plat->type = SOCFPGA_A10_CLK_PER_PLL; 287 } else if (!fdt_node_check_compatible(fdt, offset, 288 "altr,socfpga-a10-perip-clk")) { 289 plat->type = SOCFPGA_A10_CLK_PERIP_CLK; 290 } else if (!fdt_node_check_compatible(fdt, offset, 291 "altr,socfpga-a10-gate-clk")) { 292 plat->type = SOCFPGA_A10_CLK_GATE_CLK; 293 } else { 294 plat->type = SOCFPGA_A10_CLK_UNKNOWN_CLK; 295 } 296 297 return 0; 298 } 299 300 static int socfpga_a10_ofdata_to_platdata(struct udevice *dev) 301 { 302 struct socfpga_a10_clk_platdata *plat = dev_get_platdata(dev); 303 struct socfpga_a10_clk_platdata *pplat; 304 struct udevice *pdev; 305 const void *fdt = gd->fdt_blob; 306 unsigned int divreg[3], gatereg[2]; 307 int ret, offset = dev_of_offset(dev); 308 u32 regs; 309 310 regs = dev_read_u32_default(dev, "reg", 0x0); 311 312 if (!fdt_node_check_compatible(fdt, offset, "altr,clk-mgr")) { 313 plat->regs = devfdt_get_addr(dev); 314 } else { 315 pdev = dev_get_parent(dev); 316 if (!pdev) 317 return -ENODEV; 318 319 pplat = dev_get_platdata(pdev); 320 if (!pplat) 321 return -EINVAL; 322 323 plat->ctl_reg = regs; 324 plat->regs = pplat->regs; 325 } 326 327 plat->type = SOCFPGA_A10_CLK_UNKNOWN_CLK; 328 329 plat->fix_div = dev_read_u32_default(dev, "fixed-divider", 1); 330 331 ret = dev_read_u32_array(dev, "div-reg", divreg, ARRAY_SIZE(divreg)); 332 if (!ret) { 333 plat->div_reg = divreg[0]; 334 plat->div_len = divreg[2]; 335 plat->div_off = divreg[1]; 336 } 337 338 ret = dev_read_u32_array(dev, "clk-gate", gatereg, ARRAY_SIZE(gatereg)); 339 if (!ret) { 340 plat->gate_reg = gatereg[0]; 341 plat->gate_bit = gatereg[1]; 342 } 343 344 return 0; 345 } 346 347 static const struct udevice_id socfpga_a10_clk_match[] = { 348 { .compatible = "altr,clk-mgr" }, 349 {} 350 }; 351 352 U_BOOT_DRIVER(socfpga_a10_clk) = { 353 .name = "clk-a10", 354 .id = UCLASS_CLK, 355 .flags = DM_FLAG_PRE_RELOC, 356 .of_match = socfpga_a10_clk_match, 357 .ops = &socfpga_a10_clk_ops, 358 .bind = socfpga_a10_clk_bind, 359 .probe = socfpga_a10_clk_probe, 360 .ofdata_to_platdata = socfpga_a10_ofdata_to_platdata, 361 362 .platdata_auto_alloc_size = sizeof(struct socfpga_a10_clk_platdata), 363 }; 364