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

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

DEFINITIONS

This source file includes following definitions.
  1. jz4725b_cgu_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Ingenic JZ4725B SoC CGU driver
   4  *
   5  * Copyright (C) 2018 Paul Cercueil
   6  * Author: Paul Cercueil <paul@crapouillou.net>
   7  */
   8 
   9 #include <linux/clk-provider.h>
  10 #include <linux/delay.h>
  11 #include <linux/of.h>
  12 #include <dt-bindings/clock/jz4725b-cgu.h>
  13 #include "cgu.h"
  14 #include "pm.h"
  15 
  16 /* CGU register offsets */
  17 #define CGU_REG_CPCCR           0x00
  18 #define CGU_REG_LCR             0x04
  19 #define CGU_REG_CPPCR           0x10
  20 #define CGU_REG_CLKGR           0x20
  21 #define CGU_REG_OPCR            0x24
  22 #define CGU_REG_I2SCDR          0x60
  23 #define CGU_REG_LPCDR           0x64
  24 #define CGU_REG_MSCCDR          0x68
  25 #define CGU_REG_SSICDR          0x74
  26 #define CGU_REG_CIMCDR          0x78
  27 
  28 /* bits within the LCR register */
  29 #define LCR_SLEEP               BIT(0)
  30 
  31 static struct ingenic_cgu *cgu;
  32 
  33 static const s8 pll_od_encoding[4] = {
  34         0x0, 0x1, -1, 0x3,
  35 };
  36 
  37 static const u8 jz4725b_cgu_cpccr_div_table[] = {
  38         1, 2, 3, 4, 6, 8,
  39 };
  40 
  41 static const u8 jz4725b_cgu_pll_half_div_table[] = {
  42         2, 1,
  43 };
  44 
  45 static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
  46 
  47         /* External clocks */
  48 
  49         [JZ4725B_CLK_EXT] = { "ext", CGU_CLK_EXT },
  50         [JZ4725B_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
  51 
  52         [JZ4725B_CLK_PLL] = {
  53                 "pll", CGU_CLK_PLL,
  54                 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
  55                 .pll = {
  56                         .reg = CGU_REG_CPPCR,
  57                         .m_shift = 23,
  58                         .m_bits = 9,
  59                         .m_offset = 2,
  60                         .n_shift = 18,
  61                         .n_bits = 5,
  62                         .n_offset = 2,
  63                         .od_shift = 16,
  64                         .od_bits = 2,
  65                         .od_max = 4,
  66                         .od_encoding = pll_od_encoding,
  67                         .stable_bit = 10,
  68                         .bypass_bit = 9,
  69                         .enable_bit = 8,
  70                 },
  71         },
  72 
  73         /* Muxes & dividers */
  74 
  75         [JZ4725B_CLK_PLL_HALF] = {
  76                 "pll half", CGU_CLK_DIV,
  77                 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
  78                 .div = {
  79                         CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
  80                         jz4725b_cgu_pll_half_div_table,
  81                 },
  82         },
  83 
  84         [JZ4725B_CLK_CCLK] = {
  85                 "cclk", CGU_CLK_DIV,
  86                 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
  87                 .div = {
  88                         CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
  89                         jz4725b_cgu_cpccr_div_table,
  90                 },
  91         },
  92 
  93         [JZ4725B_CLK_HCLK] = {
  94                 "hclk", CGU_CLK_DIV,
  95                 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
  96                 .div = {
  97                         CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
  98                         jz4725b_cgu_cpccr_div_table,
  99                 },
 100         },
 101 
 102         [JZ4725B_CLK_PCLK] = {
 103                 "pclk", CGU_CLK_DIV,
 104                 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
 105                 .div = {
 106                         CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
 107                         jz4725b_cgu_cpccr_div_table,
 108                 },
 109         },
 110 
 111         [JZ4725B_CLK_MCLK] = {
 112                 "mclk", CGU_CLK_DIV,
 113                 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
 114                 .div = {
 115                         CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
 116                         jz4725b_cgu_cpccr_div_table,
 117                 },
 118         },
 119 
 120         [JZ4725B_CLK_IPU] = {
 121                 "ipu", CGU_CLK_DIV | CGU_CLK_GATE,
 122                 .parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
 123                 .div = {
 124                         CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1,
 125                         jz4725b_cgu_cpccr_div_table,
 126                 },
 127                 .gate = { CGU_REG_CLKGR, 13 },
 128         },
 129 
 130         [JZ4725B_CLK_LCD] = {
 131                 "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
 132                 .parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },
 133                 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
 134                 .gate = { CGU_REG_CLKGR, 9 },
 135         },
 136 
 137         [JZ4725B_CLK_I2S] = {
 138                 "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 139                 .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
 140                 .mux = { CGU_REG_CPCCR, 31, 1 },
 141                 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
 142                 .gate = { CGU_REG_CLKGR, 6 },
 143         },
 144 
 145         [JZ4725B_CLK_SPI] = {
 146                 "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 147                 .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL, -1, -1 },
 148                 .mux = { CGU_REG_SSICDR, 31, 1 },
 149                 .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
 150                 .gate = { CGU_REG_CLKGR, 4 },
 151         },
 152 
 153         [JZ4725B_CLK_MMC_MUX] = {
 154                 "mmc_mux", CGU_CLK_DIV,
 155                 .parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },
 156                 .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
 157         },
 158 
 159         [JZ4725B_CLK_UDC] = {
 160                 "udc", CGU_CLK_MUX | CGU_CLK_DIV,
 161                 .parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
 162                 .mux = { CGU_REG_CPCCR, 29, 1 },
 163                 .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
 164         },
 165 
 166         /* Gate-only clocks */
 167 
 168         [JZ4725B_CLK_UART] = {
 169                 "uart", CGU_CLK_GATE,
 170                 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
 171                 .gate = { CGU_REG_CLKGR, 0 },
 172         },
 173 
 174         [JZ4725B_CLK_DMA] = {
 175                 "dma", CGU_CLK_GATE,
 176                 .parents = { JZ4725B_CLK_PCLK, -1, -1, -1 },
 177                 .gate = { CGU_REG_CLKGR, 12 },
 178         },
 179 
 180         [JZ4725B_CLK_ADC] = {
 181                 "adc", CGU_CLK_GATE,
 182                 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
 183                 .gate = { CGU_REG_CLKGR, 7 },
 184         },
 185 
 186         [JZ4725B_CLK_I2C] = {
 187                 "i2c", CGU_CLK_GATE,
 188                 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
 189                 .gate = { CGU_REG_CLKGR, 3 },
 190         },
 191 
 192         [JZ4725B_CLK_AIC] = {
 193                 "aic", CGU_CLK_GATE,
 194                 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
 195                 .gate = { CGU_REG_CLKGR, 5 },
 196         },
 197 
 198         [JZ4725B_CLK_MMC0] = {
 199                 "mmc0", CGU_CLK_GATE,
 200                 .parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },
 201                 .gate = { CGU_REG_CLKGR, 6 },
 202         },
 203 
 204         [JZ4725B_CLK_MMC1] = {
 205                 "mmc1", CGU_CLK_GATE,
 206                 .parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },
 207                 .gate = { CGU_REG_CLKGR, 16 },
 208         },
 209 
 210         [JZ4725B_CLK_BCH] = {
 211                 "bch", CGU_CLK_GATE,
 212                 .parents = { JZ4725B_CLK_MCLK/* not sure */, -1, -1, -1 },
 213                 .gate = { CGU_REG_CLKGR, 11 },
 214         },
 215 
 216         [JZ4725B_CLK_TCU] = {
 217                 "tcu", CGU_CLK_GATE,
 218                 .parents = { JZ4725B_CLK_EXT/* not sure */, -1, -1, -1 },
 219                 .gate = { CGU_REG_CLKGR, 1 },
 220         },
 221 
 222         [JZ4725B_CLK_EXT512] = {
 223                 "ext/512", CGU_CLK_FIXDIV,
 224                 .parents = { JZ4725B_CLK_EXT },
 225 
 226                 /* Doc calls it EXT512, but it seems to be /256... */
 227                 .fixdiv = { 256 },
 228         },
 229 
 230         [JZ4725B_CLK_RTC] = {
 231                 "rtc", CGU_CLK_MUX,
 232                 .parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 },
 233                 .mux = { CGU_REG_OPCR, 2, 1},
 234         },
 235 
 236         [JZ4725B_CLK_UDC_PHY] = {
 237                 "udc_phy", CGU_CLK_GATE,
 238                 .parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
 239                 .gate = { CGU_REG_OPCR, 6, true },
 240         },
 241 };
 242 
 243 static void __init jz4725b_cgu_init(struct device_node *np)
 244 {
 245         int retval;
 246 
 247         cgu = ingenic_cgu_new(jz4725b_cgu_clocks,
 248                               ARRAY_SIZE(jz4725b_cgu_clocks), np);
 249         if (!cgu) {
 250                 pr_err("%s: failed to initialise CGU\n", __func__);
 251                 return;
 252         }
 253 
 254         retval = ingenic_cgu_register_clocks(cgu);
 255         if (retval)
 256                 pr_err("%s: failed to register CGU Clocks\n", __func__);
 257 
 258         ingenic_cgu_register_syscore_ops(cgu);
 259 }
 260 CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);

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