347 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Ingenic JZ4755 SoC CGU driver4 * Heavily based on JZ4725b CGU driver5 *6 * Copyright (C) 2022 Siarhei Volkau7 * Author: Siarhei Volkau <lis8215@gmail.com>8 */9 10#include <linux/clk-provider.h>11#include <linux/delay.h>12#include <linux/of.h>13 14#include <dt-bindings/clock/ingenic,jz4755-cgu.h>15 16#include "cgu.h"17#include "pm.h"18 19/* CGU register offsets */20#define CGU_REG_CPCCR 0x0021#define CGU_REG_CPPCR 0x1022#define CGU_REG_CLKGR 0x2023#define CGU_REG_OPCR 0x2424#define CGU_REG_I2SCDR 0x6025#define CGU_REG_LPCDR 0x6426#define CGU_REG_MSCCDR 0x6827#define CGU_REG_SSICDR 0x7428#define CGU_REG_CIMCDR 0x7C29 30static struct ingenic_cgu *cgu;31 32static const s8 pll_od_encoding[4] = {33 0x0, 0x1, -1, 0x3,34};35 36static const u8 jz4755_cgu_cpccr_div_table[] = {37 1, 2, 3, 4, 6, 8,38};39 40static const u8 jz4755_cgu_pll_half_div_table[] = {41 2, 1,42};43 44static const struct ingenic_cgu_clk_info jz4755_cgu_clocks[] = {45 46 /* External clocks */47 48 [JZ4755_CLK_EXT] = { "ext", CGU_CLK_EXT },49 [JZ4755_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },50 51 [JZ4755_CLK_PLL] = {52 "pll", CGU_CLK_PLL,53 .parents = { JZ4755_CLK_EXT, },54 .pll = {55 .reg = CGU_REG_CPPCR,56 .rate_multiplier = 1,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_reg = CGU_REG_CPPCR,69 .bypass_bit = 9,70 .enable_bit = 8,71 },72 },73 74 /* Muxes & dividers */75 76 [JZ4755_CLK_PLL_HALF] = {77 "pll half", CGU_CLK_DIV,78 .parents = { JZ4755_CLK_PLL, },79 .div = {80 CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,81 jz4755_cgu_pll_half_div_table,82 },83 },84 85 [JZ4755_CLK_EXT_HALF] = {86 "ext half", CGU_CLK_DIV,87 .parents = { JZ4755_CLK_EXT, },88 .div = {89 CGU_REG_CPCCR, 30, 1, 1, -1, -1, -1, 0,90 NULL,91 },92 },93 94 [JZ4755_CLK_CCLK] = {95 "cclk", CGU_CLK_DIV,96 .parents = { JZ4755_CLK_PLL, },97 .div = {98 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,99 jz4755_cgu_cpccr_div_table,100 },101 },102 103 [JZ4755_CLK_H0CLK] = {104 "hclk", CGU_CLK_DIV,105 .parents = { JZ4755_CLK_PLL, },106 .div = {107 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,108 jz4755_cgu_cpccr_div_table,109 },110 },111 112 [JZ4755_CLK_PCLK] = {113 "pclk", CGU_CLK_DIV,114 .parents = { JZ4755_CLK_PLL, },115 .div = {116 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,117 jz4755_cgu_cpccr_div_table,118 },119 },120 121 [JZ4755_CLK_MCLK] = {122 "mclk", CGU_CLK_DIV,123 .parents = { JZ4755_CLK_PLL, },124 .div = {125 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,126 jz4755_cgu_cpccr_div_table,127 },128 },129 130 [JZ4755_CLK_H1CLK] = {131 "h1clk", CGU_CLK_DIV,132 .parents = { JZ4755_CLK_PLL, },133 .div = {134 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,135 jz4755_cgu_cpccr_div_table,136 },137 },138 139 [JZ4755_CLK_UDC] = {140 "udc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,141 .parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, },142 .mux = { CGU_REG_CPCCR, 29, 1 },143 .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },144 .gate = { CGU_REG_CLKGR, 10 },145 },146 147 [JZ4755_CLK_LCD] = {148 "lcd", CGU_CLK_DIV | CGU_CLK_GATE,149 .parents = { JZ4755_CLK_PLL_HALF, },150 .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },151 .gate = { CGU_REG_CLKGR, 9 },152 },153 154 [JZ4755_CLK_MMC] = {155 "mmc", CGU_CLK_DIV,156 .parents = { JZ4755_CLK_PLL_HALF, },157 .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },158 },159 160 [JZ4755_CLK_I2S] = {161 "i2s", CGU_CLK_MUX | CGU_CLK_DIV,162 .parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, },163 .mux = { CGU_REG_CPCCR, 31, 1 },164 .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },165 },166 167 [JZ4755_CLK_SPI] = {168 "spi", CGU_CLK_DIV | CGU_CLK_GATE,169 .parents = { JZ4755_CLK_PLL_HALF, },170 .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },171 .gate = { CGU_REG_CLKGR, 4 },172 },173 174 [JZ4755_CLK_TVE] = {175 "tve", CGU_CLK_MUX | CGU_CLK_GATE,176 .parents = { JZ4755_CLK_LCD, JZ4755_CLK_EXT, },177 .mux = { CGU_REG_LPCDR, 31, 1 },178 .gate = { CGU_REG_CLKGR, 18 },179 },180 181 [JZ4755_CLK_RTC] = {182 "rtc", CGU_CLK_MUX | CGU_CLK_GATE,183 .parents = { JZ4755_CLK_EXT512, JZ4755_CLK_OSC32K, },184 .mux = { CGU_REG_OPCR, 2, 1},185 .gate = { CGU_REG_CLKGR, 2 },186 },187 188 [JZ4755_CLK_CIM] = {189 "cim", CGU_CLK_DIV | CGU_CLK_GATE,190 .parents = { JZ4755_CLK_PLL_HALF, },191 .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },192 .gate = { CGU_REG_CLKGR, 8 },193 },194 195 /* Gate-only clocks */196 197 [JZ4755_CLK_UART0] = {198 "uart0", CGU_CLK_GATE,199 .parents = { JZ4755_CLK_EXT_HALF, },200 .gate = { CGU_REG_CLKGR, 0 },201 },202 203 [JZ4755_CLK_UART1] = {204 "uart1", CGU_CLK_GATE,205 .parents = { JZ4755_CLK_EXT_HALF, },206 .gate = { CGU_REG_CLKGR, 14 },207 },208 209 [JZ4755_CLK_UART2] = {210 "uart2", CGU_CLK_GATE,211 .parents = { JZ4755_CLK_EXT_HALF, },212 .gate = { CGU_REG_CLKGR, 15 },213 },214 215 [JZ4755_CLK_ADC] = {216 "adc", CGU_CLK_GATE,217 .parents = { JZ4755_CLK_EXT_HALF, },218 .gate = { CGU_REG_CLKGR, 7 },219 },220 221 [JZ4755_CLK_AIC] = {222 "aic", CGU_CLK_GATE,223 .parents = { JZ4755_CLK_EXT_HALF, },224 .gate = { CGU_REG_CLKGR, 5 },225 },226 227 [JZ4755_CLK_I2C] = {228 "i2c", CGU_CLK_GATE,229 .parents = { JZ4755_CLK_EXT_HALF, },230 .gate = { CGU_REG_CLKGR, 3 },231 },232 233 [JZ4755_CLK_BCH] = {234 "bch", CGU_CLK_GATE,235 .parents = { JZ4755_CLK_H1CLK, },236 .gate = { CGU_REG_CLKGR, 11 },237 },238 239 [JZ4755_CLK_TCU] = {240 "tcu", CGU_CLK_GATE,241 .parents = { JZ4755_CLK_EXT, },242 .gate = { CGU_REG_CLKGR, 1 },243 },244 245 [JZ4755_CLK_DMA] = {246 "dma", CGU_CLK_GATE,247 .parents = { JZ4755_CLK_PCLK, },248 .gate = { CGU_REG_CLKGR, 12 },249 },250 251 [JZ4755_CLK_MMC0] = {252 "mmc0", CGU_CLK_GATE,253 .parents = { JZ4755_CLK_MMC, },254 .gate = { CGU_REG_CLKGR, 6 },255 },256 257 [JZ4755_CLK_MMC1] = {258 "mmc1", CGU_CLK_GATE,259 .parents = { JZ4755_CLK_MMC, },260 .gate = { CGU_REG_CLKGR, 16 },261 },262 263 [JZ4755_CLK_AUX_CPU] = {264 "aux_cpu", CGU_CLK_GATE,265 .parents = { JZ4755_CLK_H1CLK, },266 .gate = { CGU_REG_CLKGR, 24 },267 },268 269 [JZ4755_CLK_AHB1] = {270 "ahb1", CGU_CLK_GATE,271 .parents = { JZ4755_CLK_H1CLK, },272 .gate = { CGU_REG_CLKGR, 23 },273 },274 275 [JZ4755_CLK_IDCT] = {276 "idct", CGU_CLK_GATE,277 .parents = { JZ4755_CLK_H1CLK, },278 .gate = { CGU_REG_CLKGR, 22 },279 },280 281 [JZ4755_CLK_DB] = {282 "db", CGU_CLK_GATE,283 .parents = { JZ4755_CLK_H1CLK, },284 .gate = { CGU_REG_CLKGR, 21 },285 },286 287 [JZ4755_CLK_ME] = {288 "me", CGU_CLK_GATE,289 .parents = { JZ4755_CLK_H1CLK, },290 .gate = { CGU_REG_CLKGR, 20 },291 },292 293 [JZ4755_CLK_MC] = {294 "mc", CGU_CLK_GATE,295 .parents = { JZ4755_CLK_H1CLK, },296 .gate = { CGU_REG_CLKGR, 19 },297 },298 299 [JZ4755_CLK_TSSI] = {300 "tssi", CGU_CLK_GATE,301 .parents = { JZ4755_CLK_EXT_HALF/* not sure */, },302 .gate = { CGU_REG_CLKGR, 17 },303 },304 305 [JZ4755_CLK_IPU] = {306 "ipu", CGU_CLK_GATE,307 .parents = { JZ4755_CLK_PLL_HALF/* not sure */, },308 .gate = { CGU_REG_CLKGR, 13 },309 },310 311 [JZ4755_CLK_EXT512] = {312 "ext/512", CGU_CLK_FIXDIV,313 .parents = { JZ4755_CLK_EXT, },314 315 .fixdiv = { 512 },316 },317 318 [JZ4755_CLK_UDC_PHY] = {319 "udc_phy", CGU_CLK_GATE,320 .parents = { JZ4755_CLK_EXT_HALF, },321 .gate = { CGU_REG_OPCR, 6, true },322 },323};324 325static void __init jz4755_cgu_init(struct device_node *np)326{327 int retval;328 329 cgu = ingenic_cgu_new(jz4755_cgu_clocks,330 ARRAY_SIZE(jz4755_cgu_clocks), np);331 if (!cgu) {332 pr_err("%s: failed to initialise CGU\n", __func__);333 return;334 }335 336 retval = ingenic_cgu_register_clocks(cgu);337 if (retval)338 pr_err("%s: failed to register CGU Clocks\n", __func__);339 340 ingenic_cgu_register_syscore_ops(cgu);341}342/*343 * CGU has some children devices, this is useful for probing children devices344 * in the case where the device node is compatible with "simple-mfd".345 */346CLK_OF_DECLARE_DRIVER(jz4755_cgu, "ingenic,jz4755-cgu", jz4755_cgu_init);347