1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Main clock support for AT91 architectures. 4 * 5 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries 6 * 7 * Author: Claudiu Beznea <claudiu.beznea@microchip.com> 8 * 9 * Based on drivers/clk/at91/clk-main.c from Linux. 10 */ 11 12#include <asm/processor.h> 13#include <common.h> 14#include <clk-uclass.h> 15#include <dm.h> 16#include <linux/clk-provider.h> 17#include <linux/clk/at91_pmc.h> 18#include <linux/delay.h> 19#include <linux/io.h> 20#include <linux/time.h> 21#include "pmc.h" 22 23#define UBOOT_DM_CLK_AT91_MAIN_RC "at91-main-rc-clk" 24#define UBOOT_DM_CLK_AT91_MAIN_OSC "at91-main-osc-clk" 25#define UBOOT_DM_CLK_AT91_RM9200_MAIN "at91-rm9200-main-clk" 26#define UBOOT_DM_CLK_AT91_SAM9X5_MAIN "at91-sam9x5-main-clk" 27 28#define MOR_KEY_MASK GENMASK(23, 16) 29#define SLOW_CLOCK_FREQ 32768 30 31#define clk_main_parent_select(s) (((s) & \ 32 (AT91_PMC_MOSCEN | \ 33 AT91_PMC_OSCBYPASS)) ? 1 : 0) 34 35struct clk_main_rc { 36 void __iomem *reg; 37 struct clk clk; 38}; 39 40#define to_clk_main_rc(_clk) container_of(_clk, struct clk_main_rc, clk) 41 42struct clk_main_osc { 43 void __iomem *reg; 44 struct clk clk; 45}; 46 47#define to_clk_main_osc(_clk) container_of(_clk, struct clk_main_osc, clk) 48 49struct clk_main { 50 void __iomem *reg; 51 const unsigned int *clk_mux_table; 52 const char * const *parent_names; 53 unsigned int num_parents; 54 int type; 55 struct clk clk; 56}; 57 58#define to_clk_main(_clk) container_of(_clk, struct clk_main, clk) 59 60static int main_rc_enable(struct clk *clk) 61{ 62 struct clk_main_rc *main_rc = to_clk_main_rc(clk); 63 void __iomem *reg = main_rc->reg; 64 unsigned int val; 65 66 pmc_read(reg, AT91_CKGR_MOR, &val); 67 68 if (!(val & AT91_PMC_MOSCRCEN)) { 69 pmc_update_bits(reg, AT91_CKGR_MOR, 70 MOR_KEY_MASK | AT91_PMC_MOSCRCEN, 71 AT91_PMC_KEY | AT91_PMC_MOSCRCEN); 72 } 73 74 pmc_read(reg, AT91_PMC_SR, &val); 75 while (!(val & AT91_PMC_MOSCRCS)) { 76 pmc_read(reg, AT91_PMC_SR, &val); 77 debug("waiting for main rc...\n"); 78 cpu_relax(); 79 } 80 81 return 0; 82} 83 84static int main_rc_disable(struct clk *clk) 85{ 86 struct clk_main_rc *main_rc = to_clk_main_rc(clk); 87 struct reg *reg = main_rc->reg; 88 unsigned int val; 89 90 pmc_read(reg, AT91_CKGR_MOR, &val); 91 92 if (!(val & AT91_PMC_MOSCRCEN)) 93 return 0; 94 95 pmc_update_bits(reg, AT91_CKGR_MOR, MOR_KEY_MASK | AT91_PMC_MOSCRCEN, 96 AT91_PMC_KEY); 97 98 return 0; 99} 100 101static const struct clk_ops main_rc_clk_ops = { 102 .enable = main_rc_enable, 103 .disable = main_rc_disable, 104 .get_rate = clk_generic_get_rate, 105}; 106 107struct clk *at91_clk_main_rc(void __iomem *reg, const char *name, 108 const char *parent_name) 109{ 110 struct clk_main_rc *main_rc; 111 struct clk *clk; 112 int ret; 113 114 if (!reg || !name || !parent_name) 115 return ERR_PTR(-EINVAL); 116 117 main_rc = kzalloc(sizeof(*main_rc), GFP_KERNEL); 118 if (!main_rc) 119 return ERR_PTR(-ENOMEM); 120 121 main_rc->reg = reg; 122 clk = &main_rc->clk; 123 124 ret = clk_register(clk, UBOOT_DM_CLK_AT91_MAIN_RC, name, 125 parent_name); 126 if (ret) { 127 kfree(main_rc); 128 clk = ERR_PTR(ret); 129 } 130 131 return clk; 132} 133 134U_BOOT_DRIVER(at91_main_rc_clk) = { 135 .name = UBOOT_DM_CLK_AT91_MAIN_RC, 136 .id = UCLASS_CLK, 137 .ops = &main_rc_clk_ops, 138 .flags = DM_FLAG_PRE_RELOC, 139}; 140 141static int clk_main_osc_enable(struct clk *clk) 142{ 143 struct clk_main_osc *main = to_clk_main_osc(clk); 144 void __iomem *reg = main->reg; 145 unsigned int val; 146 147 pmc_read(reg, AT91_CKGR_MOR, &val); 148 val &= ~MOR_KEY_MASK; 149 150 if (val & AT91_PMC_OSCBYPASS) 151 return 0; 152 153 if (!(val & AT91_PMC_MOSCEN)) { 154 val |= AT91_PMC_MOSCEN | AT91_PMC_KEY; 155 pmc_write(reg, AT91_CKGR_MOR, val); 156 } 157 158 pmc_read(reg, AT91_PMC_SR, &val); 159 while (!(val & AT91_PMC_MOSCS)) { 160 pmc_read(reg, AT91_PMC_SR, &val); 161 debug("waiting for main osc..\n"); 162 cpu_relax(); 163 } 164 165 return 0; 166} 167 168static int clk_main_osc_disable(struct clk *clk) 169{ 170 struct clk_main_osc *main = to_clk_main_osc(clk); 171 void __iomem *reg = main->reg; 172 unsigned int val; 173 174 pmc_read(reg, AT91_CKGR_MOR, &val); 175 if (val & AT91_PMC_OSCBYPASS) 176 return 0; 177 178 if (!(val & AT91_PMC_MOSCEN)) 179 return 0; 180 181 val &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); 182 pmc_write(reg, AT91_CKGR_MOR, val | AT91_PMC_KEY); 183 184 return 0; 185} 186 187static const struct clk_ops main_osc_clk_ops = { 188 .enable = clk_main_osc_enable, 189 .disable = clk_main_osc_disable, 190 .get_rate = clk_generic_get_rate, 191}; 192 193struct clk *at91_clk_main_osc(void __iomem *reg, const char *name, 194 const char *parent_name, bool bypass) 195{ 196 struct clk_main_osc *main; 197 struct clk *clk; 198 int ret; 199 200 if (!reg || !name || !parent_name) 201 return ERR_PTR(-EINVAL); 202 203 main = kzalloc(sizeof(*main), GFP_KERNEL); 204 if (!main) 205 return ERR_PTR(-ENOMEM); 206 207 main->reg = reg; 208 clk = &main->clk; 209 210 if (bypass) { 211 pmc_update_bits(reg, AT91_CKGR_MOR, 212 MOR_KEY_MASK | AT91_PMC_OSCBYPASS, 213 AT91_PMC_KEY | AT91_PMC_OSCBYPASS); 214 } 215 216 ret = clk_register(clk, UBOOT_DM_CLK_AT91_MAIN_OSC, name, parent_name); 217 if (ret) { 218 kfree(main); 219 clk = ERR_PTR(ret); 220 } 221 222 return clk; 223} 224 225U_BOOT_DRIVER(at91_main_osc_clk) = { 226 .name = UBOOT_DM_CLK_AT91_MAIN_OSC, 227 .id = UCLASS_CLK, 228 .ops = &main_osc_clk_ops, 229 .flags = DM_FLAG_PRE_RELOC, 230}; 231 232static int clk_main_probe_frequency(void __iomem *reg) 233{ 234 unsigned int cycles = 16; 235 unsigned int cycle = DIV_ROUND_UP(USEC_PER_SEC, SLOW_CLOCK_FREQ); 236 unsigned int mcfr; 237 238 while (cycles--) { 239 pmc_read(reg, AT91_CKGR_MCFR, &mcfr); 240 if (mcfr & AT91_PMC_MAINRDY) 241 return 0; 242 udelay(cycle); 243 } 244 245 return -ETIMEDOUT; 246} 247 248static int clk_rm9200_main_enable(struct clk *clk) 249{ 250 struct clk_main *main = to_clk_main(clk); 251 252 return clk_main_probe_frequency(main->reg); 253} 254 255static const struct clk_ops rm9200_main_clk_ops = { 256 .enable = clk_rm9200_main_enable, 257}; 258 259struct clk *at91_clk_rm9200_main(void __iomem *reg, const char *name, 260 const char *parent_name) 261{ 262 struct clk_main *main; 263 struct clk *clk; 264 int ret; 265 266 if (!reg || !name || !parent_name) 267 return ERR_PTR(-EINVAL); 268 269 main = kzalloc(sizeof(*main), GFP_KERNEL); 270 if (!main) 271 return ERR_PTR(-ENOMEM); 272 273 main->reg = reg; 274 clk = &main->clk; 275 276 ret = clk_register(clk, UBOOT_DM_CLK_AT91_RM9200_MAIN, name, 277 parent_name); 278 if (ret) { 279 kfree(main); 280 clk = ERR_PTR(ret); 281 } 282 283 return clk; 284} 285 286U_BOOT_DRIVER(at91_rm9200_main_clk) = { 287 .name = UBOOT_DM_CLK_AT91_RM9200_MAIN, 288 .id = UCLASS_CLK, 289 .ops = &rm9200_main_clk_ops, 290 .flags = DM_FLAG_PRE_RELOC, 291}; 292 293static inline bool clk_sam9x5_main_ready(void __iomem *reg) 294{ 295 unsigned int val; 296 297 pmc_read(reg, AT91_PMC_SR, &val); 298 299 return !!(val & AT91_PMC_MOSCSELS); 300} 301 302static int clk_sam9x5_main_enable(struct clk *clk) 303{ 304 struct clk_main *main = to_clk_main(clk); 305 void __iomem *reg = main->reg; 306 307 while (!clk_sam9x5_main_ready(reg)) { 308 debug("waiting for main..."); 309 cpu_relax(); 310 } 311 312 return clk_main_probe_frequency(reg); 313} 314 315static int clk_sam9x5_main_set_parent(struct clk *clk, struct clk *parent) 316{ 317 struct clk_main *main = to_clk_main(clk); 318 void __iomem *reg = main->reg; 319 unsigned int tmp, index; 320 321 index = at91_clk_mux_val_to_index(main->clk_mux_table, 322 main->num_parents, AT91_CLK_ID_TO_DID(parent->id)); 323 if (index < 0) 324 return index; 325 326 pmc_read(reg, AT91_CKGR_MOR, &tmp); 327 tmp &= ~MOR_KEY_MASK; 328 tmp |= AT91_PMC_KEY; 329 330 if (index && !(tmp & AT91_PMC_MOSCSEL)) 331 pmc_write(reg, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); 332 else if (!index && (tmp & AT91_PMC_MOSCSEL)) 333 pmc_write(reg, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); 334 335 while (!clk_sam9x5_main_ready(reg)) 336 cpu_relax(); 337 338 return 0; 339} 340 341static const struct clk_ops sam9x5_main_clk_ops = { 342 .enable = clk_sam9x5_main_enable, 343 .set_parent = clk_sam9x5_main_set_parent, 344 .get_rate = clk_generic_get_rate, 345}; 346 347struct clk *at91_clk_sam9x5_main(void __iomem *reg, const char *name, 348 const char * const *parent_names, 349 int num_parents, const u32 *clk_mux_table, 350 int type) 351{ 352 struct clk *clk = ERR_PTR(-ENOMEM); 353 struct clk_main *main = NULL; 354 unsigned int val; 355 int ret; 356 357 if (!reg || !name || !parent_names || !num_parents || !clk_mux_table) 358 return ERR_PTR(-EINVAL); 359 360 main = kzalloc(sizeof(*main), GFP_KERNEL); 361 if (!main) 362 return ERR_PTR(-ENOMEM); 363 364 main->reg = reg; 365 main->parent_names = parent_names; 366 main->num_parents = num_parents; 367 main->clk_mux_table = clk_mux_table; 368 main->type = type; 369 clk = &main->clk; 370 clk->flags = CLK_GET_RATE_NOCACHE; 371 pmc_read(reg, AT91_CKGR_MOR, &val); 372 ret = clk_register(clk, UBOOT_DM_CLK_AT91_SAM9X5_MAIN, name, 373 main->parent_names[clk_main_parent_select(val)]); 374 if (ret) { 375 kfree(main); 376 clk = ERR_PTR(ret); 377 } 378 379 return clk; 380} 381 382U_BOOT_DRIVER(at91_sam9x5_main_clk) = { 383 .name = UBOOT_DM_CLK_AT91_SAM9X5_MAIN, 384 .id = UCLASS_CLK, 385 .ops = &sam9x5_main_clk_ops, 386 .flags = DM_FLAG_PRE_RELOC, 387}; 388