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

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

DEFINITIONS

This source file includes following definitions.
  1. jz4740_cgu_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Ingenic JZ4740 SoC CGU driver
   4  *
   5  * Copyright (c) 2015 Imagination Technologies
   6  * Author: Paul Burton <paul.burton@mips.com>
   7  */
   8 
   9 #include <linux/clk-provider.h>
  10 #include <linux/delay.h>
  11 #include <linux/io.h>
  12 #include <linux/of.h>
  13 #include <dt-bindings/clock/jz4740-cgu.h>
  14 #include "cgu.h"
  15 #include "pm.h"
  16 
  17 /* CGU register offsets */
  18 #define CGU_REG_CPCCR           0x00
  19 #define CGU_REG_LCR             0x04
  20 #define CGU_REG_CPPCR           0x10
  21 #define CGU_REG_CLKGR           0x20
  22 #define CGU_REG_SCR             0x24
  23 #define CGU_REG_I2SCDR          0x60
  24 #define CGU_REG_LPCDR           0x64
  25 #define CGU_REG_MSCCDR          0x68
  26 #define CGU_REG_UHCCDR          0x6c
  27 #define CGU_REG_SSICDR          0x74
  28 
  29 /* bits within a PLL control register */
  30 #define PLLCTL_M_SHIFT          23
  31 #define PLLCTL_M_MASK           (0x1ff << PLLCTL_M_SHIFT)
  32 #define PLLCTL_N_SHIFT          18
  33 #define PLLCTL_N_MASK           (0x1f << PLLCTL_N_SHIFT)
  34 #define PLLCTL_OD_SHIFT         16
  35 #define PLLCTL_OD_MASK          (0x3 << PLLCTL_OD_SHIFT)
  36 #define PLLCTL_STABLE           (1 << 10)
  37 #define PLLCTL_BYPASS           (1 << 9)
  38 #define PLLCTL_ENABLE           (1 << 8)
  39 
  40 /* bits within the LCR register */
  41 #define LCR_SLEEP               (1 << 0)
  42 
  43 /* bits within the CLKGR register */
  44 #define CLKGR_UDC               (1 << 11)
  45 
  46 static struct ingenic_cgu *cgu;
  47 
  48 static const s8 pll_od_encoding[4] = {
  49         0x0, 0x1, -1, 0x3,
  50 };
  51 
  52 static const u8 jz4740_cgu_cpccr_div_table[] = {
  53         1, 2, 3, 4, 6, 8, 12, 16, 24, 32,
  54 };
  55 
  56 static const u8 jz4740_cgu_pll_half_div_table[] = {
  57         2, 1,
  58 };
  59 
  60 static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
  61 
  62         /* External clocks */
  63 
  64         [JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },
  65         [JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },
  66 
  67         [JZ4740_CLK_PLL] = {
  68                 "pll", CGU_CLK_PLL,
  69                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
  70                 .pll = {
  71                         .reg = CGU_REG_CPPCR,
  72                         .m_shift = 23,
  73                         .m_bits = 9,
  74                         .m_offset = 2,
  75                         .n_shift = 18,
  76                         .n_bits = 5,
  77                         .n_offset = 2,
  78                         .od_shift = 16,
  79                         .od_bits = 2,
  80                         .od_max = 4,
  81                         .od_encoding = pll_od_encoding,
  82                         .stable_bit = 10,
  83                         .bypass_bit = 9,
  84                         .enable_bit = 8,
  85                 },
  86         },
  87 
  88         /* Muxes & dividers */
  89 
  90         [JZ4740_CLK_PLL_HALF] = {
  91                 "pll half", CGU_CLK_DIV,
  92                 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
  93                 .div = {
  94                         CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
  95                         jz4740_cgu_pll_half_div_table,
  96                 },
  97         },
  98 
  99         [JZ4740_CLK_CCLK] = {
 100                 "cclk", CGU_CLK_DIV,
 101                 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
 102                 .div = {
 103                         CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1,
 104                         jz4740_cgu_cpccr_div_table,
 105                 },
 106         },
 107 
 108         [JZ4740_CLK_HCLK] = {
 109                 "hclk", CGU_CLK_DIV,
 110                 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
 111                 .div = {
 112                         CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1,
 113                         jz4740_cgu_cpccr_div_table,
 114                 },
 115         },
 116 
 117         [JZ4740_CLK_PCLK] = {
 118                 "pclk", CGU_CLK_DIV,
 119                 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
 120                 .div = {
 121                         CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1,
 122                         jz4740_cgu_cpccr_div_table,
 123                 },
 124         },
 125 
 126         [JZ4740_CLK_MCLK] = {
 127                 "mclk", CGU_CLK_DIV,
 128                 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
 129                 .div = {
 130                         CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1,
 131                         jz4740_cgu_cpccr_div_table,
 132                 },
 133         },
 134 
 135         [JZ4740_CLK_LCD] = {
 136                 "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
 137                 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
 138                 .div = {
 139                         CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1,
 140                         jz4740_cgu_cpccr_div_table,
 141                 },
 142                 .gate = { CGU_REG_CLKGR, 10 },
 143         },
 144 
 145         [JZ4740_CLK_LCD_PCLK] = {
 146                 "lcd_pclk", CGU_CLK_DIV,
 147                 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
 148                 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
 149         },
 150 
 151         [JZ4740_CLK_I2S] = {
 152                 "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 153                 .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
 154                 .mux = { CGU_REG_CPCCR, 31, 1 },
 155                 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
 156                 .gate = { CGU_REG_CLKGR, 6 },
 157         },
 158 
 159         [JZ4740_CLK_SPI] = {
 160                 "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 161                 .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 },
 162                 .mux = { CGU_REG_SSICDR, 31, 1 },
 163                 .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
 164                 .gate = { CGU_REG_CLKGR, 4 },
 165         },
 166 
 167         [JZ4740_CLK_MMC] = {
 168                 "mmc", CGU_CLK_DIV | CGU_CLK_GATE,
 169                 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
 170                 .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
 171                 .gate = { CGU_REG_CLKGR, 7 },
 172         },
 173 
 174         [JZ4740_CLK_UHC] = {
 175                 "uhc", CGU_CLK_DIV | CGU_CLK_GATE,
 176                 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
 177                 .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
 178                 .gate = { CGU_REG_CLKGR, 14 },
 179         },
 180 
 181         [JZ4740_CLK_UDC] = {
 182                 "udc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 183                 .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
 184                 .mux = { CGU_REG_CPCCR, 29, 1 },
 185                 .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
 186                 .gate = { CGU_REG_SCR, 6, true },
 187         },
 188 
 189         /* Gate-only clocks */
 190 
 191         [JZ4740_CLK_UART0] = {
 192                 "uart0", CGU_CLK_GATE,
 193                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
 194                 .gate = { CGU_REG_CLKGR, 0 },
 195         },
 196 
 197         [JZ4740_CLK_UART1] = {
 198                 "uart1", CGU_CLK_GATE,
 199                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
 200                 .gate = { CGU_REG_CLKGR, 15 },
 201         },
 202 
 203         [JZ4740_CLK_DMA] = {
 204                 "dma", CGU_CLK_GATE,
 205                 .parents = { JZ4740_CLK_PCLK, -1, -1, -1 },
 206                 .gate = { CGU_REG_CLKGR, 12 },
 207         },
 208 
 209         [JZ4740_CLK_IPU] = {
 210                 "ipu", CGU_CLK_GATE,
 211                 .parents = { JZ4740_CLK_PCLK, -1, -1, -1 },
 212                 .gate = { CGU_REG_CLKGR, 13 },
 213         },
 214 
 215         [JZ4740_CLK_ADC] = {
 216                 "adc", CGU_CLK_GATE,
 217                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
 218                 .gate = { CGU_REG_CLKGR, 8 },
 219         },
 220 
 221         [JZ4740_CLK_I2C] = {
 222                 "i2c", CGU_CLK_GATE,
 223                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
 224                 .gate = { CGU_REG_CLKGR, 3 },
 225         },
 226 
 227         [JZ4740_CLK_AIC] = {
 228                 "aic", CGU_CLK_GATE,
 229                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
 230                 .gate = { CGU_REG_CLKGR, 5 },
 231         },
 232 
 233         [JZ4740_CLK_TCU] = {
 234                 "tcu", CGU_CLK_GATE,
 235                 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
 236                 .gate = { CGU_REG_CLKGR, 1 },
 237         },
 238 };
 239 
 240 static void __init jz4740_cgu_init(struct device_node *np)
 241 {
 242         int retval;
 243 
 244         cgu = ingenic_cgu_new(jz4740_cgu_clocks,
 245                               ARRAY_SIZE(jz4740_cgu_clocks), np);
 246         if (!cgu) {
 247                 pr_err("%s: failed to initialise CGU\n", __func__);
 248                 return;
 249         }
 250 
 251         retval = ingenic_cgu_register_clocks(cgu);
 252         if (retval)
 253                 pr_err("%s: failed to register CGU Clocks\n", __func__);
 254 
 255         ingenic_cgu_register_syscore_ops(cgu);
 256 }
 257 CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);

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