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