162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * JZ4760 SoC CGU driver 462306a36Sopenharmony_ci * Copyright 2018, Paul Cercueil <paul@crapouillou.net> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/bitops.h> 862306a36Sopenharmony_ci#include <linux/clk-provider.h> 962306a36Sopenharmony_ci#include <linux/delay.h> 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <linux/of.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/clk.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <dt-bindings/clock/ingenic,jz4760-cgu.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "cgu.h" 1862306a36Sopenharmony_ci#include "pm.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define MHZ (1000 * 1000) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * CPM registers offset address definition 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci#define CGU_REG_CPCCR 0x00 2662306a36Sopenharmony_ci#define CGU_REG_LCR 0x04 2762306a36Sopenharmony_ci#define CGU_REG_CPPCR0 0x10 2862306a36Sopenharmony_ci#define CGU_REG_CLKGR0 0x20 2962306a36Sopenharmony_ci#define CGU_REG_OPCR 0x24 3062306a36Sopenharmony_ci#define CGU_REG_CLKGR1 0x28 3162306a36Sopenharmony_ci#define CGU_REG_CPPCR1 0x30 3262306a36Sopenharmony_ci#define CGU_REG_USBPCR 0x3c 3362306a36Sopenharmony_ci#define CGU_REG_USBCDR 0x50 3462306a36Sopenharmony_ci#define CGU_REG_I2SCDR 0x60 3562306a36Sopenharmony_ci#define CGU_REG_LPCDR 0x64 3662306a36Sopenharmony_ci#define CGU_REG_MSCCDR 0x68 3762306a36Sopenharmony_ci#define CGU_REG_UHCCDR 0x6c 3862306a36Sopenharmony_ci#define CGU_REG_SSICDR 0x74 3962306a36Sopenharmony_ci#define CGU_REG_CIMCDR 0x7c 4062306a36Sopenharmony_ci#define CGU_REG_GPSCDR 0x80 4162306a36Sopenharmony_ci#define CGU_REG_PCMCDR 0x84 4262306a36Sopenharmony_ci#define CGU_REG_GPUCDR 0x88 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const s8 pll_od_encoding[8] = { 4562306a36Sopenharmony_ci 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic const u8 jz4760_cgu_cpccr_div_table[] = { 4962306a36Sopenharmony_ci 1, 2, 3, 4, 6, 8, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic const u8 jz4760_cgu_pll_half_div_table[] = { 5362306a36Sopenharmony_ci 2, 1, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic void 5762306a36Sopenharmony_cijz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, 5862306a36Sopenharmony_ci unsigned long rate, unsigned long parent_rate, 5962306a36Sopenharmony_ci unsigned int *pm, unsigned int *pn, unsigned int *pod) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 1; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* The frequency after the N divider must be between 1 and 50 MHz. */ 6462306a36Sopenharmony_ci n = parent_rate / (1 * MHZ); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* The N divider must be >= 2. */ 6762306a36Sopenharmony_ci n = clamp_val(n, 2, 1 << pll_info->n_bits); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci rate /= MHZ; 7062306a36Sopenharmony_ci parent_rate /= MHZ; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci for (m = m_max; m >= m_max && n >= 2; n--) { 7362306a36Sopenharmony_ci m = rate * n / parent_rate; 7462306a36Sopenharmony_ci od = m & 1; 7562306a36Sopenharmony_ci m <<= od; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci *pm = m; 7962306a36Sopenharmony_ci *pn = n + 1; 8062306a36Sopenharmony_ci *pod = 1 << od; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_cistatic const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = { 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* External clocks */ 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci [JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT }, 8862306a36Sopenharmony_ci [JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* PLLs */ 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci [JZ4760_CLK_PLL0] = { 9362306a36Sopenharmony_ci "pll0", CGU_CLK_PLL, 9462306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT }, 9562306a36Sopenharmony_ci .pll = { 9662306a36Sopenharmony_ci .reg = CGU_REG_CPPCR0, 9762306a36Sopenharmony_ci .rate_multiplier = 1, 9862306a36Sopenharmony_ci .m_shift = 23, 9962306a36Sopenharmony_ci .m_bits = 8, 10062306a36Sopenharmony_ci .m_offset = 0, 10162306a36Sopenharmony_ci .n_shift = 18, 10262306a36Sopenharmony_ci .n_bits = 4, 10362306a36Sopenharmony_ci .n_offset = 0, 10462306a36Sopenharmony_ci .od_shift = 16, 10562306a36Sopenharmony_ci .od_bits = 2, 10662306a36Sopenharmony_ci .od_max = 8, 10762306a36Sopenharmony_ci .od_encoding = pll_od_encoding, 10862306a36Sopenharmony_ci .bypass_reg = CGU_REG_CPPCR0, 10962306a36Sopenharmony_ci .bypass_bit = 9, 11062306a36Sopenharmony_ci .enable_bit = 8, 11162306a36Sopenharmony_ci .stable_bit = 10, 11262306a36Sopenharmony_ci .calc_m_n_od = jz4760_cgu_calc_m_n_od, 11362306a36Sopenharmony_ci }, 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci [JZ4760_CLK_PLL1] = { 11762306a36Sopenharmony_ci /* TODO: PLL1 can depend on PLL0 */ 11862306a36Sopenharmony_ci "pll1", CGU_CLK_PLL, 11962306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT }, 12062306a36Sopenharmony_ci .pll = { 12162306a36Sopenharmony_ci .reg = CGU_REG_CPPCR1, 12262306a36Sopenharmony_ci .rate_multiplier = 1, 12362306a36Sopenharmony_ci .m_shift = 23, 12462306a36Sopenharmony_ci .m_bits = 8, 12562306a36Sopenharmony_ci .m_offset = 0, 12662306a36Sopenharmony_ci .n_shift = 18, 12762306a36Sopenharmony_ci .n_bits = 4, 12862306a36Sopenharmony_ci .n_offset = 0, 12962306a36Sopenharmony_ci .od_shift = 16, 13062306a36Sopenharmony_ci .od_bits = 2, 13162306a36Sopenharmony_ci .od_max = 8, 13262306a36Sopenharmony_ci .od_encoding = pll_od_encoding, 13362306a36Sopenharmony_ci .bypass_bit = -1, 13462306a36Sopenharmony_ci .enable_bit = 7, 13562306a36Sopenharmony_ci .stable_bit = 6, 13662306a36Sopenharmony_ci .calc_m_n_od = jz4760_cgu_calc_m_n_od, 13762306a36Sopenharmony_ci }, 13862306a36Sopenharmony_ci }, 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* Main clocks */ 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci [JZ4760_CLK_CCLK] = { 14362306a36Sopenharmony_ci "cclk", CGU_CLK_DIV, 14462306a36Sopenharmony_ci /* 14562306a36Sopenharmony_ci * Disabling the CPU clock or any parent clocks will hang the 14662306a36Sopenharmony_ci * system; mark it critical. 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_ci .flags = CLK_IS_CRITICAL, 14962306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0, }, 15062306a36Sopenharmony_ci .div = { 15162306a36Sopenharmony_ci CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, 15262306a36Sopenharmony_ci jz4760_cgu_cpccr_div_table, 15362306a36Sopenharmony_ci }, 15462306a36Sopenharmony_ci }, 15562306a36Sopenharmony_ci [JZ4760_CLK_HCLK] = { 15662306a36Sopenharmony_ci "hclk", CGU_CLK_DIV, 15762306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0, }, 15862306a36Sopenharmony_ci .div = { 15962306a36Sopenharmony_ci CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, 16062306a36Sopenharmony_ci jz4760_cgu_cpccr_div_table, 16162306a36Sopenharmony_ci }, 16262306a36Sopenharmony_ci }, 16362306a36Sopenharmony_ci [JZ4760_CLK_SCLK] = { 16462306a36Sopenharmony_ci "sclk", CGU_CLK_DIV, 16562306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0, }, 16662306a36Sopenharmony_ci .div = { 16762306a36Sopenharmony_ci CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0, 16862306a36Sopenharmony_ci jz4760_cgu_cpccr_div_table, 16962306a36Sopenharmony_ci }, 17062306a36Sopenharmony_ci }, 17162306a36Sopenharmony_ci [JZ4760_CLK_H2CLK] = { 17262306a36Sopenharmony_ci "h2clk", CGU_CLK_DIV, 17362306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0, }, 17462306a36Sopenharmony_ci .div = { 17562306a36Sopenharmony_ci CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, 17662306a36Sopenharmony_ci jz4760_cgu_cpccr_div_table, 17762306a36Sopenharmony_ci }, 17862306a36Sopenharmony_ci }, 17962306a36Sopenharmony_ci [JZ4760_CLK_MCLK] = { 18062306a36Sopenharmony_ci "mclk", CGU_CLK_DIV, 18162306a36Sopenharmony_ci /* 18262306a36Sopenharmony_ci * Disabling MCLK or its parents will render DRAM 18362306a36Sopenharmony_ci * inaccessible; mark it critical. 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ci .flags = CLK_IS_CRITICAL, 18662306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0, }, 18762306a36Sopenharmony_ci .div = { 18862306a36Sopenharmony_ci CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, 18962306a36Sopenharmony_ci jz4760_cgu_cpccr_div_table, 19062306a36Sopenharmony_ci }, 19162306a36Sopenharmony_ci }, 19262306a36Sopenharmony_ci [JZ4760_CLK_PCLK] = { 19362306a36Sopenharmony_ci "pclk", CGU_CLK_DIV, 19462306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0, }, 19562306a36Sopenharmony_ci .div = { 19662306a36Sopenharmony_ci CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, 19762306a36Sopenharmony_ci jz4760_cgu_cpccr_div_table, 19862306a36Sopenharmony_ci }, 19962306a36Sopenharmony_ci }, 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Divided clocks */ 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci [JZ4760_CLK_PLL0_HALF] = { 20462306a36Sopenharmony_ci "pll0_half", CGU_CLK_DIV, 20562306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0 }, 20662306a36Sopenharmony_ci .div = { 20762306a36Sopenharmony_ci CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0, 20862306a36Sopenharmony_ci jz4760_cgu_pll_half_div_table, 20962306a36Sopenharmony_ci }, 21062306a36Sopenharmony_ci }, 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Those divided clocks can connect to PLL0 or PLL1 */ 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci [JZ4760_CLK_UHC] = { 21562306a36Sopenharmony_ci "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 21662306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 21762306a36Sopenharmony_ci .mux = { CGU_REG_UHCCDR, 31, 1 }, 21862306a36Sopenharmony_ci .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 }, 21962306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 24 }, 22062306a36Sopenharmony_ci }, 22162306a36Sopenharmony_ci [JZ4760_CLK_GPU] = { 22262306a36Sopenharmony_ci "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 22362306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 22462306a36Sopenharmony_ci .mux = { CGU_REG_GPUCDR, 31, 1 }, 22562306a36Sopenharmony_ci .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 }, 22662306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR1, 9 }, 22762306a36Sopenharmony_ci }, 22862306a36Sopenharmony_ci [JZ4760_CLK_LPCLK_DIV] = { 22962306a36Sopenharmony_ci "lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX, 23062306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 23162306a36Sopenharmony_ci .mux = { CGU_REG_LPCDR, 29, 1 }, 23262306a36Sopenharmony_ci .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, 23362306a36Sopenharmony_ci }, 23462306a36Sopenharmony_ci [JZ4760_CLK_TVE] = { 23562306a36Sopenharmony_ci "tve", CGU_CLK_GATE | CGU_CLK_MUX, 23662306a36Sopenharmony_ci .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, }, 23762306a36Sopenharmony_ci .mux = { CGU_REG_LPCDR, 31, 1 }, 23862306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 27 }, 23962306a36Sopenharmony_ci }, 24062306a36Sopenharmony_ci [JZ4760_CLK_LPCLK] = { 24162306a36Sopenharmony_ci "lpclk", CGU_CLK_GATE | CGU_CLK_MUX, 24262306a36Sopenharmony_ci .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, }, 24362306a36Sopenharmony_ci .mux = { CGU_REG_LPCDR, 30, 1 }, 24462306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 28 }, 24562306a36Sopenharmony_ci }, 24662306a36Sopenharmony_ci [JZ4760_CLK_GPS] = { 24762306a36Sopenharmony_ci "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 24862306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, 24962306a36Sopenharmony_ci .mux = { CGU_REG_GPSCDR, 31, 1 }, 25062306a36Sopenharmony_ci .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 }, 25162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 22 }, 25262306a36Sopenharmony_ci }, 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Those divided clocks can connect to EXT, PLL0 or PLL1 */ 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci [JZ4760_CLK_PCM] = { 25762306a36Sopenharmony_ci "pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 25862306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, -1, 25962306a36Sopenharmony_ci JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, 26062306a36Sopenharmony_ci .mux = { CGU_REG_PCMCDR, 30, 2 }, 26162306a36Sopenharmony_ci .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, 26262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR1, 8 }, 26362306a36Sopenharmony_ci }, 26462306a36Sopenharmony_ci [JZ4760_CLK_I2S] = { 26562306a36Sopenharmony_ci "i2s", CGU_CLK_DIV | CGU_CLK_MUX, 26662306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, -1, 26762306a36Sopenharmony_ci JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, 26862306a36Sopenharmony_ci .mux = { CGU_REG_I2SCDR, 30, 2 }, 26962306a36Sopenharmony_ci .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, 27062306a36Sopenharmony_ci }, 27162306a36Sopenharmony_ci [JZ4760_CLK_OTG] = { 27262306a36Sopenharmony_ci "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 27362306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, -1, 27462306a36Sopenharmony_ci JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, 27562306a36Sopenharmony_ci .mux = { CGU_REG_USBCDR, 30, 2 }, 27662306a36Sopenharmony_ci .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 }, 27762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 2 }, 27862306a36Sopenharmony_ci }, 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* Those divided clocks can connect to EXT or PLL0 */ 28162306a36Sopenharmony_ci [JZ4760_CLK_MMC_MUX] = { 28262306a36Sopenharmony_ci "mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV, 28362306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, 28462306a36Sopenharmony_ci .mux = { CGU_REG_MSCCDR, 31, 1 }, 28562306a36Sopenharmony_ci .div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) }, 28662306a36Sopenharmony_ci }, 28762306a36Sopenharmony_ci [JZ4760_CLK_SSI_MUX] = { 28862306a36Sopenharmony_ci "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX, 28962306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, 29062306a36Sopenharmony_ci .mux = { CGU_REG_SSICDR, 31, 1 }, 29162306a36Sopenharmony_ci .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) }, 29262306a36Sopenharmony_ci }, 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* These divided clock can connect to PLL0 only */ 29562306a36Sopenharmony_ci [JZ4760_CLK_CIM] = { 29662306a36Sopenharmony_ci "cim", CGU_CLK_DIV | CGU_CLK_GATE, 29762306a36Sopenharmony_ci .parents = { JZ4760_CLK_PLL0_HALF }, 29862306a36Sopenharmony_ci .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 }, 29962306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 26 }, 30062306a36Sopenharmony_ci }, 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci /* Gate-only clocks */ 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci [JZ4760_CLK_SSI0] = { 30562306a36Sopenharmony_ci "ssi0", CGU_CLK_GATE, 30662306a36Sopenharmony_ci .parents = { JZ4760_CLK_SSI_MUX, }, 30762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 4 }, 30862306a36Sopenharmony_ci }, 30962306a36Sopenharmony_ci [JZ4760_CLK_SSI1] = { 31062306a36Sopenharmony_ci "ssi1", CGU_CLK_GATE, 31162306a36Sopenharmony_ci .parents = { JZ4760_CLK_SSI_MUX, }, 31262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 19 }, 31362306a36Sopenharmony_ci }, 31462306a36Sopenharmony_ci [JZ4760_CLK_SSI2] = { 31562306a36Sopenharmony_ci "ssi2", CGU_CLK_GATE, 31662306a36Sopenharmony_ci .parents = { JZ4760_CLK_SSI_MUX, }, 31762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 20 }, 31862306a36Sopenharmony_ci }, 31962306a36Sopenharmony_ci [JZ4760_CLK_DMA] = { 32062306a36Sopenharmony_ci "dma", CGU_CLK_GATE, 32162306a36Sopenharmony_ci .parents = { JZ4760_CLK_H2CLK, }, 32262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 21 }, 32362306a36Sopenharmony_ci }, 32462306a36Sopenharmony_ci [JZ4760_CLK_MDMA] = { 32562306a36Sopenharmony_ci "mdma", CGU_CLK_GATE, 32662306a36Sopenharmony_ci .parents = { JZ4760_CLK_HCLK, }, 32762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 25 }, 32862306a36Sopenharmony_ci }, 32962306a36Sopenharmony_ci [JZ4760_CLK_BDMA] = { 33062306a36Sopenharmony_ci "bdma", CGU_CLK_GATE, 33162306a36Sopenharmony_ci .parents = { JZ4760_CLK_HCLK, }, 33262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR1, 0 }, 33362306a36Sopenharmony_ci }, 33462306a36Sopenharmony_ci [JZ4760_CLK_I2C0] = { 33562306a36Sopenharmony_ci "i2c0", CGU_CLK_GATE, 33662306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 33762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 5 }, 33862306a36Sopenharmony_ci }, 33962306a36Sopenharmony_ci [JZ4760_CLK_I2C1] = { 34062306a36Sopenharmony_ci "i2c1", CGU_CLK_GATE, 34162306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 34262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 6 }, 34362306a36Sopenharmony_ci }, 34462306a36Sopenharmony_ci [JZ4760_CLK_UART0] = { 34562306a36Sopenharmony_ci "uart0", CGU_CLK_GATE, 34662306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 34762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 15 }, 34862306a36Sopenharmony_ci }, 34962306a36Sopenharmony_ci [JZ4760_CLK_UART1] = { 35062306a36Sopenharmony_ci "uart1", CGU_CLK_GATE, 35162306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 35262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 16 }, 35362306a36Sopenharmony_ci }, 35462306a36Sopenharmony_ci [JZ4760_CLK_UART2] = { 35562306a36Sopenharmony_ci "uart2", CGU_CLK_GATE, 35662306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 35762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 17 }, 35862306a36Sopenharmony_ci }, 35962306a36Sopenharmony_ci [JZ4760_CLK_UART3] = { 36062306a36Sopenharmony_ci "uart3", CGU_CLK_GATE, 36162306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 36262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 18 }, 36362306a36Sopenharmony_ci }, 36462306a36Sopenharmony_ci [JZ4760_CLK_IPU] = { 36562306a36Sopenharmony_ci "ipu", CGU_CLK_GATE, 36662306a36Sopenharmony_ci .parents = { JZ4760_CLK_HCLK, }, 36762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 29 }, 36862306a36Sopenharmony_ci }, 36962306a36Sopenharmony_ci [JZ4760_CLK_ADC] = { 37062306a36Sopenharmony_ci "adc", CGU_CLK_GATE, 37162306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 37262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 14 }, 37362306a36Sopenharmony_ci }, 37462306a36Sopenharmony_ci [JZ4760_CLK_AIC] = { 37562306a36Sopenharmony_ci "aic", CGU_CLK_GATE, 37662306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT, }, 37762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 8 }, 37862306a36Sopenharmony_ci }, 37962306a36Sopenharmony_ci [JZ4760_CLK_VPU] = { 38062306a36Sopenharmony_ci "vpu", CGU_CLK_GATE, 38162306a36Sopenharmony_ci .parents = { JZ4760_CLK_HCLK, }, 38262306a36Sopenharmony_ci .gate = { CGU_REG_LCR, 30, false, 150 }, 38362306a36Sopenharmony_ci }, 38462306a36Sopenharmony_ci [JZ4760_CLK_MMC0] = { 38562306a36Sopenharmony_ci "mmc0", CGU_CLK_GATE, 38662306a36Sopenharmony_ci .parents = { JZ4760_CLK_MMC_MUX, }, 38762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 3 }, 38862306a36Sopenharmony_ci }, 38962306a36Sopenharmony_ci [JZ4760_CLK_MMC1] = { 39062306a36Sopenharmony_ci "mmc1", CGU_CLK_GATE, 39162306a36Sopenharmony_ci .parents = { JZ4760_CLK_MMC_MUX, }, 39262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 11 }, 39362306a36Sopenharmony_ci }, 39462306a36Sopenharmony_ci [JZ4760_CLK_MMC2] = { 39562306a36Sopenharmony_ci "mmc2", CGU_CLK_GATE, 39662306a36Sopenharmony_ci .parents = { JZ4760_CLK_MMC_MUX, }, 39762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR0, 12 }, 39862306a36Sopenharmony_ci }, 39962306a36Sopenharmony_ci [JZ4760_CLK_UHC_PHY] = { 40062306a36Sopenharmony_ci "uhc_phy", CGU_CLK_GATE, 40162306a36Sopenharmony_ci .parents = { JZ4760_CLK_UHC, }, 40262306a36Sopenharmony_ci .gate = { CGU_REG_OPCR, 5 }, 40362306a36Sopenharmony_ci }, 40462306a36Sopenharmony_ci [JZ4760_CLK_OTG_PHY] = { 40562306a36Sopenharmony_ci "usb_phy", CGU_CLK_GATE, 40662306a36Sopenharmony_ci .parents = { JZ4760_CLK_OTG }, 40762306a36Sopenharmony_ci .gate = { CGU_REG_OPCR, 7, true, 50 }, 40862306a36Sopenharmony_ci }, 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* Custom clocks */ 41162306a36Sopenharmony_ci [JZ4760_CLK_EXT512] = { 41262306a36Sopenharmony_ci "ext/512", CGU_CLK_FIXDIV, 41362306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT }, 41462306a36Sopenharmony_ci .fixdiv = { 512 }, 41562306a36Sopenharmony_ci }, 41662306a36Sopenharmony_ci [JZ4760_CLK_RTC] = { 41762306a36Sopenharmony_ci "rtc", CGU_CLK_MUX, 41862306a36Sopenharmony_ci .parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, }, 41962306a36Sopenharmony_ci .mux = { CGU_REG_OPCR, 2, 1}, 42062306a36Sopenharmony_ci }, 42162306a36Sopenharmony_ci}; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void __init jz4760_cgu_init(struct device_node *np) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci struct ingenic_cgu *cgu; 42662306a36Sopenharmony_ci int retval; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci cgu = ingenic_cgu_new(jz4760_cgu_clocks, 42962306a36Sopenharmony_ci ARRAY_SIZE(jz4760_cgu_clocks), np); 43062306a36Sopenharmony_ci if (!cgu) { 43162306a36Sopenharmony_ci pr_err("%s: failed to initialise CGU\n", __func__); 43262306a36Sopenharmony_ci return; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci retval = ingenic_cgu_register_clocks(cgu); 43662306a36Sopenharmony_ci if (retval) 43762306a36Sopenharmony_ci pr_err("%s: failed to register CGU Clocks\n", __func__); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci ingenic_cgu_register_syscore_ops(cgu); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci/* We only probe via devicetree, no need for a platform driver */ 44362306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci/* JZ4760B has some small differences, but we don't implement them. */ 44662306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init); 447