root/drivers/clk/ingenic/jz4770-cgu.c

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

DEFINITIONS

This source file includes following definitions.
  1. jz4770_uhc_phy_enable
  2. jz4770_uhc_phy_disable
  3. jz4770_uhc_phy_is_enabled
  4. jz4770_cgu_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * JZ4770 SoC CGU driver
   4  * Copyright 2018, Paul Cercueil <paul@crapouillou.net>
   5  */
   6 
   7 #include <linux/bitops.h>
   8 #include <linux/clk-provider.h>
   9 #include <linux/delay.h>
  10 #include <linux/io.h>
  11 #include <linux/of.h>
  12 #include <dt-bindings/clock/jz4770-cgu.h>
  13 #include "cgu.h"
  14 #include "pm.h"
  15 
  16 /*
  17  * CPM registers offset address definition
  18  */
  19 #define CGU_REG_CPCCR           0x00
  20 #define CGU_REG_LCR             0x04
  21 #define CGU_REG_CPPCR0          0x10
  22 #define CGU_REG_CLKGR0          0x20
  23 #define CGU_REG_OPCR            0x24
  24 #define CGU_REG_CLKGR1          0x28
  25 #define CGU_REG_CPPCR1          0x30
  26 #define CGU_REG_USBPCR1         0x48
  27 #define CGU_REG_USBCDR          0x50
  28 #define CGU_REG_I2SCDR          0x60
  29 #define CGU_REG_LPCDR           0x64
  30 #define CGU_REG_MSC0CDR         0x68
  31 #define CGU_REG_UHCCDR          0x6c
  32 #define CGU_REG_SSICDR          0x74
  33 #define CGU_REG_CIMCDR          0x7c
  34 #define CGU_REG_GPSCDR          0x80
  35 #define CGU_REG_PCMCDR          0x84
  36 #define CGU_REG_GPUCDR          0x88
  37 #define CGU_REG_MSC1CDR         0xA4
  38 #define CGU_REG_MSC2CDR         0xA8
  39 #define CGU_REG_BCHCDR          0xAC
  40 
  41 /* bits within the OPCR register */
  42 #define OPCR_SPENDH             BIT(5)          /* UHC PHY suspend */
  43 
  44 /* bits within the USBPCR1 register */
  45 #define USBPCR1_UHC_POWER       BIT(5)          /* UHC PHY power down */
  46 
  47 static struct ingenic_cgu *cgu;
  48 
  49 static int jz4770_uhc_phy_enable(struct clk_hw *hw)
  50 {
  51         void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
  52         void __iomem *reg_usbpcr1       = cgu->base + CGU_REG_USBPCR1;
  53 
  54         writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr);
  55         writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1);
  56         return 0;
  57 }
  58 
  59 static void jz4770_uhc_phy_disable(struct clk_hw *hw)
  60 {
  61         void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
  62         void __iomem *reg_usbpcr1       = cgu->base + CGU_REG_USBPCR1;
  63 
  64         writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1);
  65         writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr);
  66 }
  67 
  68 static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw)
  69 {
  70         void __iomem *reg_opcr          = cgu->base + CGU_REG_OPCR;
  71         void __iomem *reg_usbpcr1       = cgu->base + CGU_REG_USBPCR1;
  72 
  73         return !(readl(reg_opcr) & OPCR_SPENDH) &&
  74                 (readl(reg_usbpcr1) & USBPCR1_UHC_POWER);
  75 }
  76 
  77 static const struct clk_ops jz4770_uhc_phy_ops = {
  78         .enable = jz4770_uhc_phy_enable,
  79         .disable = jz4770_uhc_phy_disable,
  80         .is_enabled = jz4770_uhc_phy_is_enabled,
  81 };
  82 
  83 static const s8 pll_od_encoding[8] = {
  84         0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
  85 };
  86 
  87 static const u8 jz4770_cgu_cpccr_div_table[] = {
  88         1, 2, 3, 4, 6, 8, 12,
  89 };
  90 
  91 static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
  92 
  93         /* External clocks */
  94 
  95         [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT },
  96         [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
  97 
  98         /* PLLs */
  99 
 100         [JZ4770_CLK_PLL0] = {
 101                 "pll0", CGU_CLK_PLL,
 102                 .parents = { JZ4770_CLK_EXT },
 103                 .pll = {
 104                         .reg = CGU_REG_CPPCR0,
 105                         .m_shift = 24,
 106                         .m_bits = 7,
 107                         .m_offset = 1,
 108                         .n_shift = 18,
 109                         .n_bits = 5,
 110                         .n_offset = 1,
 111                         .od_shift = 16,
 112                         .od_bits = 2,
 113                         .od_max = 8,
 114                         .od_encoding = pll_od_encoding,
 115                         .bypass_bit = 9,
 116                         .enable_bit = 8,
 117                         .stable_bit = 10,
 118                 },
 119         },
 120 
 121         [JZ4770_CLK_PLL1] = {
 122                 /* TODO: PLL1 can depend on PLL0 */
 123                 "pll1", CGU_CLK_PLL,
 124                 .parents = { JZ4770_CLK_EXT },
 125                 .pll = {
 126                         .reg = CGU_REG_CPPCR1,
 127                         .m_shift = 24,
 128                         .m_bits = 7,
 129                         .m_offset = 1,
 130                         .n_shift = 18,
 131                         .n_bits = 5,
 132                         .n_offset = 1,
 133                         .od_shift = 16,
 134                         .od_bits = 2,
 135                         .od_max = 8,
 136                         .od_encoding = pll_od_encoding,
 137                         .enable_bit = 7,
 138                         .stable_bit = 6,
 139                         .no_bypass_bit = true,
 140                 },
 141         },
 142 
 143         /* Main clocks */
 144 
 145         [JZ4770_CLK_CCLK] = {
 146                 "cclk", CGU_CLK_DIV,
 147                 .parents = { JZ4770_CLK_PLL0, },
 148                 .div = {
 149                         CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
 150                         jz4770_cgu_cpccr_div_table,
 151                 },
 152         },
 153         [JZ4770_CLK_H0CLK] = {
 154                 "h0clk", CGU_CLK_DIV,
 155                 .parents = { JZ4770_CLK_PLL0, },
 156                 .div = {
 157                         CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
 158                         jz4770_cgu_cpccr_div_table,
 159                 },
 160         },
 161         [JZ4770_CLK_H1CLK] = {
 162                 "h1clk", CGU_CLK_DIV | CGU_CLK_GATE,
 163                 .parents = { JZ4770_CLK_PLL0, },
 164                 .div = {
 165                         CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1,
 166                         jz4770_cgu_cpccr_div_table,
 167                 },
 168                 .gate = { CGU_REG_CLKGR1, 7 },
 169         },
 170         [JZ4770_CLK_H2CLK] = {
 171                 "h2clk", CGU_CLK_DIV,
 172                 .parents = { JZ4770_CLK_PLL0, },
 173                 .div = {
 174                         CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1,
 175                         jz4770_cgu_cpccr_div_table,
 176                 },
 177         },
 178         [JZ4770_CLK_C1CLK] = {
 179                 "c1clk", CGU_CLK_DIV | CGU_CLK_GATE,
 180                 .parents = { JZ4770_CLK_PLL0, },
 181                 .div = {
 182                         CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
 183                         jz4770_cgu_cpccr_div_table,
 184                 },
 185                 .gate = { CGU_REG_OPCR, 31, true }, // disable CCLK stop on idle
 186         },
 187         [JZ4770_CLK_PCLK] = {
 188                 "pclk", CGU_CLK_DIV,
 189                 .parents = { JZ4770_CLK_PLL0, },
 190                 .div = {
 191                         CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
 192                         jz4770_cgu_cpccr_div_table,
 193                 },
 194         },
 195 
 196         /* Those divided clocks can connect to PLL0 or PLL1 */
 197 
 198         [JZ4770_CLK_MMC0_MUX] = {
 199                 "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 200                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 201                 .mux = { CGU_REG_MSC0CDR, 30, 1 },
 202                 .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 },
 203                 .gate = { CGU_REG_MSC0CDR, 31 },
 204         },
 205         [JZ4770_CLK_MMC1_MUX] = {
 206                 "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 207                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 208                 .mux = { CGU_REG_MSC1CDR, 30, 1 },
 209                 .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 },
 210                 .gate = { CGU_REG_MSC1CDR, 31 },
 211         },
 212         [JZ4770_CLK_MMC2_MUX] = {
 213                 "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 214                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 215                 .mux = { CGU_REG_MSC2CDR, 30, 1 },
 216                 .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 },
 217                 .gate = { CGU_REG_MSC2CDR, 31 },
 218         },
 219         [JZ4770_CLK_CIM] = {
 220                 "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 221                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 222                 .mux = { CGU_REG_CIMCDR, 31, 1 },
 223                 .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
 224                 .gate = { CGU_REG_CLKGR0, 26 },
 225         },
 226         [JZ4770_CLK_UHC] = {
 227                 "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 228                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 229                 .mux = { CGU_REG_UHCCDR, 29, 1 },
 230                 .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
 231                 .gate = { CGU_REG_CLKGR0, 24 },
 232         },
 233         [JZ4770_CLK_GPU] = {
 234                 "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 235                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 },
 236                 .mux = { CGU_REG_GPUCDR, 31, 1 },
 237                 .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
 238                 .gate = { CGU_REG_CLKGR1, 9 },
 239         },
 240         [JZ4770_CLK_BCH] = {
 241                 "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 242                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 243                 .mux = { CGU_REG_BCHCDR, 31, 1 },
 244                 .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 },
 245                 .gate = { CGU_REG_CLKGR0, 1 },
 246         },
 247         [JZ4770_CLK_LPCLK_MUX] = {
 248                 "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 249                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 250                 .mux = { CGU_REG_LPCDR, 29, 1 },
 251                 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
 252                 .gate = { CGU_REG_CLKGR0, 28 },
 253         },
 254         [JZ4770_CLK_GPS] = {
 255                 "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 256                 .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, },
 257                 .mux = { CGU_REG_GPSCDR, 31, 1 },
 258                 .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
 259                 .gate = { CGU_REG_CLKGR0, 22 },
 260         },
 261 
 262         /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
 263 
 264         [JZ4770_CLK_SSI_MUX] = {
 265                 "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
 266                 .parents = { JZ4770_CLK_EXT, -1,
 267                         JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
 268                 .mux = { CGU_REG_SSICDR, 30, 2 },
 269                 .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 },
 270         },
 271         [JZ4770_CLK_PCM_MUX] = {
 272                 "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX,
 273                 .parents = { JZ4770_CLK_EXT, -1,
 274                         JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
 275                 .mux = { CGU_REG_PCMCDR, 30, 2 },
 276                 .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 },
 277         },
 278         [JZ4770_CLK_I2S] = {
 279                 "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 280                 .parents = { JZ4770_CLK_EXT, -1,
 281                         JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
 282                 .mux = { CGU_REG_I2SCDR, 30, 2 },
 283                 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
 284                 .gate = { CGU_REG_CLKGR1, 13 },
 285         },
 286         [JZ4770_CLK_OTG] = {
 287                 "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
 288                 .parents = { JZ4770_CLK_EXT, -1,
 289                         JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 },
 290                 .mux = { CGU_REG_USBCDR, 30, 2 },
 291                 .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
 292                 .gate = { CGU_REG_CLKGR0, 2 },
 293         },
 294 
 295         /* Gate-only clocks */
 296 
 297         [JZ4770_CLK_SSI0] = {
 298                 "ssi0", CGU_CLK_GATE,
 299                 .parents = { JZ4770_CLK_SSI_MUX, },
 300                 .gate = { CGU_REG_CLKGR0, 4 },
 301         },
 302         [JZ4770_CLK_SSI1] = {
 303                 "ssi1", CGU_CLK_GATE,
 304                 .parents = { JZ4770_CLK_SSI_MUX, },
 305                 .gate = { CGU_REG_CLKGR0, 19 },
 306         },
 307         [JZ4770_CLK_SSI2] = {
 308                 "ssi2", CGU_CLK_GATE,
 309                 .parents = { JZ4770_CLK_SSI_MUX, },
 310                 .gate = { CGU_REG_CLKGR0, 20 },
 311         },
 312         [JZ4770_CLK_PCM0] = {
 313                 "pcm0", CGU_CLK_GATE,
 314                 .parents = { JZ4770_CLK_PCM_MUX, },
 315                 .gate = { CGU_REG_CLKGR1, 8 },
 316         },
 317         [JZ4770_CLK_PCM1] = {
 318                 "pcm1", CGU_CLK_GATE,
 319                 .parents = { JZ4770_CLK_PCM_MUX, },
 320                 .gate = { CGU_REG_CLKGR1, 10 },
 321         },
 322         [JZ4770_CLK_DMA] = {
 323                 "dma", CGU_CLK_GATE,
 324                 .parents = { JZ4770_CLK_H2CLK, },
 325                 .gate = { CGU_REG_CLKGR0, 21 },
 326         },
 327         [JZ4770_CLK_I2C0] = {
 328                 "i2c0", CGU_CLK_GATE,
 329                 .parents = { JZ4770_CLK_EXT, },
 330                 .gate = { CGU_REG_CLKGR0, 5 },
 331         },
 332         [JZ4770_CLK_I2C1] = {
 333                 "i2c1", CGU_CLK_GATE,
 334                 .parents = { JZ4770_CLK_EXT, },
 335                 .gate = { CGU_REG_CLKGR0, 6 },
 336         },
 337         [JZ4770_CLK_I2C2] = {
 338                 "i2c2", CGU_CLK_GATE,
 339                 .parents = { JZ4770_CLK_EXT, },
 340                 .gate = { CGU_REG_CLKGR1, 15 },
 341         },
 342         [JZ4770_CLK_UART0] = {
 343                 "uart0", CGU_CLK_GATE,
 344                 .parents = { JZ4770_CLK_EXT, },
 345                 .gate = { CGU_REG_CLKGR0, 15 },
 346         },
 347         [JZ4770_CLK_UART1] = {
 348                 "uart1", CGU_CLK_GATE,
 349                 .parents = { JZ4770_CLK_EXT, },
 350                 .gate = { CGU_REG_CLKGR0, 16 },
 351         },
 352         [JZ4770_CLK_UART2] = {
 353                 "uart2", CGU_CLK_GATE,
 354                 .parents = { JZ4770_CLK_EXT, },
 355                 .gate = { CGU_REG_CLKGR0, 17 },
 356         },
 357         [JZ4770_CLK_UART3] = {
 358                 "uart3", CGU_CLK_GATE,
 359                 .parents = { JZ4770_CLK_EXT, },
 360                 .gate = { CGU_REG_CLKGR0, 18 },
 361         },
 362         [JZ4770_CLK_IPU] = {
 363                 "ipu", CGU_CLK_GATE,
 364                 .parents = { JZ4770_CLK_H0CLK, },
 365                 .gate = { CGU_REG_CLKGR0, 29 },
 366         },
 367         [JZ4770_CLK_ADC] = {
 368                 "adc", CGU_CLK_GATE,
 369                 .parents = { JZ4770_CLK_EXT, },
 370                 .gate = { CGU_REG_CLKGR0, 14 },
 371         },
 372         [JZ4770_CLK_AIC] = {
 373                 "aic", CGU_CLK_GATE,
 374                 .parents = { JZ4770_CLK_EXT, },
 375                 .gate = { CGU_REG_CLKGR0, 8 },
 376         },
 377         [JZ4770_CLK_AUX] = {
 378                 "aux", CGU_CLK_GATE,
 379                 .parents = { JZ4770_CLK_C1CLK, },
 380                 .gate = { CGU_REG_CLKGR1, 14 },
 381         },
 382         [JZ4770_CLK_VPU] = {
 383                 "vpu", CGU_CLK_GATE,
 384                 .parents = { JZ4770_CLK_H1CLK, },
 385                 .gate = { CGU_REG_LCR, 30, false, 150 },
 386         },
 387         [JZ4770_CLK_MMC0] = {
 388                 "mmc0", CGU_CLK_GATE,
 389                 .parents = { JZ4770_CLK_MMC0_MUX, },
 390                 .gate = { CGU_REG_CLKGR0, 3 },
 391         },
 392         [JZ4770_CLK_MMC1] = {
 393                 "mmc1", CGU_CLK_GATE,
 394                 .parents = { JZ4770_CLK_MMC1_MUX, },
 395                 .gate = { CGU_REG_CLKGR0, 11 },
 396         },
 397         [JZ4770_CLK_MMC2] = {
 398                 "mmc2", CGU_CLK_GATE,
 399                 .parents = { JZ4770_CLK_MMC2_MUX, },
 400                 .gate = { CGU_REG_CLKGR0, 12 },
 401         },
 402         [JZ4770_CLK_OTG_PHY] = {
 403                 "usb_phy", CGU_CLK_GATE,
 404                 .parents = { JZ4770_CLK_OTG },
 405                 .gate = { CGU_REG_OPCR, 7, true, 50 },
 406         },
 407 
 408         /* Custom clocks */
 409 
 410         [JZ4770_CLK_UHC_PHY] = {
 411                 "uhc_phy", CGU_CLK_CUSTOM,
 412                 .parents = { JZ4770_CLK_UHC, -1, -1, -1 },
 413                 .custom = { &jz4770_uhc_phy_ops },
 414         },
 415 
 416         [JZ4770_CLK_EXT512] = {
 417                 "ext/512", CGU_CLK_FIXDIV,
 418                 .parents = { JZ4770_CLK_EXT },
 419                 .fixdiv = { 512 },
 420         },
 421 
 422         [JZ4770_CLK_RTC] = {
 423                 "rtc", CGU_CLK_MUX,
 424                 .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, },
 425                 .mux = { CGU_REG_OPCR, 2, 1},
 426         },
 427 };
 428 
 429 static void __init jz4770_cgu_init(struct device_node *np)
 430 {
 431         int retval;
 432 
 433         cgu = ingenic_cgu_new(jz4770_cgu_clocks,
 434                               ARRAY_SIZE(jz4770_cgu_clocks), np);
 435         if (!cgu) {
 436                 pr_err("%s: failed to initialise CGU\n", __func__);
 437                 return;
 438         }
 439 
 440         retval = ingenic_cgu_register_clocks(cgu);
 441         if (retval)
 442                 pr_err("%s: failed to register CGU Clocks\n", __func__);
 443 
 444         ingenic_cgu_register_syscore_ops(cgu);
 445 }
 446 
 447 /* We only probe via devicetree, no need for a platform driver */
 448 CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);

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