root/drivers/clk/clk-nomadik.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nomadik_clk_reboot_handler
  2. nomadik_src_init
  3. pll_clk_enable
  4. pll_clk_disable
  5. pll_clk_is_enabled
  6. pll_clk_recalc_rate
  7. pll_clk_register
  8. src_clk_enable
  9. src_clk_disable
  10. src_clk_is_enabled
  11. src_clk_recalc_rate
  12. src_clk_register
  13. nomadik_src_clk_debugfs_show
  14. nomadik_src_clk_init_debugfs
  15. of_nomadik_pll_setup
  16. of_nomadik_hclk_setup
  17. of_nomadik_src_clk_setup

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Nomadik clock implementation
   4  * Copyright (C) 2013 ST-Ericsson AB
   5  * Author: Linus Walleij <linus.walleij@linaro.org>
   6  */
   7 
   8 #define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
   9 
  10 #include <linux/bitops.h>
  11 #include <linux/slab.h>
  12 #include <linux/err.h>
  13 #include <linux/io.h>
  14 #include <linux/clk-provider.h>
  15 #include <linux/of.h>
  16 #include <linux/of_address.h>
  17 #include <linux/debugfs.h>
  18 #include <linux/seq_file.h>
  19 #include <linux/spinlock.h>
  20 #include <linux/reboot.h>
  21 
  22 /*
  23  * The Nomadik clock tree is described in the STN8815A12 DB V4.2
  24  * reference manual for the chip, page 94 ff.
  25  * Clock IDs are in the STn8815 Reference Manual table 3, page 27.
  26  */
  27 
  28 #define SRC_CR                  0x00U
  29 #define SRC_CR_T0_ENSEL         BIT(15)
  30 #define SRC_CR_T1_ENSEL         BIT(17)
  31 #define SRC_CR_T2_ENSEL         BIT(19)
  32 #define SRC_CR_T3_ENSEL         BIT(21)
  33 #define SRC_CR_T4_ENSEL         BIT(23)
  34 #define SRC_CR_T5_ENSEL         BIT(25)
  35 #define SRC_CR_T6_ENSEL         BIT(27)
  36 #define SRC_CR_T7_ENSEL         BIT(29)
  37 #define SRC_XTALCR              0x0CU
  38 #define SRC_XTALCR_XTALTIMEN    BIT(20)
  39 #define SRC_XTALCR_SXTALDIS     BIT(19)
  40 #define SRC_XTALCR_MXTALSTAT    BIT(2)
  41 #define SRC_XTALCR_MXTALEN      BIT(1)
  42 #define SRC_XTALCR_MXTALOVER    BIT(0)
  43 #define SRC_PLLCR               0x10U
  44 #define SRC_PLLCR_PLLTIMEN      BIT(29)
  45 #define SRC_PLLCR_PLL2EN        BIT(28)
  46 #define SRC_PLLCR_PLL1STAT      BIT(2)
  47 #define SRC_PLLCR_PLL1EN        BIT(1)
  48 #define SRC_PLLCR_PLL1OVER      BIT(0)
  49 #define SRC_PLLFR               0x14U
  50 #define SRC_PCKEN0              0x24U
  51 #define SRC_PCKDIS0             0x28U
  52 #define SRC_PCKENSR0            0x2CU
  53 #define SRC_PCKSR0              0x30U
  54 #define SRC_PCKEN1              0x34U
  55 #define SRC_PCKDIS1             0x38U
  56 #define SRC_PCKENSR1            0x3CU
  57 #define SRC_PCKSR1              0x40U
  58 
  59 /* Lock protecting the SRC_CR register */
  60 static DEFINE_SPINLOCK(src_lock);
  61 /* Base address of the SRC */
  62 static void __iomem *src_base;
  63 
  64 static int nomadik_clk_reboot_handler(struct notifier_block *this,
  65                                 unsigned long code,
  66                                 void *unused)
  67 {
  68         u32 val;
  69 
  70         /* The main chrystal need to be enabled for reboot to work */
  71         val = readl(src_base + SRC_XTALCR);
  72         val &= ~SRC_XTALCR_MXTALOVER;
  73         val |= SRC_XTALCR_MXTALEN;
  74         pr_crit("force-enabling MXTALO\n");
  75         writel(val, src_base + SRC_XTALCR);
  76         return NOTIFY_OK;
  77 }
  78 
  79 static struct notifier_block nomadik_clk_reboot_notifier = {
  80         .notifier_call = nomadik_clk_reboot_handler,
  81 };
  82 
  83 static const struct of_device_id nomadik_src_match[] __initconst = {
  84         { .compatible = "stericsson,nomadik-src" },
  85         { /* sentinel */ }
  86 };
  87 
  88 static void __init nomadik_src_init(void)
  89 {
  90         struct device_node *np;
  91         u32 val;
  92 
  93         np = of_find_matching_node(NULL, nomadik_src_match);
  94         if (!np) {
  95                 pr_crit("no matching node for SRC, aborting clock init\n");
  96                 return;
  97         }
  98         src_base = of_iomap(np, 0);
  99         if (!src_base) {
 100                 pr_err("%s: must have src parent node with REGS (%pOFn)\n",
 101                        __func__, np);
 102                 return;
 103         }
 104 
 105         /* Set all timers to use the 2.4 MHz TIMCLK */
 106         val = readl(src_base + SRC_CR);
 107         val |= SRC_CR_T0_ENSEL;
 108         val |= SRC_CR_T1_ENSEL;
 109         val |= SRC_CR_T2_ENSEL;
 110         val |= SRC_CR_T3_ENSEL;
 111         val |= SRC_CR_T4_ENSEL;
 112         val |= SRC_CR_T5_ENSEL;
 113         val |= SRC_CR_T6_ENSEL;
 114         val |= SRC_CR_T7_ENSEL;
 115         writel(val, src_base + SRC_CR);
 116 
 117         val = readl(src_base + SRC_XTALCR);
 118         pr_info("SXTALO is %s\n",
 119                 (val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
 120         pr_info("MXTAL is %s\n",
 121                 (val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
 122         if (of_property_read_bool(np, "disable-sxtalo")) {
 123                 /* The machine uses an external oscillator circuit */
 124                 val |= SRC_XTALCR_SXTALDIS;
 125                 pr_info("disabling SXTALO\n");
 126         }
 127         if (of_property_read_bool(np, "disable-mxtalo")) {
 128                 /* Disable this too: also run by external oscillator */
 129                 val |= SRC_XTALCR_MXTALOVER;
 130                 val &= ~SRC_XTALCR_MXTALEN;
 131                 pr_info("disabling MXTALO\n");
 132         }
 133         writel(val, src_base + SRC_XTALCR);
 134         register_reboot_notifier(&nomadik_clk_reboot_notifier);
 135 }
 136 
 137 /**
 138  * struct clk_pll1 - Nomadik PLL1 clock
 139  * @hw: corresponding clock hardware entry
 140  * @id: PLL instance: 1 or 2
 141  */
 142 struct clk_pll {
 143         struct clk_hw hw;
 144         int id;
 145 };
 146 
 147 /**
 148  * struct clk_src - Nomadik src clock
 149  * @hw: corresponding clock hardware entry
 150  * @id: the clock ID
 151  * @group1: true if the clock is in group1, else it is in group0
 152  * @clkbit: bit 0...31 corresponding to the clock in each clock register
 153  */
 154 struct clk_src {
 155         struct clk_hw hw;
 156         int id;
 157         bool group1;
 158         u32 clkbit;
 159 };
 160 
 161 #define to_pll(_hw) container_of(_hw, struct clk_pll, hw)
 162 #define to_src(_hw) container_of(_hw, struct clk_src, hw)
 163 
 164 static int pll_clk_enable(struct clk_hw *hw)
 165 {
 166         struct clk_pll *pll = to_pll(hw);
 167         u32 val;
 168 
 169         spin_lock(&src_lock);
 170         val = readl(src_base + SRC_PLLCR);
 171         if (pll->id == 1) {
 172                 if (val & SRC_PLLCR_PLL1OVER) {
 173                         val |= SRC_PLLCR_PLL1EN;
 174                         writel(val, src_base + SRC_PLLCR);
 175                 }
 176         } else if (pll->id == 2) {
 177                 val |= SRC_PLLCR_PLL2EN;
 178                 writel(val, src_base + SRC_PLLCR);
 179         }
 180         spin_unlock(&src_lock);
 181         return 0;
 182 }
 183 
 184 static void pll_clk_disable(struct clk_hw *hw)
 185 {
 186         struct clk_pll *pll = to_pll(hw);
 187         u32 val;
 188 
 189         spin_lock(&src_lock);
 190         val = readl(src_base + SRC_PLLCR);
 191         if (pll->id == 1) {
 192                 if (val & SRC_PLLCR_PLL1OVER) {
 193                         val &= ~SRC_PLLCR_PLL1EN;
 194                         writel(val, src_base + SRC_PLLCR);
 195                 }
 196         } else if (pll->id == 2) {
 197                 val &= ~SRC_PLLCR_PLL2EN;
 198                 writel(val, src_base + SRC_PLLCR);
 199         }
 200         spin_unlock(&src_lock);
 201 }
 202 
 203 static int pll_clk_is_enabled(struct clk_hw *hw)
 204 {
 205         struct clk_pll *pll = to_pll(hw);
 206         u32 val;
 207 
 208         val = readl(src_base + SRC_PLLCR);
 209         if (pll->id == 1) {
 210                 if (val & SRC_PLLCR_PLL1OVER)
 211                         return !!(val & SRC_PLLCR_PLL1EN);
 212         } else if (pll->id == 2) {
 213                 return !!(val & SRC_PLLCR_PLL2EN);
 214         }
 215         return 1;
 216 }
 217 
 218 static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
 219                                           unsigned long parent_rate)
 220 {
 221         struct clk_pll *pll = to_pll(hw);
 222         u32 val;
 223 
 224         val = readl(src_base + SRC_PLLFR);
 225 
 226         if (pll->id == 1) {
 227                 u8 mul;
 228                 u8 div;
 229 
 230                 mul = (val >> 8) & 0x3FU;
 231                 mul += 2;
 232                 div = val & 0x07U;
 233                 return (parent_rate * mul) >> div;
 234         }
 235 
 236         if (pll->id == 2) {
 237                 u8 mul;
 238 
 239                 mul = (val >> 24) & 0x3FU;
 240                 mul += 2;
 241                 return (parent_rate * mul);
 242         }
 243 
 244         /* Unknown PLL */
 245         return 0;
 246 }
 247 
 248 
 249 static const struct clk_ops pll_clk_ops = {
 250         .enable = pll_clk_enable,
 251         .disable = pll_clk_disable,
 252         .is_enabled = pll_clk_is_enabled,
 253         .recalc_rate = pll_clk_recalc_rate,
 254 };
 255 
 256 static struct clk_hw * __init
 257 pll_clk_register(struct device *dev, const char *name,
 258                  const char *parent_name, u32 id)
 259 {
 260         int ret;
 261         struct clk_pll *pll;
 262         struct clk_init_data init;
 263 
 264         if (id != 1 && id != 2) {
 265                 pr_err("%s: the Nomadik has only PLL 1 & 2\n", __func__);
 266                 return ERR_PTR(-EINVAL);
 267         }
 268 
 269         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 270         if (!pll)
 271                 return ERR_PTR(-ENOMEM);
 272 
 273         init.name = name;
 274         init.ops = &pll_clk_ops;
 275         init.parent_names = (parent_name ? &parent_name : NULL);
 276         init.num_parents = (parent_name ? 1 : 0);
 277         pll->hw.init = &init;
 278         pll->id = id;
 279 
 280         pr_debug("register PLL1 clock \"%s\"\n", name);
 281 
 282         ret = clk_hw_register(dev, &pll->hw);
 283         if (ret) {
 284                 kfree(pll);
 285                 return ERR_PTR(ret);
 286         }
 287 
 288         return &pll->hw;
 289 }
 290 
 291 /*
 292  * The Nomadik SRC clocks are gated, but not in the sense that
 293  * you read-modify-write a register. Instead there are separate
 294  * clock enable and clock disable registers. Writing a '1' bit in
 295  * the enable register for a certain clock ungates that clock without
 296  * affecting the other clocks. The disable register works the opposite
 297  * way.
 298  */
 299 
 300 static int src_clk_enable(struct clk_hw *hw)
 301 {
 302         struct clk_src *sclk = to_src(hw);
 303         u32 enreg = sclk->group1 ? SRC_PCKEN1 : SRC_PCKEN0;
 304         u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
 305 
 306         writel(sclk->clkbit, src_base + enreg);
 307         /* spin until enabled */
 308         while (!(readl(src_base + sreg) & sclk->clkbit))
 309                 cpu_relax();
 310         return 0;
 311 }
 312 
 313 static void src_clk_disable(struct clk_hw *hw)
 314 {
 315         struct clk_src *sclk = to_src(hw);
 316         u32 disreg = sclk->group1 ? SRC_PCKDIS1 : SRC_PCKDIS0;
 317         u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
 318 
 319         writel(sclk->clkbit, src_base + disreg);
 320         /* spin until disabled */
 321         while (readl(src_base + sreg) & sclk->clkbit)
 322                 cpu_relax();
 323 }
 324 
 325 static int src_clk_is_enabled(struct clk_hw *hw)
 326 {
 327         struct clk_src *sclk = to_src(hw);
 328         u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
 329         u32 val = readl(src_base + sreg);
 330 
 331         return !!(val & sclk->clkbit);
 332 }
 333 
 334 static unsigned long
 335 src_clk_recalc_rate(struct clk_hw *hw,
 336                     unsigned long parent_rate)
 337 {
 338         return parent_rate;
 339 }
 340 
 341 static const struct clk_ops src_clk_ops = {
 342         .enable = src_clk_enable,
 343         .disable = src_clk_disable,
 344         .is_enabled = src_clk_is_enabled,
 345         .recalc_rate = src_clk_recalc_rate,
 346 };
 347 
 348 static struct clk_hw * __init
 349 src_clk_register(struct device *dev, const char *name,
 350                  const char *parent_name, u8 id)
 351 {
 352         int ret;
 353         struct clk_src *sclk;
 354         struct clk_init_data init;
 355 
 356         sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
 357         if (!sclk)
 358                 return ERR_PTR(-ENOMEM);
 359 
 360         init.name = name;
 361         init.ops = &src_clk_ops;
 362         /* Do not force-disable the static SDRAM controller */
 363         if (id == 2)
 364                 init.flags = CLK_IGNORE_UNUSED;
 365         else
 366                 init.flags = 0;
 367         init.parent_names = (parent_name ? &parent_name : NULL);
 368         init.num_parents = (parent_name ? 1 : 0);
 369         sclk->hw.init = &init;
 370         sclk->id = id;
 371         sclk->group1 = (id > 31);
 372         sclk->clkbit = BIT(id & 0x1f);
 373 
 374         pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
 375                  name, id, sclk->group1, sclk->clkbit);
 376 
 377         ret = clk_hw_register(dev, &sclk->hw);
 378         if (ret) {
 379                 kfree(sclk);
 380                 return ERR_PTR(ret);
 381         }
 382 
 383         return &sclk->hw;
 384 }
 385 
 386 #ifdef CONFIG_DEBUG_FS
 387 
 388 static u32 src_pcksr0_boot;
 389 static u32 src_pcksr1_boot;
 390 
 391 static const char * const src_clk_names[] = {
 392         "HCLKDMA0  ",
 393         "HCLKSMC   ",
 394         "HCLKSDRAM ",
 395         "HCLKDMA1  ",
 396         "HCLKCLCD  ",
 397         "PCLKIRDA  ",
 398         "PCLKSSP   ",
 399         "PCLKUART0 ",
 400         "PCLKSDI   ",
 401         "PCLKI2C0  ",
 402         "PCLKI2C1  ",
 403         "PCLKUART1 ",
 404         "PCLMSP0   ",
 405         "HCLKUSB   ",
 406         "HCLKDIF   ",
 407         "HCLKSAA   ",
 408         "HCLKSVA   ",
 409         "PCLKHSI   ",
 410         "PCLKXTI   ",
 411         "PCLKUART2 ",
 412         "PCLKMSP1  ",
 413         "PCLKMSP2  ",
 414         "PCLKOWM   ",
 415         "HCLKHPI   ",
 416         "PCLKSKE   ",
 417         "PCLKHSEM  ",
 418         "HCLK3D    ",
 419         "HCLKHASH  ",
 420         "HCLKCRYP  ",
 421         "PCLKMSHC  ",
 422         "HCLKUSBM  ",
 423         "HCLKRNG   ",
 424         "RESERVED  ",
 425         "RESERVED  ",
 426         "RESERVED  ",
 427         "RESERVED  ",
 428         "CLDCLK    ",
 429         "IRDACLK   ",
 430         "SSPICLK   ",
 431         "UART0CLK  ",
 432         "SDICLK    ",
 433         "I2C0CLK   ",
 434         "I2C1CLK   ",
 435         "UART1CLK  ",
 436         "MSPCLK0   ",
 437         "USBCLK    ",
 438         "DIFCLK    ",
 439         "IPI2CCLK  ",
 440         "IPBMCCLK  ",
 441         "HSICLKRX  ",
 442         "HSICLKTX  ",
 443         "UART2CLK  ",
 444         "MSPCLK1   ",
 445         "MSPCLK2   ",
 446         "OWMCLK    ",
 447         "RESERVED  ",
 448         "SKECLK    ",
 449         "RESERVED  ",
 450         "3DCLK     ",
 451         "PCLKMSP3  ",
 452         "MSPCLK3   ",
 453         "MSHCCLK   ",
 454         "USBMCLK   ",
 455         "RNGCCLK   ",
 456 };
 457 
 458 static int nomadik_src_clk_debugfs_show(struct seq_file *s, void *what)
 459 {
 460         int i;
 461         u32 src_pcksr0 = readl(src_base + SRC_PCKSR0);
 462         u32 src_pcksr1 = readl(src_base + SRC_PCKSR1);
 463         u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
 464         u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
 465 
 466         seq_puts(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
 467         for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
 468                 u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
 469                 u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
 470                 u32 pckreq = (i < 0x20) ? src_pckensr0 : src_pckensr1;
 471                 u32 mask = BIT(i & 0x1f);
 472 
 473                 seq_printf(s, "%s  %s     %s     %s\n",
 474                            src_clk_names[i],
 475                            (pcksrb & mask) ? "on " : "off",
 476                            (pcksr & mask) ? "on " : "off",
 477                            (pckreq & mask) ? "on " : "off");
 478         }
 479         return 0;
 480 }
 481 
 482 DEFINE_SHOW_ATTRIBUTE(nomadik_src_clk_debugfs);
 483 
 484 static int __init nomadik_src_clk_init_debugfs(void)
 485 {
 486         /* Vital for multiplatform */
 487         if (!src_base)
 488                 return -ENODEV;
 489         src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
 490         src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
 491         debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
 492                             NULL, NULL, &nomadik_src_clk_debugfs_fops);
 493         return 0;
 494 }
 495 device_initcall(nomadik_src_clk_init_debugfs);
 496 
 497 #endif
 498 
 499 static void __init of_nomadik_pll_setup(struct device_node *np)
 500 {
 501         struct clk_hw *hw;
 502         const char *clk_name = np->name;
 503         const char *parent_name;
 504         u32 pll_id;
 505 
 506         if (!src_base)
 507                 nomadik_src_init();
 508 
 509         if (of_property_read_u32(np, "pll-id", &pll_id)) {
 510                 pr_err("%s: PLL \"%s\" missing pll-id property\n",
 511                         __func__, clk_name);
 512                 return;
 513         }
 514         parent_name = of_clk_get_parent_name(np, 0);
 515         hw = pll_clk_register(NULL, clk_name, parent_name, pll_id);
 516         if (!IS_ERR(hw))
 517                 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 518 }
 519 CLK_OF_DECLARE(nomadik_pll_clk,
 520         "st,nomadik-pll-clock", of_nomadik_pll_setup);
 521 
 522 static void __init of_nomadik_hclk_setup(struct device_node *np)
 523 {
 524         struct clk_hw *hw;
 525         const char *clk_name = np->name;
 526         const char *parent_name;
 527 
 528         if (!src_base)
 529                 nomadik_src_init();
 530 
 531         parent_name = of_clk_get_parent_name(np, 0);
 532         /*
 533          * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
 534          */
 535         hw = clk_hw_register_divider(NULL, clk_name, parent_name,
 536                            0, src_base + SRC_CR,
 537                            13, 2,
 538                            CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
 539                            &src_lock);
 540         if (!IS_ERR(hw))
 541                 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 542 }
 543 CLK_OF_DECLARE(nomadik_hclk_clk,
 544         "st,nomadik-hclk-clock", of_nomadik_hclk_setup);
 545 
 546 static void __init of_nomadik_src_clk_setup(struct device_node *np)
 547 {
 548         struct clk_hw *hw;
 549         const char *clk_name = np->name;
 550         const char *parent_name;
 551         u32 clk_id;
 552 
 553         if (!src_base)
 554                 nomadik_src_init();
 555 
 556         if (of_property_read_u32(np, "clock-id", &clk_id)) {
 557                 pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
 558                         __func__, clk_name);
 559                 return;
 560         }
 561         parent_name = of_clk_get_parent_name(np, 0);
 562         hw = src_clk_register(NULL, clk_name, parent_name, clk_id);
 563         if (!IS_ERR(hw))
 564                 of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
 565 }
 566 CLK_OF_DECLARE(nomadik_src_clk,
 567         "st,nomadik-src-clock", of_nomadik_src_clk_setup);

/* [<][>][^][v][top][bottom][index][help] */