162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * X1000 SoC CGU driver 462306a36Sopenharmony_ci * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/clk-provider.h> 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/io.h> 1062306a36Sopenharmony_ci#include <linux/of.h> 1162306a36Sopenharmony_ci#include <linux/rational.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <dt-bindings/clock/ingenic,x1000-cgu.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "cgu.h" 1662306a36Sopenharmony_ci#include "pm.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* CGU register offsets */ 1962306a36Sopenharmony_ci#define CGU_REG_CPCCR 0x00 2062306a36Sopenharmony_ci#define CGU_REG_APLL 0x10 2162306a36Sopenharmony_ci#define CGU_REG_MPLL 0x14 2262306a36Sopenharmony_ci#define CGU_REG_CLKGR 0x20 2362306a36Sopenharmony_ci#define CGU_REG_OPCR 0x24 2462306a36Sopenharmony_ci#define CGU_REG_DDRCDR 0x2c 2562306a36Sopenharmony_ci#define CGU_REG_USBPCR 0x3c 2662306a36Sopenharmony_ci#define CGU_REG_USBPCR1 0x48 2762306a36Sopenharmony_ci#define CGU_REG_USBCDR 0x50 2862306a36Sopenharmony_ci#define CGU_REG_MACCDR 0x54 2962306a36Sopenharmony_ci#define CGU_REG_I2SCDR 0x60 3062306a36Sopenharmony_ci#define CGU_REG_LPCDR 0x64 3162306a36Sopenharmony_ci#define CGU_REG_MSC0CDR 0x68 3262306a36Sopenharmony_ci#define CGU_REG_I2SCDR1 0x70 3362306a36Sopenharmony_ci#define CGU_REG_SSICDR 0x74 3462306a36Sopenharmony_ci#define CGU_REG_CIMCDR 0x7c 3562306a36Sopenharmony_ci#define CGU_REG_PCMCDR 0x84 3662306a36Sopenharmony_ci#define CGU_REG_MSC1CDR 0xa4 3762306a36Sopenharmony_ci#define CGU_REG_CMP_INTR 0xb0 3862306a36Sopenharmony_ci#define CGU_REG_CMP_INTRE 0xb4 3962306a36Sopenharmony_ci#define CGU_REG_DRCG 0xd0 4062306a36Sopenharmony_ci#define CGU_REG_CPCSR 0xd4 4162306a36Sopenharmony_ci#define CGU_REG_PCMCDR1 0xe0 4262306a36Sopenharmony_ci#define CGU_REG_MACPHYC 0xe8 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* bits within the OPCR register */ 4562306a36Sopenharmony_ci#define OPCR_SPENDN0 BIT(7) 4662306a36Sopenharmony_ci#define OPCR_SPENDN1 BIT(6) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* bits within the USBPCR register */ 4962306a36Sopenharmony_ci#define USBPCR_SIDDQ BIT(21) 5062306a36Sopenharmony_ci#define USBPCR_OTG_DISABLE BIT(20) 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* bits within the USBPCR1 register */ 5362306a36Sopenharmony_ci#define USBPCR1_REFCLKSEL_SHIFT 26 5462306a36Sopenharmony_ci#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT) 5562306a36Sopenharmony_ci#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT) 5662306a36Sopenharmony_ci#define USBPCR1_REFCLKDIV_SHIFT 24 5762306a36Sopenharmony_ci#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT) 5862306a36Sopenharmony_ci#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT) 5962306a36Sopenharmony_ci#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT) 6062306a36Sopenharmony_ci#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic struct ingenic_cgu *cgu; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic unsigned long x1000_otg_phy_recalc_rate(struct clk_hw *hw, 6562306a36Sopenharmony_ci unsigned long parent_rate) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci u32 usbpcr1; 6862306a36Sopenharmony_ci unsigned refclk_div; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); 7162306a36Sopenharmony_ci refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci switch (refclk_div) { 7462306a36Sopenharmony_ci case USBPCR1_REFCLKDIV_12: 7562306a36Sopenharmony_ci return 12000000; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci case USBPCR1_REFCLKDIV_24: 7862306a36Sopenharmony_ci return 24000000; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci case USBPCR1_REFCLKDIV_48: 8162306a36Sopenharmony_ci return 48000000; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return parent_rate; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic long x1000_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate, 8862306a36Sopenharmony_ci unsigned long *parent_rate) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci if (req_rate < 18000000) 9162306a36Sopenharmony_ci return 12000000; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (req_rate < 36000000) 9462306a36Sopenharmony_ci return 24000000; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return 48000000; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic int x1000_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate, 10062306a36Sopenharmony_ci unsigned long parent_rate) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci unsigned long flags; 10362306a36Sopenharmony_ci u32 usbpcr1, div_bits; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci switch (req_rate) { 10662306a36Sopenharmony_ci case 12000000: 10762306a36Sopenharmony_ci div_bits = USBPCR1_REFCLKDIV_12; 10862306a36Sopenharmony_ci break; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci case 24000000: 11162306a36Sopenharmony_ci div_bits = USBPCR1_REFCLKDIV_24; 11262306a36Sopenharmony_ci break; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci case 48000000: 11562306a36Sopenharmony_ci div_bits = USBPCR1_REFCLKDIV_48; 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci default: 11962306a36Sopenharmony_ci return -EINVAL; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci spin_lock_irqsave(&cgu->lock, flags); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); 12562306a36Sopenharmony_ci usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK; 12662306a36Sopenharmony_ci usbpcr1 |= div_bits; 12762306a36Sopenharmony_ci writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci spin_unlock_irqrestore(&cgu->lock, flags); 13062306a36Sopenharmony_ci return 0; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int x1000_usb_phy_enable(struct clk_hw *hw) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 13662306a36Sopenharmony_ci void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr); 13962306a36Sopenharmony_ci writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr); 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic void x1000_usb_phy_disable(struct clk_hw *hw) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 14662306a36Sopenharmony_ci void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr); 14962306a36Sopenharmony_ci writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic int x1000_usb_phy_is_enabled(struct clk_hw *hw) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 15562306a36Sopenharmony_ci void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return (readl(reg_opcr) & OPCR_SPENDN0) && 15862306a36Sopenharmony_ci !(readl(reg_usbpcr) & USBPCR_SIDDQ) && 15962306a36Sopenharmony_ci !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic const struct clk_ops x1000_otg_phy_ops = { 16362306a36Sopenharmony_ci .recalc_rate = x1000_otg_phy_recalc_rate, 16462306a36Sopenharmony_ci .round_rate = x1000_otg_phy_round_rate, 16562306a36Sopenharmony_ci .set_rate = x1000_otg_phy_set_rate, 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci .enable = x1000_usb_phy_enable, 16862306a36Sopenharmony_ci .disable = x1000_usb_phy_disable, 16962306a36Sopenharmony_ci .is_enabled = x1000_usb_phy_is_enabled, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic void 17362306a36Sopenharmony_cix1000_i2spll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, 17462306a36Sopenharmony_ci unsigned long rate, unsigned long parent_rate, 17562306a36Sopenharmony_ci unsigned int *pm, unsigned int *pn, unsigned int *pod) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci const unsigned long m_max = GENMASK(pll_info->m_bits - 1, 0); 17862306a36Sopenharmony_ci const unsigned long n_max = GENMASK(pll_info->n_bits - 1, 0); 17962306a36Sopenharmony_ci unsigned long m, n; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci rational_best_approximation(rate, parent_rate, m_max, n_max, &m, &n); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* n should not be less than 2*m */ 18462306a36Sopenharmony_ci if (n < 2 * m) 18562306a36Sopenharmony_ci n = 2 * m; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci *pm = m; 18862306a36Sopenharmony_ci *pn = n; 18962306a36Sopenharmony_ci *pod = 1; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic void 19362306a36Sopenharmony_cix1000_i2spll_set_rate_hook(const struct ingenic_cgu_pll_info *pll_info, 19462306a36Sopenharmony_ci unsigned long rate, unsigned long parent_rate) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci /* 19762306a36Sopenharmony_ci * Writing 0 causes I2SCDR1.I2SDIV_D to be automatically recalculated 19862306a36Sopenharmony_ci * based on the current value of I2SCDR.I2SDIV_N, which is needed for 19962306a36Sopenharmony_ci * the divider to function correctly. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci writel(0, cgu->base + CGU_REG_I2SCDR1); 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic const s8 pll_od_encoding[8] = { 20562306a36Sopenharmony_ci 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = { 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* External clocks */ 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci [X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT }, 21362306a36Sopenharmony_ci [X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT }, 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* PLLs */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci [X1000_CLK_APLL] = { 21862306a36Sopenharmony_ci "apll", CGU_CLK_PLL, 21962306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 22062306a36Sopenharmony_ci .pll = { 22162306a36Sopenharmony_ci .reg = CGU_REG_APLL, 22262306a36Sopenharmony_ci .rate_multiplier = 1, 22362306a36Sopenharmony_ci .m_shift = 24, 22462306a36Sopenharmony_ci .m_bits = 7, 22562306a36Sopenharmony_ci .m_offset = 1, 22662306a36Sopenharmony_ci .n_shift = 18, 22762306a36Sopenharmony_ci .n_bits = 5, 22862306a36Sopenharmony_ci .n_offset = 1, 22962306a36Sopenharmony_ci .od_shift = 16, 23062306a36Sopenharmony_ci .od_bits = 2, 23162306a36Sopenharmony_ci .od_max = 8, 23262306a36Sopenharmony_ci .od_encoding = pll_od_encoding, 23362306a36Sopenharmony_ci .bypass_reg = CGU_REG_APLL, 23462306a36Sopenharmony_ci .bypass_bit = 9, 23562306a36Sopenharmony_ci .enable_bit = 8, 23662306a36Sopenharmony_ci .stable_bit = 10, 23762306a36Sopenharmony_ci }, 23862306a36Sopenharmony_ci }, 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci [X1000_CLK_MPLL] = { 24162306a36Sopenharmony_ci "mpll", CGU_CLK_PLL, 24262306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 24362306a36Sopenharmony_ci .pll = { 24462306a36Sopenharmony_ci .reg = CGU_REG_MPLL, 24562306a36Sopenharmony_ci .rate_multiplier = 1, 24662306a36Sopenharmony_ci .m_shift = 24, 24762306a36Sopenharmony_ci .m_bits = 7, 24862306a36Sopenharmony_ci .m_offset = 1, 24962306a36Sopenharmony_ci .n_shift = 18, 25062306a36Sopenharmony_ci .n_bits = 5, 25162306a36Sopenharmony_ci .n_offset = 1, 25262306a36Sopenharmony_ci .od_shift = 16, 25362306a36Sopenharmony_ci .od_bits = 2, 25462306a36Sopenharmony_ci .od_max = 8, 25562306a36Sopenharmony_ci .od_encoding = pll_od_encoding, 25662306a36Sopenharmony_ci .bypass_reg = CGU_REG_MPLL, 25762306a36Sopenharmony_ci .bypass_bit = 6, 25862306a36Sopenharmony_ci .enable_bit = 7, 25962306a36Sopenharmony_ci .stable_bit = 0, 26062306a36Sopenharmony_ci }, 26162306a36Sopenharmony_ci }, 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Custom (SoC-specific) OTG PHY */ 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci [X1000_CLK_OTGPHY] = { 26662306a36Sopenharmony_ci "otg_phy", CGU_CLK_CUSTOM, 26762306a36Sopenharmony_ci .parents = { -1, -1, X1000_CLK_EXCLK, -1 }, 26862306a36Sopenharmony_ci .custom = { &x1000_otg_phy_ops }, 26962306a36Sopenharmony_ci }, 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* Muxes & dividers */ 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci [X1000_CLK_SCLKA] = { 27462306a36Sopenharmony_ci "sclk_a", CGU_CLK_MUX, 27562306a36Sopenharmony_ci .parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 }, 27662306a36Sopenharmony_ci .mux = { CGU_REG_CPCCR, 30, 2 }, 27762306a36Sopenharmony_ci }, 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci [X1000_CLK_CPUMUX] = { 28062306a36Sopenharmony_ci "cpu_mux", CGU_CLK_MUX, 28162306a36Sopenharmony_ci .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 28262306a36Sopenharmony_ci .mux = { CGU_REG_CPCCR, 28, 2 }, 28362306a36Sopenharmony_ci }, 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci [X1000_CLK_CPU] = { 28662306a36Sopenharmony_ci "cpu", CGU_CLK_DIV | CGU_CLK_GATE, 28762306a36Sopenharmony_ci /* 28862306a36Sopenharmony_ci * Disabling the CPU clock or any parent clocks will hang the 28962306a36Sopenharmony_ci * system; mark it critical. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_ci .flags = CLK_IS_CRITICAL, 29262306a36Sopenharmony_ci .parents = { X1000_CLK_CPUMUX }, 29362306a36Sopenharmony_ci .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, 29462306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 30 }, 29562306a36Sopenharmony_ci }, 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci [X1000_CLK_L2CACHE] = { 29862306a36Sopenharmony_ci "l2cache", CGU_CLK_DIV, 29962306a36Sopenharmony_ci /* 30062306a36Sopenharmony_ci * The L2 cache clock is critical if caches are enabled and 30162306a36Sopenharmony_ci * disabling it or any parent clocks will hang the system. 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_ci .flags = CLK_IS_CRITICAL, 30462306a36Sopenharmony_ci .parents = { X1000_CLK_CPUMUX }, 30562306a36Sopenharmony_ci .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, 30662306a36Sopenharmony_ci }, 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci [X1000_CLK_AHB0] = { 30962306a36Sopenharmony_ci "ahb0", CGU_CLK_MUX | CGU_CLK_DIV, 31062306a36Sopenharmony_ci .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 31162306a36Sopenharmony_ci .mux = { CGU_REG_CPCCR, 26, 2 }, 31262306a36Sopenharmony_ci .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 }, 31362306a36Sopenharmony_ci }, 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci [X1000_CLK_AHB2PMUX] = { 31662306a36Sopenharmony_ci "ahb2_apb_mux", CGU_CLK_MUX, 31762306a36Sopenharmony_ci .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 31862306a36Sopenharmony_ci .mux = { CGU_REG_CPCCR, 24, 2 }, 31962306a36Sopenharmony_ci }, 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci [X1000_CLK_AHB2] = { 32262306a36Sopenharmony_ci "ahb2", CGU_CLK_DIV, 32362306a36Sopenharmony_ci .parents = { X1000_CLK_AHB2PMUX }, 32462306a36Sopenharmony_ci .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 }, 32562306a36Sopenharmony_ci }, 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci [X1000_CLK_PCLK] = { 32862306a36Sopenharmony_ci "pclk", CGU_CLK_DIV | CGU_CLK_GATE, 32962306a36Sopenharmony_ci .parents = { X1000_CLK_AHB2PMUX }, 33062306a36Sopenharmony_ci .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 }, 33162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 28 }, 33262306a36Sopenharmony_ci }, 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci [X1000_CLK_DDR] = { 33562306a36Sopenharmony_ci "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 33662306a36Sopenharmony_ci /* 33762306a36Sopenharmony_ci * Disabling DDR clock or its parents will render DRAM 33862306a36Sopenharmony_ci * inaccessible; mark it critical. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci .flags = CLK_IS_CRITICAL, 34162306a36Sopenharmony_ci .parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 }, 34262306a36Sopenharmony_ci .mux = { CGU_REG_DDRCDR, 30, 2 }, 34362306a36Sopenharmony_ci .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 }, 34462306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 31 }, 34562306a36Sopenharmony_ci }, 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci [X1000_CLK_MAC] = { 34862306a36Sopenharmony_ci "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 34962306a36Sopenharmony_ci .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 35062306a36Sopenharmony_ci .mux = { CGU_REG_MACCDR, 31, 1 }, 35162306a36Sopenharmony_ci .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 }, 35262306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 25 }, 35362306a36Sopenharmony_ci }, 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci [X1000_CLK_I2SPLLMUX] = { 35662306a36Sopenharmony_ci "i2s_pll_mux", CGU_CLK_MUX, 35762306a36Sopenharmony_ci .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 35862306a36Sopenharmony_ci .mux = { CGU_REG_I2SCDR, 31, 1 }, 35962306a36Sopenharmony_ci }, 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci [X1000_CLK_I2SPLL] = { 36262306a36Sopenharmony_ci "i2s_pll", CGU_CLK_PLL, 36362306a36Sopenharmony_ci .parents = { X1000_CLK_I2SPLLMUX }, 36462306a36Sopenharmony_ci .pll = { 36562306a36Sopenharmony_ci .reg = CGU_REG_I2SCDR, 36662306a36Sopenharmony_ci .rate_multiplier = 1, 36762306a36Sopenharmony_ci .m_shift = 13, 36862306a36Sopenharmony_ci .m_bits = 9, 36962306a36Sopenharmony_ci .n_shift = 0, 37062306a36Sopenharmony_ci .n_bits = 13, 37162306a36Sopenharmony_ci .calc_m_n_od = x1000_i2spll_calc_m_n_od, 37262306a36Sopenharmony_ci .set_rate_hook = x1000_i2spll_set_rate_hook, 37362306a36Sopenharmony_ci }, 37462306a36Sopenharmony_ci }, 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci [X1000_CLK_I2S] = { 37762306a36Sopenharmony_ci "i2s", CGU_CLK_MUX, 37862306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK, -1, -1, X1000_CLK_I2SPLL }, 37962306a36Sopenharmony_ci /* 38062306a36Sopenharmony_ci * NOTE: the mux is at bit 30; bit 29 enables the M/N divider. 38162306a36Sopenharmony_ci * Therefore, the divider is disabled when EXCLK is selected. 38262306a36Sopenharmony_ci */ 38362306a36Sopenharmony_ci .mux = { CGU_REG_I2SCDR, 29, 2 }, 38462306a36Sopenharmony_ci }, 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci [X1000_CLK_LCD] = { 38762306a36Sopenharmony_ci "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE, 38862306a36Sopenharmony_ci .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 38962306a36Sopenharmony_ci .mux = { CGU_REG_LPCDR, 31, 1 }, 39062306a36Sopenharmony_ci .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 }, 39162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 23 }, 39262306a36Sopenharmony_ci }, 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci [X1000_CLK_MSCMUX] = { 39562306a36Sopenharmony_ci "msc_mux", CGU_CLK_MUX, 39662306a36Sopenharmony_ci .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 39762306a36Sopenharmony_ci .mux = { CGU_REG_MSC0CDR, 31, 1 }, 39862306a36Sopenharmony_ci }, 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci [X1000_CLK_MSC0] = { 40162306a36Sopenharmony_ci "msc0", CGU_CLK_DIV | CGU_CLK_GATE, 40262306a36Sopenharmony_ci .parents = { X1000_CLK_MSCMUX }, 40362306a36Sopenharmony_ci .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 }, 40462306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 4 }, 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci [X1000_CLK_MSC1] = { 40862306a36Sopenharmony_ci "msc1", CGU_CLK_DIV | CGU_CLK_GATE, 40962306a36Sopenharmony_ci .parents = { X1000_CLK_MSCMUX, -1, -1, -1 }, 41062306a36Sopenharmony_ci .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 }, 41162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 5 }, 41262306a36Sopenharmony_ci }, 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci [X1000_CLK_OTG] = { 41562306a36Sopenharmony_ci "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 41662306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK, -1, X1000_CLK_APLL, X1000_CLK_MPLL }, 41762306a36Sopenharmony_ci .mux = { CGU_REG_USBCDR, 30, 2 }, 41862306a36Sopenharmony_ci .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 }, 41962306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 3 }, 42062306a36Sopenharmony_ci }, 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci [X1000_CLK_SSIPLL] = { 42362306a36Sopenharmony_ci "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV, 42462306a36Sopenharmony_ci .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL }, 42562306a36Sopenharmony_ci .mux = { CGU_REG_SSICDR, 31, 1 }, 42662306a36Sopenharmony_ci .div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 }, 42762306a36Sopenharmony_ci }, 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci [X1000_CLK_SSIPLL_DIV2] = { 43062306a36Sopenharmony_ci "ssi_pll_div2", CGU_CLK_FIXDIV, 43162306a36Sopenharmony_ci .parents = { X1000_CLK_SSIPLL }, 43262306a36Sopenharmony_ci .fixdiv = { 2 }, 43362306a36Sopenharmony_ci }, 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci [X1000_CLK_SSIMUX] = { 43662306a36Sopenharmony_ci "ssi_mux", CGU_CLK_MUX, 43762306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2 }, 43862306a36Sopenharmony_ci .mux = { CGU_REG_SSICDR, 30, 1 }, 43962306a36Sopenharmony_ci }, 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci [X1000_CLK_EXCLK_DIV512] = { 44262306a36Sopenharmony_ci "exclk_div512", CGU_CLK_FIXDIV, 44362306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 44462306a36Sopenharmony_ci .fixdiv = { 512 }, 44562306a36Sopenharmony_ci }, 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci [X1000_CLK_RTC] = { 44862306a36Sopenharmony_ci "rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE, 44962306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK }, 45062306a36Sopenharmony_ci .mux = { CGU_REG_OPCR, 2, 1}, 45162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 27 }, 45262306a36Sopenharmony_ci }, 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Gate-only clocks */ 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci [X1000_CLK_EMC] = { 45762306a36Sopenharmony_ci "emc", CGU_CLK_GATE, 45862306a36Sopenharmony_ci .parents = { X1000_CLK_AHB2 }, 45962306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 0 }, 46062306a36Sopenharmony_ci }, 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci [X1000_CLK_EFUSE] = { 46362306a36Sopenharmony_ci "efuse", CGU_CLK_GATE, 46462306a36Sopenharmony_ci .parents = { X1000_CLK_AHB2 }, 46562306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 1 }, 46662306a36Sopenharmony_ci }, 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci [X1000_CLK_SFC] = { 46962306a36Sopenharmony_ci "sfc", CGU_CLK_GATE, 47062306a36Sopenharmony_ci .parents = { X1000_CLK_SSIPLL }, 47162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 2 }, 47262306a36Sopenharmony_ci }, 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci [X1000_CLK_I2C0] = { 47562306a36Sopenharmony_ci "i2c0", CGU_CLK_GATE, 47662306a36Sopenharmony_ci .parents = { X1000_CLK_PCLK }, 47762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 7 }, 47862306a36Sopenharmony_ci }, 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci [X1000_CLK_I2C1] = { 48162306a36Sopenharmony_ci "i2c1", CGU_CLK_GATE, 48262306a36Sopenharmony_ci .parents = { X1000_CLK_PCLK }, 48362306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 8 }, 48462306a36Sopenharmony_ci }, 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci [X1000_CLK_I2C2] = { 48762306a36Sopenharmony_ci "i2c2", CGU_CLK_GATE, 48862306a36Sopenharmony_ci .parents = { X1000_CLK_PCLK }, 48962306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 9 }, 49062306a36Sopenharmony_ci }, 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci [X1000_CLK_AIC] = { 49362306a36Sopenharmony_ci "aic", CGU_CLK_GATE, 49462306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 49562306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 11 }, 49662306a36Sopenharmony_ci }, 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci [X1000_CLK_UART0] = { 49962306a36Sopenharmony_ci "uart0", CGU_CLK_GATE, 50062306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 50162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 14 }, 50262306a36Sopenharmony_ci }, 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci [X1000_CLK_UART1] = { 50562306a36Sopenharmony_ci "uart1", CGU_CLK_GATE, 50662306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK}, 50762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 15 }, 50862306a36Sopenharmony_ci }, 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci [X1000_CLK_UART2] = { 51162306a36Sopenharmony_ci "uart2", CGU_CLK_GATE, 51262306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 51362306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 16 }, 51462306a36Sopenharmony_ci }, 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci [X1000_CLK_TCU] = { 51762306a36Sopenharmony_ci "tcu", CGU_CLK_GATE, 51862306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 51962306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 18 }, 52062306a36Sopenharmony_ci }, 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci [X1000_CLK_SSI] = { 52362306a36Sopenharmony_ci "ssi", CGU_CLK_GATE, 52462306a36Sopenharmony_ci .parents = { X1000_CLK_SSIMUX }, 52562306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 19 }, 52662306a36Sopenharmony_ci }, 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci [X1000_CLK_OST] = { 52962306a36Sopenharmony_ci "ost", CGU_CLK_GATE, 53062306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 53162306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 20 }, 53262306a36Sopenharmony_ci }, 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci [X1000_CLK_PDMA] = { 53562306a36Sopenharmony_ci "pdma", CGU_CLK_GATE, 53662306a36Sopenharmony_ci .parents = { X1000_CLK_EXCLK }, 53762306a36Sopenharmony_ci .gate = { CGU_REG_CLKGR, 21 }, 53862306a36Sopenharmony_ci }, 53962306a36Sopenharmony_ci}; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic void __init x1000_cgu_init(struct device_node *np) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci int retval; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci cgu = ingenic_cgu_new(x1000_cgu_clocks, 54662306a36Sopenharmony_ci ARRAY_SIZE(x1000_cgu_clocks), np); 54762306a36Sopenharmony_ci if (!cgu) { 54862306a36Sopenharmony_ci pr_err("%s: failed to initialise CGU\n", __func__); 54962306a36Sopenharmony_ci return; 55062306a36Sopenharmony_ci } 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci retval = ingenic_cgu_register_clocks(cgu); 55362306a36Sopenharmony_ci if (retval) { 55462306a36Sopenharmony_ci pr_err("%s: failed to register CGU Clocks\n", __func__); 55562306a36Sopenharmony_ci return; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci ingenic_cgu_register_syscore_ops(cgu); 55962306a36Sopenharmony_ci} 56062306a36Sopenharmony_ci/* 56162306a36Sopenharmony_ci * CGU has some children devices, this is useful for probing children devices 56262306a36Sopenharmony_ci * in the case where the device node is compatible with "simple-mfd". 56362306a36Sopenharmony_ci */ 56462306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init); 565