linux/drivers/clk/ingenic/x1000-cgu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * X1000 SoC CGU driver
   4 * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
   5 */
   6
   7#include <linux/clk-provider.h>
   8#include <linux/delay.h>
   9#include <linux/io.h>
  10#include <linux/of.h>
  11
  12#include <dt-bindings/clock/x1000-cgu.h>
  13
  14#include "cgu.h"
  15#include "pm.h"
  16
  17/* CGU register offsets */
  18#define CGU_REG_CPCCR           0x00
  19#define CGU_REG_APLL            0x10
  20#define CGU_REG_MPLL            0x14
  21#define CGU_REG_CLKGR           0x20
  22#define CGU_REG_OPCR            0x24
  23#define CGU_REG_DDRCDR          0x2c
  24#define CGU_REG_USBPCR          0x3c
  25#define CGU_REG_USBPCR1         0x48
  26#define CGU_REG_USBCDR          0x50
  27#define CGU_REG_MACCDR          0x54
  28#define CGU_REG_I2SCDR          0x60
  29#define CGU_REG_LPCDR           0x64
  30#define CGU_REG_MSC0CDR         0x68
  31#define CGU_REG_I2SCDR1         0x70
  32#define CGU_REG_SSICDR          0x74
  33#define CGU_REG_CIMCDR          0x7c
  34#define CGU_REG_PCMCDR          0x84
  35#define CGU_REG_MSC1CDR         0xa4
  36#define CGU_REG_CMP_INTR        0xb0
  37#define CGU_REG_CMP_INTRE       0xb4
  38#define CGU_REG_DRCG            0xd0
  39#define CGU_REG_CPCSR           0xd4
  40#define CGU_REG_PCMCDR1         0xe0
  41#define CGU_REG_MACPHYC         0xe8
  42
  43/* bits within the OPCR register */
  44#define OPCR_SPENDN0            BIT(7)
  45#define OPCR_SPENDN1            BIT(6)
  46
  47/* bits within the USBPCR register */
  48#define USBPCR_SIDDQ            BIT(21)
  49#define USBPCR_OTG_DISABLE      BIT(20)
  50
  51/* bits within the USBPCR1 register */
  52#define USBPCR1_REFCLKSEL_SHIFT 26
  53#define USBPCR1_REFCLKSEL_MASK  (0x3 << USBPCR1_REFCLKSEL_SHIFT)
  54#define USBPCR1_REFCLKSEL_CORE  (0x2 << USBPCR1_REFCLKSEL_SHIFT)
  55#define USBPCR1_REFCLKDIV_SHIFT 24
  56#define USBPCR1_REFCLKDIV_MASK  (0x3 << USBPCR1_REFCLKDIV_SHIFT)
  57#define USBPCR1_REFCLKDIV_48    (0x2 << USBPCR1_REFCLKDIV_SHIFT)
  58#define USBPCR1_REFCLKDIV_24    (0x1 << USBPCR1_REFCLKDIV_SHIFT)
  59#define USBPCR1_REFCLKDIV_12    (0x0 << USBPCR1_REFCLKDIV_SHIFT)
  60
  61static struct ingenic_cgu *cgu;
  62
  63static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw,
  64                                                unsigned long parent_rate)
  65{
  66        u32 usbpcr1;
  67        unsigned refclk_div;
  68
  69        usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
  70        refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
  71
  72        switch (refclk_div) {
  73        case USBPCR1_REFCLKDIV_12:
  74                return 12000000;
  75
  76        case USBPCR1_REFCLKDIV_24:
  77                return 24000000;
  78
  79        case USBPCR1_REFCLKDIV_48:
  80                return 48000000;
  81        }
  82
  83        return parent_rate;
  84}
  85
  86static long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
  87                                      unsigned long *parent_rate)
  88{
  89        if (req_rate < 18000000)
  90                return 12000000;
  91
  92        if (req_rate < 36000000)
  93                return 24000000;
  94
  95        return 48000000;
  96}
  97
  98static int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
  99                                   unsigned long parent_rate)
 100{
 101        unsigned long flags;
 102        u32 usbpcr1, div_bits;
 103
 104        switch (req_rate) {
 105        case 12000000:
 106                div_bits = USBPCR1_REFCLKDIV_12;
 107                break;
 108
 109        case 24000000:
 110                div_bits = USBPCR1_REFCLKDIV_24;
 111                break;
 112
 113        case 48000000:
 114                div_bits = USBPCR1_REFCLKDIV_48;
 115                break;
 116
 117        default:
 118                return -EINVAL;
 119        }
 120
 121        spin_lock_irqsave(&cgu->lock, flags);
 122
 123        usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
 124        usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
 125        usbpcr1 |= div_bits;
 126        writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
 127
 128        spin_unlock_irqrestore(&cgu->lock, flags);
 129        return 0;
 130}
 131
 132static int x1000_usb_phy_enable(struct clk_hw *hw)
 133{
 134        void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
 135        void __iomem *reg_usbpcr        = cgu->base + CGU_REG_USBPCR;
 136
 137        writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
 138        writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
 139        return 0;
 140}
 141
 142static void x1000_usb_phy_disable(struct clk_hw *hw)
 143{
 144        void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
 145        void __iomem *reg_usbpcr        = cgu->base + CGU_REG_USBPCR;
 146
 147        writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
 148        writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
 149}
 150
 151static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
 152{
 153        void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
 154        void __iomem *reg_usbpcr        = cgu->base + CGU_REG_USBPCR;
 155
 156        return (readl(reg_opcr) & OPCR_SPENDN0) &&
 157                !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
 158                !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
 159}
 160
 161static const struct clk_ops x1000_otg_phy_ops = {
 162        .recalc_rate = x1000_otg_phy_recalc_rate,
 163        .round_rate = x1000_otg_phy_round_rate,
 164        .set_rate = x1000_otg_phy_set_rate,
 165
 166        .enable         = x1000_usb_phy_enable,
 167        .disable        = x1000_usb_phy_disable,
 168        .is_enabled     = x1000_usb_phy_is_enabled,
 169};
 170
 171static const s8 pll_od_encoding[8] = {
 172        0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
 173};
 174
 175static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
 176
 177        /* External clocks */
 178
 179        [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
 180        [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
 181
 182        /* PLLs */
 183
 184        [X1000_CLK_APLL] = {
 185                "apll", CGU_CLK_PLL,
 186                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 187                .pll = {
 188                        .reg = CGU_REG_APLL,
 189                        .rate_multiplier = 1,
 190                        .m_shift = 24,
 191                        .m_bits = 7,
 192                        .m_offset = 1,
 193                        .n_shift = 18,
 194                        .n_bits = 5,
 195                        .n_offset = 1,
 196                        .od_shift = 16,
 197                        .od_bits = 2,
 198                        .od_max = 8,
 199                        .od_encoding = pll_od_encoding,
 200                        .bypass_reg = CGU_REG_APLL,
 201                        .bypass_bit = 9,
 202                        .enable_bit = 8,
 203                        .stable_bit = 10,
 204                },
 205        },
 206
 207        [X1000_CLK_MPLL] = {
 208                "mpll", CGU_CLK_PLL,
 209                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 210                .pll = {
 211                        .reg = CGU_REG_MPLL,
 212                        .rate_multiplier = 1,
 213                        .m_shift = 24,
 214                        .m_bits = 7,
 215                        .m_offset = 1,
 216                        .n_shift = 18,
 217                        .n_bits = 5,
 218                        .n_offset = 1,
 219                        .od_shift = 16,
 220                        .od_bits = 2,
 221                        .od_max = 8,
 222                        .od_encoding = pll_od_encoding,
 223                        .bypass_reg = CGU_REG_MPLL,
 224                        .bypass_bit = 6,
 225                        .enable_bit = 7,
 226                        .stable_bit = 0,
 227                },
 228        },
 229
 230        /* Custom (SoC-specific) OTG PHY */
 231
 232        [X1000_CLK_OTGPHY] = {
 233                "otg_phy", CGU_CLK_CUSTOM,
 234                .parents = { -1, -1, X1000_CLK_EXCLK, -1 },
 235                .custom = { &x1000_otg_phy_ops },
 236        },
 237
 238        /* Muxes & dividers */
 239
 240        [X1000_CLK_SCLKA] = {
 241                "sclk_a", CGU_CLK_MUX,
 242                .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 },
 243                .mux = { CGU_REG_CPCCR, 30, 2 },
 244        },
 245
 246        [X1000_CLK_CPUMUX] = {
 247                "cpu_mux", CGU_CLK_MUX,
 248                .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
 249                .mux = { CGU_REG_CPCCR, 28, 2 },
 250        },
 251
 252        [X1000_CLK_CPU] = {
 253                "cpu", CGU_CLK_DIV | CGU_CLK_GATE,
 254                .parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
 255                .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
 256                .gate = { CGU_REG_CLKGR, 30 },
 257        },
 258
 259        [X1000_CLK_L2CACHE] = {
 260                "l2cache", CGU_CLK_DIV,
 261                .parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
 262                .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
 263        },
 264
 265        [X1000_CLK_AHB0] = {
 266                "ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
 267                .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
 268                .mux = { CGU_REG_CPCCR, 26, 2 },
 269                .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
 270        },
 271
 272        [X1000_CLK_AHB2PMUX] = {
 273                "ahb2_apb_mux", CGU_CLK_MUX,
 274                .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
 275                .mux = { CGU_REG_CPCCR, 24, 2 },
 276        },
 277
 278        [X1000_CLK_AHB2] = {
 279                "ahb2", CGU_CLK_DIV,
 280                .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
 281                .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
 282        },
 283
 284        [X1000_CLK_PCLK] = {
 285                "pclk", CGU_CLK_DIV | CGU_CLK_GATE,
 286                .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
 287                .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
 288                .gate = { CGU_REG_CLKGR, 28 },
 289        },
 290
 291        [X1000_CLK_DDR] = {
 292                "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 293                .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
 294                .mux = { CGU_REG_DDRCDR, 30, 2 },
 295                .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
 296                .gate = { CGU_REG_CLKGR, 31 },
 297        },
 298
 299        [X1000_CLK_MAC] = {
 300                "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 301                .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
 302                .mux = { CGU_REG_MACCDR, 31, 1 },
 303                .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
 304                .gate = { CGU_REG_CLKGR, 25 },
 305        },
 306
 307        [X1000_CLK_LCD] = {
 308                "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 309                .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
 310                .mux = { CGU_REG_LPCDR, 31, 1 },
 311                .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
 312                .gate = { CGU_REG_CLKGR, 23 },
 313        },
 314
 315        [X1000_CLK_MSCMUX] = {
 316                "msc_mux", CGU_CLK_MUX,
 317                .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
 318                .mux = { CGU_REG_MSC0CDR, 31, 1 },
 319        },
 320
 321        [X1000_CLK_MSC0] = {
 322                "msc0", CGU_CLK_DIV | CGU_CLK_GATE,
 323                .parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
 324                .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
 325                .gate = { CGU_REG_CLKGR, 4 },
 326        },
 327
 328        [X1000_CLK_MSC1] = {
 329                "msc1", CGU_CLK_DIV | CGU_CLK_GATE,
 330                .parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
 331                .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
 332                .gate = { CGU_REG_CLKGR, 5 },
 333        },
 334
 335        [X1000_CLK_OTG] = {
 336                "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 337                .parents = { X1000_CLK_EXCLK, -1,
 338                                         X1000_CLK_APLL, X1000_CLK_MPLL },
 339                .mux = { CGU_REG_USBCDR, 30, 2 },
 340                .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
 341                .gate = { CGU_REG_CLKGR, 3 },
 342        },
 343
 344        [X1000_CLK_SSIPLL] = {
 345                "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
 346                .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
 347                .mux = { CGU_REG_SSICDR, 31, 1 },
 348                .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
 349        },
 350
 351        [X1000_CLK_SSIPLL_DIV2] = {
 352                "ssi_pll_div2", CGU_CLK_FIXDIV,
 353                .parents = { X1000_CLK_SSIPLL },
 354                .fixdiv = { 2 },
 355        },
 356
 357        [X1000_CLK_SSIMUX] = {
 358                "ssi_mux", CGU_CLK_MUX,
 359                .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
 360                .mux = { CGU_REG_SSICDR, 30, 1 },
 361        },
 362
 363        [X1000_CLK_EXCLK_DIV512] = {
 364                "exclk_div512", CGU_CLK_FIXDIV,
 365                .parents = { X1000_CLK_EXCLK },
 366                .fixdiv = { 512 },
 367        },
 368
 369        [X1000_CLK_RTC] = {
 370                "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
 371                .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK },
 372                .mux = { CGU_REG_OPCR, 2, 1},
 373                .gate = { CGU_REG_CLKGR, 27 },
 374        },
 375
 376        /* Gate-only clocks */
 377
 378        [X1000_CLK_EMC] = {
 379                "emc", CGU_CLK_GATE,
 380                .parents = { X1000_CLK_AHB2, -1, -1, -1 },
 381                .gate = { CGU_REG_CLKGR, 0 },
 382        },
 383
 384        [X1000_CLK_EFUSE] = {
 385                "efuse", CGU_CLK_GATE,
 386                .parents = { X1000_CLK_AHB2, -1, -1, -1 },
 387                .gate = { CGU_REG_CLKGR, 1 },
 388        },
 389
 390        [X1000_CLK_SFC] = {
 391                "sfc", CGU_CLK_GATE,
 392                .parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
 393                .gate = { CGU_REG_CLKGR, 2 },
 394        },
 395
 396        [X1000_CLK_I2C0] = {
 397                "i2c0", CGU_CLK_GATE,
 398                .parents = { X1000_CLK_PCLK, -1, -1, -1 },
 399                .gate = { CGU_REG_CLKGR, 7 },
 400        },
 401
 402        [X1000_CLK_I2C1] = {
 403                "i2c1", CGU_CLK_GATE,
 404                .parents = { X1000_CLK_PCLK, -1, -1, -1 },
 405                .gate = { CGU_REG_CLKGR, 8 },
 406        },
 407
 408        [X1000_CLK_I2C2] = {
 409                "i2c2", CGU_CLK_GATE,
 410                .parents = { X1000_CLK_PCLK, -1, -1, -1 },
 411                .gate = { CGU_REG_CLKGR, 9 },
 412        },
 413
 414        [X1000_CLK_UART0] = {
 415                "uart0", CGU_CLK_GATE,
 416                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 417                .gate = { CGU_REG_CLKGR, 14 },
 418        },
 419
 420        [X1000_CLK_UART1] = {
 421                "uart1", CGU_CLK_GATE,
 422                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 423                .gate = { CGU_REG_CLKGR, 15 },
 424        },
 425
 426        [X1000_CLK_UART2] = {
 427                "uart2", CGU_CLK_GATE,
 428                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 429                .gate = { CGU_REG_CLKGR, 16 },
 430        },
 431
 432        [X1000_CLK_TCU] = {
 433                "tcu", CGU_CLK_GATE,
 434                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 435                .gate = { CGU_REG_CLKGR, 18 },
 436        },
 437
 438        [X1000_CLK_SSI] = {
 439                "ssi", CGU_CLK_GATE,
 440                .parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
 441                .gate = { CGU_REG_CLKGR, 19 },
 442        },
 443
 444        [X1000_CLK_OST] = {
 445                "ost", CGU_CLK_GATE,
 446                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 447                .gate = { CGU_REG_CLKGR, 20 },
 448        },
 449
 450        [X1000_CLK_PDMA] = {
 451                "pdma", CGU_CLK_GATE,
 452                .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
 453                .gate = { CGU_REG_CLKGR, 21 },
 454        },
 455};
 456
 457static void __init x1000_cgu_init(struct device_node *np)
 458{
 459        int retval;
 460
 461        cgu = ingenic_cgu_new(x1000_cgu_clocks,
 462                              ARRAY_SIZE(x1000_cgu_clocks), np);
 463        if (!cgu) {
 464                pr_err("%s: failed to initialise CGU\n", __func__);
 465                return;
 466        }
 467
 468        retval = ingenic_cgu_register_clocks(cgu);
 469        if (retval) {
 470                pr_err("%s: failed to register CGU Clocks\n", __func__);
 471                return;
 472        }
 473
 474        ingenic_cgu_register_syscore_ops(cgu);
 475}
 476/*
 477 * CGU has some children devices, this is useful for probing children devices
 478 * in the case where the device node is compatible with "simple-mfd".
 479 */
 480CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);
 481