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/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 */
  60static DEFINE_SPINLOCK(src_lock);
  61/* Base address of the SRC */
  62static void __iomem *src_base;
  63
  64static 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
  79static struct notifier_block nomadik_clk_reboot_notifier = {
  80        .notifier_call = nomadik_clk_reboot_handler,
  81};
  82
  83static const struct of_device_id nomadik_src_match[] __initconst = {
  84        { .compatible = "stericsson,nomadik-src" },
  85        { /* sentinel */ }
  86};
  87
  88static 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 (%s)\n",
 101                       __func__, np->name);
 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 */
 142struct 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 */
 154struct 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
 164static 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
 184static 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
 203static 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
 218static 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
 249static 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
 256static struct clk * __init
 257pll_clk_register(struct device *dev, const char *name,
 258                 const char *parent_name, u32 id)
 259{
 260        struct clk *clk;
 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                pr_err("%s: could not allocate PLL clk\n", __func__);
 272                return ERR_PTR(-ENOMEM);
 273        }
 274
 275        init.name = name;
 276        init.ops = &pll_clk_ops;
 277        init.parent_names = (parent_name ? &parent_name : NULL);
 278        init.num_parents = (parent_name ? 1 : 0);
 279        pll->hw.init = &init;
 280        pll->id = id;
 281
 282        pr_debug("register PLL1 clock \"%s\"\n", name);
 283
 284        clk = clk_register(dev, &pll->hw);
 285        if (IS_ERR(clk))
 286                kfree(pll);
 287
 288        return clk;
 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
 300static 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
 313static 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
 325static 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
 334static unsigned long
 335src_clk_recalc_rate(struct clk_hw *hw,
 336                    unsigned long parent_rate)
 337{
 338        return parent_rate;
 339}
 340
 341static 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
 348static struct clk * __init
 349src_clk_register(struct device *dev, const char *name,
 350                 const char *parent_name, u8 id)
 351{
 352        struct clk *clk;
 353        struct clk_src *sclk;
 354        struct clk_init_data init;
 355
 356        sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
 357        if (!sclk) {
 358                pr_err("could not allocate SRC clock %s\n",
 359                        name);
 360                return ERR_PTR(-ENOMEM);
 361        }
 362        init.name = name;
 363        init.ops = &src_clk_ops;
 364        /* Do not force-disable the static SDRAM controller */
 365        if (id == 2)
 366                init.flags = CLK_IGNORE_UNUSED;
 367        else
 368                init.flags = 0;
 369        init.parent_names = (parent_name ? &parent_name : NULL);
 370        init.num_parents = (parent_name ? 1 : 0);
 371        sclk->hw.init = &init;
 372        sclk->id = id;
 373        sclk->group1 = (id > 31);
 374        sclk->clkbit = BIT(id & 0x1f);
 375
 376        pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
 377                 name, id, sclk->group1, sclk->clkbit);
 378
 379        clk = clk_register(dev, &sclk->hw);
 380        if (IS_ERR(clk))
 381                kfree(sclk);
 382
 383        return clk;
 384}
 385
 386#ifdef CONFIG_DEBUG_FS
 387
 388static u32 src_pcksr0_boot;
 389static u32 src_pcksr1_boot;
 390
 391static 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
 458static int nomadik_src_clk_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_printf(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
 482static int nomadik_src_clk_open(struct inode *inode, struct file *file)
 483{
 484        return single_open(file, nomadik_src_clk_show, NULL);
 485}
 486
 487static const struct file_operations nomadik_src_clk_debugfs_ops = {
 488        .open           = nomadik_src_clk_open,
 489        .read           = seq_read,
 490        .llseek         = seq_lseek,
 491        .release        = single_release,
 492};
 493
 494static int __init nomadik_src_clk_init_debugfs(void)
 495{
 496        /* Vital for multiplatform */
 497        if (!src_base)
 498                return -ENODEV;
 499        src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
 500        src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
 501        debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
 502                            NULL, NULL, &nomadik_src_clk_debugfs_ops);
 503        return 0;
 504}
 505device_initcall(nomadik_src_clk_init_debugfs);
 506
 507#endif
 508
 509static void __init of_nomadik_pll_setup(struct device_node *np)
 510{
 511        struct clk *clk = ERR_PTR(-EINVAL);
 512        const char *clk_name = np->name;
 513        const char *parent_name;
 514        u32 pll_id;
 515
 516        if (!src_base)
 517                nomadik_src_init();
 518
 519        if (of_property_read_u32(np, "pll-id", &pll_id)) {
 520                pr_err("%s: PLL \"%s\" missing pll-id property\n",
 521                        __func__, clk_name);
 522                return;
 523        }
 524        parent_name = of_clk_get_parent_name(np, 0);
 525        clk = pll_clk_register(NULL, clk_name, parent_name, pll_id);
 526        if (!IS_ERR(clk))
 527                of_clk_add_provider(np, of_clk_src_simple_get, clk);
 528}
 529CLK_OF_DECLARE(nomadik_pll_clk,
 530        "st,nomadik-pll-clock", of_nomadik_pll_setup);
 531
 532static void __init of_nomadik_hclk_setup(struct device_node *np)
 533{
 534        struct clk *clk = ERR_PTR(-EINVAL);
 535        const char *clk_name = np->name;
 536        const char *parent_name;
 537
 538        if (!src_base)
 539                nomadik_src_init();
 540
 541        parent_name = of_clk_get_parent_name(np, 0);
 542        /*
 543         * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
 544         */
 545        clk = clk_register_divider(NULL, clk_name, parent_name,
 546                           0, src_base + SRC_CR,
 547                           13, 2,
 548                           CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
 549                           &src_lock);
 550        if (!IS_ERR(clk))
 551                of_clk_add_provider(np, of_clk_src_simple_get, clk);
 552}
 553CLK_OF_DECLARE(nomadik_hclk_clk,
 554        "st,nomadik-hclk-clock", of_nomadik_hclk_setup);
 555
 556static void __init of_nomadik_src_clk_setup(struct device_node *np)
 557{
 558        struct clk *clk = ERR_PTR(-EINVAL);
 559        const char *clk_name = np->name;
 560        const char *parent_name;
 561        u32 clk_id;
 562
 563        if (!src_base)
 564                nomadik_src_init();
 565
 566        if (of_property_read_u32(np, "clock-id", &clk_id)) {
 567                pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
 568                        __func__, clk_name);
 569                return;
 570        }
 571        parent_name = of_clk_get_parent_name(np, 0);
 572        clk = src_clk_register(NULL, clk_name, parent_name, clk_id);
 573        if (!IS_ERR(clk))
 574                of_clk_add_provider(np, of_clk_src_simple_get, clk);
 575}
 576CLK_OF_DECLARE(nomadik_src_clk,
 577        "st,nomadik-src-clock", of_nomadik_src_clk_setup);
 578