1*7a01c190SPaul Cercueil // SPDX-License-Identifier: GPL-2.0 2*7a01c190SPaul Cercueil /* 3*7a01c190SPaul Cercueil * JZ4770 SoC CGU driver 4*7a01c190SPaul Cercueil * Copyright 2018, Paul Cercueil <paul@crapouillou.net> 5*7a01c190SPaul Cercueil */ 6*7a01c190SPaul Cercueil 7*7a01c190SPaul Cercueil #include <linux/bitops.h> 8*7a01c190SPaul Cercueil #include <linux/clk-provider.h> 9*7a01c190SPaul Cercueil #include <linux/delay.h> 10*7a01c190SPaul Cercueil #include <linux/of.h> 11*7a01c190SPaul Cercueil #include <linux/syscore_ops.h> 12*7a01c190SPaul Cercueil #include <dt-bindings/clock/jz4770-cgu.h> 13*7a01c190SPaul Cercueil #include "cgu.h" 14*7a01c190SPaul Cercueil 15*7a01c190SPaul Cercueil /* 16*7a01c190SPaul Cercueil * CPM registers offset address definition 17*7a01c190SPaul Cercueil */ 18*7a01c190SPaul Cercueil #define CGU_REG_CPCCR 0x00 19*7a01c190SPaul Cercueil #define CGU_REG_LCR 0x04 20*7a01c190SPaul Cercueil #define CGU_REG_CPPCR0 0x10 21*7a01c190SPaul Cercueil #define CGU_REG_CLKGR0 0x20 22*7a01c190SPaul Cercueil #define CGU_REG_OPCR 0x24 23*7a01c190SPaul Cercueil #define CGU_REG_CLKGR1 0x28 24*7a01c190SPaul Cercueil #define CGU_REG_CPPCR1 0x30 25*7a01c190SPaul Cercueil #define CGU_REG_USBPCR1 0x48 26*7a01c190SPaul Cercueil #define CGU_REG_USBCDR 0x50 27*7a01c190SPaul Cercueil #define CGU_REG_I2SCDR 0x60 28*7a01c190SPaul Cercueil #define CGU_REG_LPCDR 0x64 29*7a01c190SPaul Cercueil #define CGU_REG_MSC0CDR 0x68 30*7a01c190SPaul Cercueil #define CGU_REG_UHCCDR 0x6c 31*7a01c190SPaul Cercueil #define CGU_REG_SSICDR 0x74 32*7a01c190SPaul Cercueil #define CGU_REG_CIMCDR 0x7c 33*7a01c190SPaul Cercueil #define CGU_REG_GPSCDR 0x80 34*7a01c190SPaul Cercueil #define CGU_REG_PCMCDR 0x84 35*7a01c190SPaul Cercueil #define CGU_REG_GPUCDR 0x88 36*7a01c190SPaul Cercueil #define CGU_REG_MSC1CDR 0xA4 37*7a01c190SPaul Cercueil #define CGU_REG_MSC2CDR 0xA8 38*7a01c190SPaul Cercueil #define CGU_REG_BCHCDR 0xAC 39*7a01c190SPaul Cercueil 40*7a01c190SPaul Cercueil /* bits within the LCR register */ 41*7a01c190SPaul Cercueil #define LCR_LPM BIT(0) /* Low Power Mode */ 42*7a01c190SPaul Cercueil 43*7a01c190SPaul Cercueil /* bits within the OPCR register */ 44*7a01c190SPaul Cercueil #define OPCR_SPENDH BIT(5) /* UHC PHY suspend */ 45*7a01c190SPaul Cercueil #define OPCR_SPENDN BIT(7) /* OTG PHY suspend */ 46*7a01c190SPaul Cercueil 47*7a01c190SPaul Cercueil /* bits within the USBPCR1 register */ 48*7a01c190SPaul Cercueil #define USBPCR1_UHC_POWER BIT(5) /* UHC PHY power down */ 49*7a01c190SPaul Cercueil 50*7a01c190SPaul Cercueil static struct ingenic_cgu *cgu; 51*7a01c190SPaul Cercueil 52*7a01c190SPaul Cercueil static int jz4770_uhc_phy_enable(struct clk_hw *hw) 53*7a01c190SPaul Cercueil { 54*7a01c190SPaul Cercueil void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 55*7a01c190SPaul Cercueil void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1; 56*7a01c190SPaul Cercueil 57*7a01c190SPaul Cercueil writel(readl(reg_opcr) & ~OPCR_SPENDH, reg_opcr); 58*7a01c190SPaul Cercueil writel(readl(reg_usbpcr1) | USBPCR1_UHC_POWER, reg_usbpcr1); 59*7a01c190SPaul Cercueil return 0; 60*7a01c190SPaul Cercueil } 61*7a01c190SPaul Cercueil 62*7a01c190SPaul Cercueil static void jz4770_uhc_phy_disable(struct clk_hw *hw) 63*7a01c190SPaul Cercueil { 64*7a01c190SPaul Cercueil void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 65*7a01c190SPaul Cercueil void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1; 66*7a01c190SPaul Cercueil 67*7a01c190SPaul Cercueil writel(readl(reg_usbpcr1) & ~USBPCR1_UHC_POWER, reg_usbpcr1); 68*7a01c190SPaul Cercueil writel(readl(reg_opcr) | OPCR_SPENDH, reg_opcr); 69*7a01c190SPaul Cercueil } 70*7a01c190SPaul Cercueil 71*7a01c190SPaul Cercueil static int jz4770_uhc_phy_is_enabled(struct clk_hw *hw) 72*7a01c190SPaul Cercueil { 73*7a01c190SPaul Cercueil void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 74*7a01c190SPaul Cercueil void __iomem *reg_usbpcr1 = cgu->base + CGU_REG_USBPCR1; 75*7a01c190SPaul Cercueil 76*7a01c190SPaul Cercueil return !(readl(reg_opcr) & OPCR_SPENDH) && 77*7a01c190SPaul Cercueil (readl(reg_usbpcr1) & USBPCR1_UHC_POWER); 78*7a01c190SPaul Cercueil } 79*7a01c190SPaul Cercueil 80*7a01c190SPaul Cercueil static const struct clk_ops jz4770_uhc_phy_ops = { 81*7a01c190SPaul Cercueil .enable = jz4770_uhc_phy_enable, 82*7a01c190SPaul Cercueil .disable = jz4770_uhc_phy_disable, 83*7a01c190SPaul Cercueil .is_enabled = jz4770_uhc_phy_is_enabled, 84*7a01c190SPaul Cercueil }; 85*7a01c190SPaul Cercueil 86*7a01c190SPaul Cercueil static int jz4770_otg_phy_enable(struct clk_hw *hw) 87*7a01c190SPaul Cercueil { 88*7a01c190SPaul Cercueil void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 89*7a01c190SPaul Cercueil 90*7a01c190SPaul Cercueil writel(readl(reg_opcr) | OPCR_SPENDN, reg_opcr); 91*7a01c190SPaul Cercueil 92*7a01c190SPaul Cercueil /* Wait for the clock to be stable */ 93*7a01c190SPaul Cercueil udelay(50); 94*7a01c190SPaul Cercueil return 0; 95*7a01c190SPaul Cercueil } 96*7a01c190SPaul Cercueil 97*7a01c190SPaul Cercueil static void jz4770_otg_phy_disable(struct clk_hw *hw) 98*7a01c190SPaul Cercueil { 99*7a01c190SPaul Cercueil void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 100*7a01c190SPaul Cercueil 101*7a01c190SPaul Cercueil writel(readl(reg_opcr) & ~OPCR_SPENDN, reg_opcr); 102*7a01c190SPaul Cercueil } 103*7a01c190SPaul Cercueil 104*7a01c190SPaul Cercueil static int jz4770_otg_phy_is_enabled(struct clk_hw *hw) 105*7a01c190SPaul Cercueil { 106*7a01c190SPaul Cercueil void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR; 107*7a01c190SPaul Cercueil 108*7a01c190SPaul Cercueil return !!(readl(reg_opcr) & OPCR_SPENDN); 109*7a01c190SPaul Cercueil } 110*7a01c190SPaul Cercueil 111*7a01c190SPaul Cercueil static const struct clk_ops jz4770_otg_phy_ops = { 112*7a01c190SPaul Cercueil .enable = jz4770_otg_phy_enable, 113*7a01c190SPaul Cercueil .disable = jz4770_otg_phy_disable, 114*7a01c190SPaul Cercueil .is_enabled = jz4770_otg_phy_is_enabled, 115*7a01c190SPaul Cercueil }; 116*7a01c190SPaul Cercueil 117*7a01c190SPaul Cercueil static const s8 pll_od_encoding[8] = { 118*7a01c190SPaul Cercueil 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, 119*7a01c190SPaul Cercueil }; 120*7a01c190SPaul Cercueil 121*7a01c190SPaul Cercueil static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { 122*7a01c190SPaul Cercueil 123*7a01c190SPaul Cercueil /* External clocks */ 124*7a01c190SPaul Cercueil 125*7a01c190SPaul Cercueil [JZ4770_CLK_EXT] = { "ext", CGU_CLK_EXT }, 126*7a01c190SPaul Cercueil [JZ4770_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, 127*7a01c190SPaul Cercueil 128*7a01c190SPaul Cercueil /* PLLs */ 129*7a01c190SPaul Cercueil 130*7a01c190SPaul Cercueil [JZ4770_CLK_PLL0] = { 131*7a01c190SPaul Cercueil "pll0", CGU_CLK_PLL, 132*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT }, 133*7a01c190SPaul Cercueil .pll = { 134*7a01c190SPaul Cercueil .reg = CGU_REG_CPPCR0, 135*7a01c190SPaul Cercueil .m_shift = 24, 136*7a01c190SPaul Cercueil .m_bits = 7, 137*7a01c190SPaul Cercueil .m_offset = 1, 138*7a01c190SPaul Cercueil .n_shift = 18, 139*7a01c190SPaul Cercueil .n_bits = 5, 140*7a01c190SPaul Cercueil .n_offset = 1, 141*7a01c190SPaul Cercueil .od_shift = 16, 142*7a01c190SPaul Cercueil .od_bits = 2, 143*7a01c190SPaul Cercueil .od_max = 8, 144*7a01c190SPaul Cercueil .od_encoding = pll_od_encoding, 145*7a01c190SPaul Cercueil .bypass_bit = 9, 146*7a01c190SPaul Cercueil .enable_bit = 8, 147*7a01c190SPaul Cercueil .stable_bit = 10, 148*7a01c190SPaul Cercueil }, 149*7a01c190SPaul Cercueil }, 150*7a01c190SPaul Cercueil 151*7a01c190SPaul Cercueil [JZ4770_CLK_PLL1] = { 152*7a01c190SPaul Cercueil /* TODO: PLL1 can depend on PLL0 */ 153*7a01c190SPaul Cercueil "pll1", CGU_CLK_PLL, 154*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT }, 155*7a01c190SPaul Cercueil .pll = { 156*7a01c190SPaul Cercueil .reg = CGU_REG_CPPCR1, 157*7a01c190SPaul Cercueil .m_shift = 24, 158*7a01c190SPaul Cercueil .m_bits = 7, 159*7a01c190SPaul Cercueil .m_offset = 1, 160*7a01c190SPaul Cercueil .n_shift = 18, 161*7a01c190SPaul Cercueil .n_bits = 5, 162*7a01c190SPaul Cercueil .n_offset = 1, 163*7a01c190SPaul Cercueil .od_shift = 16, 164*7a01c190SPaul Cercueil .od_bits = 2, 165*7a01c190SPaul Cercueil .od_max = 8, 166*7a01c190SPaul Cercueil .od_encoding = pll_od_encoding, 167*7a01c190SPaul Cercueil .enable_bit = 7, 168*7a01c190SPaul Cercueil .stable_bit = 6, 169*7a01c190SPaul Cercueil .no_bypass_bit = true, 170*7a01c190SPaul Cercueil }, 171*7a01c190SPaul Cercueil }, 172*7a01c190SPaul Cercueil 173*7a01c190SPaul Cercueil /* Main clocks */ 174*7a01c190SPaul Cercueil 175*7a01c190SPaul Cercueil [JZ4770_CLK_CCLK] = { 176*7a01c190SPaul Cercueil "cclk", CGU_CLK_DIV, 177*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, }, 178*7a01c190SPaul Cercueil .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 }, 179*7a01c190SPaul Cercueil }, 180*7a01c190SPaul Cercueil [JZ4770_CLK_H0CLK] = { 181*7a01c190SPaul Cercueil "h0clk", CGU_CLK_DIV, 182*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, }, 183*7a01c190SPaul Cercueil .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 }, 184*7a01c190SPaul Cercueil }, 185*7a01c190SPaul Cercueil [JZ4770_CLK_H1CLK] = { 186*7a01c190SPaul Cercueil "h1clk", CGU_CLK_DIV | CGU_CLK_GATE, 187*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, }, 188*7a01c190SPaul Cercueil .div = { CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1 }, 189*7a01c190SPaul Cercueil .gate = { CGU_REG_LCR, 30 }, 190*7a01c190SPaul Cercueil }, 191*7a01c190SPaul Cercueil [JZ4770_CLK_H2CLK] = { 192*7a01c190SPaul Cercueil "h2clk", CGU_CLK_DIV, 193*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, }, 194*7a01c190SPaul Cercueil .div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 }, 195*7a01c190SPaul Cercueil }, 196*7a01c190SPaul Cercueil [JZ4770_CLK_C1CLK] = { 197*7a01c190SPaul Cercueil "c1clk", CGU_CLK_DIV, 198*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, }, 199*7a01c190SPaul Cercueil .div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 }, 200*7a01c190SPaul Cercueil }, 201*7a01c190SPaul Cercueil [JZ4770_CLK_PCLK] = { 202*7a01c190SPaul Cercueil "pclk", CGU_CLK_DIV, 203*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, }, 204*7a01c190SPaul Cercueil .div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 }, 205*7a01c190SPaul Cercueil }, 206*7a01c190SPaul Cercueil 207*7a01c190SPaul Cercueil /* Those divided clocks can connect to PLL0 or PLL1 */ 208*7a01c190SPaul Cercueil 209*7a01c190SPaul Cercueil [JZ4770_CLK_MMC0_MUX] = { 210*7a01c190SPaul Cercueil "mmc0_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 211*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 212*7a01c190SPaul Cercueil .mux = { CGU_REG_MSC0CDR, 30, 1 }, 213*7a01c190SPaul Cercueil .div = { CGU_REG_MSC0CDR, 0, 1, 7, -1, -1, 31 }, 214*7a01c190SPaul Cercueil .gate = { CGU_REG_MSC0CDR, 31 }, 215*7a01c190SPaul Cercueil }, 216*7a01c190SPaul Cercueil [JZ4770_CLK_MMC1_MUX] = { 217*7a01c190SPaul Cercueil "mmc1_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 218*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 219*7a01c190SPaul Cercueil .mux = { CGU_REG_MSC1CDR, 30, 1 }, 220*7a01c190SPaul Cercueil .div = { CGU_REG_MSC1CDR, 0, 1, 7, -1, -1, 31 }, 221*7a01c190SPaul Cercueil .gate = { CGU_REG_MSC1CDR, 31 }, 222*7a01c190SPaul Cercueil }, 223*7a01c190SPaul Cercueil [JZ4770_CLK_MMC2_MUX] = { 224*7a01c190SPaul Cercueil "mmc2_mux", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 225*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 226*7a01c190SPaul Cercueil .mux = { CGU_REG_MSC2CDR, 30, 1 }, 227*7a01c190SPaul Cercueil .div = { CGU_REG_MSC2CDR, 0, 1, 7, -1, -1, 31 }, 228*7a01c190SPaul Cercueil .gate = { CGU_REG_MSC2CDR, 31 }, 229*7a01c190SPaul Cercueil }, 230*7a01c190SPaul Cercueil [JZ4770_CLK_CIM] = { 231*7a01c190SPaul Cercueil "cim", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 232*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 233*7a01c190SPaul Cercueil .mux = { CGU_REG_CIMCDR, 31, 1 }, 234*7a01c190SPaul Cercueil .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 }, 235*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 26 }, 236*7a01c190SPaul Cercueil }, 237*7a01c190SPaul Cercueil [JZ4770_CLK_UHC] = { 238*7a01c190SPaul Cercueil "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 239*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 240*7a01c190SPaul Cercueil .mux = { CGU_REG_UHCCDR, 29, 1 }, 241*7a01c190SPaul Cercueil .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 }, 242*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 24 }, 243*7a01c190SPaul Cercueil }, 244*7a01c190SPaul Cercueil [JZ4770_CLK_GPU] = { 245*7a01c190SPaul Cercueil "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 246*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, -1 }, 247*7a01c190SPaul Cercueil .mux = { CGU_REG_GPUCDR, 31, 1 }, 248*7a01c190SPaul Cercueil .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 }, 249*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 9 }, 250*7a01c190SPaul Cercueil }, 251*7a01c190SPaul Cercueil [JZ4770_CLK_BCH] = { 252*7a01c190SPaul Cercueil "bch", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 253*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 254*7a01c190SPaul Cercueil .mux = { CGU_REG_BCHCDR, 31, 1 }, 255*7a01c190SPaul Cercueil .div = { CGU_REG_BCHCDR, 0, 1, 3, -1, -1, -1 }, 256*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 1 }, 257*7a01c190SPaul Cercueil }, 258*7a01c190SPaul Cercueil [JZ4770_CLK_LPCLK_MUX] = { 259*7a01c190SPaul Cercueil "lpclk", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 260*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 261*7a01c190SPaul Cercueil .mux = { CGU_REG_LPCDR, 29, 1 }, 262*7a01c190SPaul Cercueil .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, 263*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 28 }, 264*7a01c190SPaul Cercueil }, 265*7a01c190SPaul Cercueil [JZ4770_CLK_GPS] = { 266*7a01c190SPaul Cercueil "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 267*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PLL0, JZ4770_CLK_PLL1, }, 268*7a01c190SPaul Cercueil .mux = { CGU_REG_GPSCDR, 31, 1 }, 269*7a01c190SPaul Cercueil .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 }, 270*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 22 }, 271*7a01c190SPaul Cercueil }, 272*7a01c190SPaul Cercueil 273*7a01c190SPaul Cercueil /* Those divided clocks can connect to EXT, PLL0 or PLL1 */ 274*7a01c190SPaul Cercueil 275*7a01c190SPaul Cercueil [JZ4770_CLK_SSI_MUX] = { 276*7a01c190SPaul Cercueil "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX, 277*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, -1, 278*7a01c190SPaul Cercueil JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 }, 279*7a01c190SPaul Cercueil .mux = { CGU_REG_SSICDR, 30, 2 }, 280*7a01c190SPaul Cercueil .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1 }, 281*7a01c190SPaul Cercueil }, 282*7a01c190SPaul Cercueil [JZ4770_CLK_PCM_MUX] = { 283*7a01c190SPaul Cercueil "pcm_mux", CGU_CLK_DIV | CGU_CLK_MUX, 284*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, -1, 285*7a01c190SPaul Cercueil JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 }, 286*7a01c190SPaul Cercueil .mux = { CGU_REG_PCMCDR, 30, 2 }, 287*7a01c190SPaul Cercueil .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1 }, 288*7a01c190SPaul Cercueil }, 289*7a01c190SPaul Cercueil [JZ4770_CLK_I2S] = { 290*7a01c190SPaul Cercueil "i2s", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 291*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, -1, 292*7a01c190SPaul Cercueil JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 }, 293*7a01c190SPaul Cercueil .mux = { CGU_REG_I2SCDR, 30, 2 }, 294*7a01c190SPaul Cercueil .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 }, 295*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 13 }, 296*7a01c190SPaul Cercueil }, 297*7a01c190SPaul Cercueil [JZ4770_CLK_OTG] = { 298*7a01c190SPaul Cercueil "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, 299*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, -1, 300*7a01c190SPaul Cercueil JZ4770_CLK_PLL0, JZ4770_CLK_PLL1 }, 301*7a01c190SPaul Cercueil .mux = { CGU_REG_USBCDR, 30, 2 }, 302*7a01c190SPaul Cercueil .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 }, 303*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 2 }, 304*7a01c190SPaul Cercueil }, 305*7a01c190SPaul Cercueil 306*7a01c190SPaul Cercueil /* Gate-only clocks */ 307*7a01c190SPaul Cercueil 308*7a01c190SPaul Cercueil [JZ4770_CLK_SSI0] = { 309*7a01c190SPaul Cercueil "ssi0", CGU_CLK_GATE, 310*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_SSI_MUX, }, 311*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 4 }, 312*7a01c190SPaul Cercueil }, 313*7a01c190SPaul Cercueil [JZ4770_CLK_SSI1] = { 314*7a01c190SPaul Cercueil "ssi1", CGU_CLK_GATE, 315*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_SSI_MUX, }, 316*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 19 }, 317*7a01c190SPaul Cercueil }, 318*7a01c190SPaul Cercueil [JZ4770_CLK_SSI2] = { 319*7a01c190SPaul Cercueil "ssi2", CGU_CLK_GATE, 320*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_SSI_MUX, }, 321*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 20 }, 322*7a01c190SPaul Cercueil }, 323*7a01c190SPaul Cercueil [JZ4770_CLK_PCM0] = { 324*7a01c190SPaul Cercueil "pcm0", CGU_CLK_GATE, 325*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PCM_MUX, }, 326*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 8 }, 327*7a01c190SPaul Cercueil }, 328*7a01c190SPaul Cercueil [JZ4770_CLK_PCM1] = { 329*7a01c190SPaul Cercueil "pcm1", CGU_CLK_GATE, 330*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_PCM_MUX, }, 331*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 10 }, 332*7a01c190SPaul Cercueil }, 333*7a01c190SPaul Cercueil [JZ4770_CLK_DMA] = { 334*7a01c190SPaul Cercueil "dma", CGU_CLK_GATE, 335*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_H2CLK, }, 336*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 21 }, 337*7a01c190SPaul Cercueil }, 338*7a01c190SPaul Cercueil [JZ4770_CLK_I2C0] = { 339*7a01c190SPaul Cercueil "i2c0", CGU_CLK_GATE, 340*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 341*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 5 }, 342*7a01c190SPaul Cercueil }, 343*7a01c190SPaul Cercueil [JZ4770_CLK_I2C1] = { 344*7a01c190SPaul Cercueil "i2c1", CGU_CLK_GATE, 345*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 346*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 6 }, 347*7a01c190SPaul Cercueil }, 348*7a01c190SPaul Cercueil [JZ4770_CLK_I2C2] = { 349*7a01c190SPaul Cercueil "i2c2", CGU_CLK_GATE, 350*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 351*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 15 }, 352*7a01c190SPaul Cercueil }, 353*7a01c190SPaul Cercueil [JZ4770_CLK_UART0] = { 354*7a01c190SPaul Cercueil "uart0", CGU_CLK_GATE, 355*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 356*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 15 }, 357*7a01c190SPaul Cercueil }, 358*7a01c190SPaul Cercueil [JZ4770_CLK_UART1] = { 359*7a01c190SPaul Cercueil "uart1", CGU_CLK_GATE, 360*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 361*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 16 }, 362*7a01c190SPaul Cercueil }, 363*7a01c190SPaul Cercueil [JZ4770_CLK_UART2] = { 364*7a01c190SPaul Cercueil "uart2", CGU_CLK_GATE, 365*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 366*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 17 }, 367*7a01c190SPaul Cercueil }, 368*7a01c190SPaul Cercueil [JZ4770_CLK_UART3] = { 369*7a01c190SPaul Cercueil "uart3", CGU_CLK_GATE, 370*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 371*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 18 }, 372*7a01c190SPaul Cercueil }, 373*7a01c190SPaul Cercueil [JZ4770_CLK_IPU] = { 374*7a01c190SPaul Cercueil "ipu", CGU_CLK_GATE, 375*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_H0CLK, }, 376*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 29 }, 377*7a01c190SPaul Cercueil }, 378*7a01c190SPaul Cercueil [JZ4770_CLK_ADC] = { 379*7a01c190SPaul Cercueil "adc", CGU_CLK_GATE, 380*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 381*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 14 }, 382*7a01c190SPaul Cercueil }, 383*7a01c190SPaul Cercueil [JZ4770_CLK_AIC] = { 384*7a01c190SPaul Cercueil "aic", CGU_CLK_GATE, 385*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT, }, 386*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 8 }, 387*7a01c190SPaul Cercueil }, 388*7a01c190SPaul Cercueil [JZ4770_CLK_AUX] = { 389*7a01c190SPaul Cercueil "aux", CGU_CLK_GATE, 390*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_C1CLK, }, 391*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 14 }, 392*7a01c190SPaul Cercueil }, 393*7a01c190SPaul Cercueil [JZ4770_CLK_VPU] = { 394*7a01c190SPaul Cercueil "vpu", CGU_CLK_GATE, 395*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_H1CLK, }, 396*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR1, 7 }, 397*7a01c190SPaul Cercueil }, 398*7a01c190SPaul Cercueil [JZ4770_CLK_MMC0] = { 399*7a01c190SPaul Cercueil "mmc0", CGU_CLK_GATE, 400*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_MMC0_MUX, }, 401*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 3 }, 402*7a01c190SPaul Cercueil }, 403*7a01c190SPaul Cercueil [JZ4770_CLK_MMC1] = { 404*7a01c190SPaul Cercueil "mmc1", CGU_CLK_GATE, 405*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_MMC1_MUX, }, 406*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 11 }, 407*7a01c190SPaul Cercueil }, 408*7a01c190SPaul Cercueil [JZ4770_CLK_MMC2] = { 409*7a01c190SPaul Cercueil "mmc2", CGU_CLK_GATE, 410*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_MMC2_MUX, }, 411*7a01c190SPaul Cercueil .gate = { CGU_REG_CLKGR0, 12 }, 412*7a01c190SPaul Cercueil }, 413*7a01c190SPaul Cercueil 414*7a01c190SPaul Cercueil /* Custom clocks */ 415*7a01c190SPaul Cercueil 416*7a01c190SPaul Cercueil [JZ4770_CLK_UHC_PHY] = { 417*7a01c190SPaul Cercueil "uhc_phy", CGU_CLK_CUSTOM, 418*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_UHC, -1, -1, -1 }, 419*7a01c190SPaul Cercueil .custom = { &jz4770_uhc_phy_ops }, 420*7a01c190SPaul Cercueil }, 421*7a01c190SPaul Cercueil [JZ4770_CLK_OTG_PHY] = { 422*7a01c190SPaul Cercueil "usb_phy", CGU_CLK_CUSTOM, 423*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_OTG, -1, -1, -1 }, 424*7a01c190SPaul Cercueil .custom = { &jz4770_otg_phy_ops }, 425*7a01c190SPaul Cercueil }, 426*7a01c190SPaul Cercueil 427*7a01c190SPaul Cercueil [JZ4770_CLK_EXT512] = { 428*7a01c190SPaul Cercueil "ext/512", CGU_CLK_FIXDIV, 429*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT }, 430*7a01c190SPaul Cercueil .fixdiv = { 512 }, 431*7a01c190SPaul Cercueil }, 432*7a01c190SPaul Cercueil 433*7a01c190SPaul Cercueil [JZ4770_CLK_RTC] = { 434*7a01c190SPaul Cercueil "rtc", CGU_CLK_MUX, 435*7a01c190SPaul Cercueil .parents = { JZ4770_CLK_EXT512, JZ4770_CLK_OSC32K, }, 436*7a01c190SPaul Cercueil .mux = { CGU_REG_OPCR, 2, 1}, 437*7a01c190SPaul Cercueil }, 438*7a01c190SPaul Cercueil }; 439*7a01c190SPaul Cercueil 440*7a01c190SPaul Cercueil #if IS_ENABLED(CONFIG_PM_SLEEP) 441*7a01c190SPaul Cercueil static int jz4770_cgu_pm_suspend(void) 442*7a01c190SPaul Cercueil { 443*7a01c190SPaul Cercueil u32 val; 444*7a01c190SPaul Cercueil 445*7a01c190SPaul Cercueil val = readl(cgu->base + CGU_REG_LCR); 446*7a01c190SPaul Cercueil writel(val | LCR_LPM, cgu->base + CGU_REG_LCR); 447*7a01c190SPaul Cercueil return 0; 448*7a01c190SPaul Cercueil } 449*7a01c190SPaul Cercueil 450*7a01c190SPaul Cercueil static void jz4770_cgu_pm_resume(void) 451*7a01c190SPaul Cercueil { 452*7a01c190SPaul Cercueil u32 val; 453*7a01c190SPaul Cercueil 454*7a01c190SPaul Cercueil val = readl(cgu->base + CGU_REG_LCR); 455*7a01c190SPaul Cercueil writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR); 456*7a01c190SPaul Cercueil } 457*7a01c190SPaul Cercueil 458*7a01c190SPaul Cercueil static struct syscore_ops jz4770_cgu_pm_ops = { 459*7a01c190SPaul Cercueil .suspend = jz4770_cgu_pm_suspend, 460*7a01c190SPaul Cercueil .resume = jz4770_cgu_pm_resume, 461*7a01c190SPaul Cercueil }; 462*7a01c190SPaul Cercueil #endif /* CONFIG_PM_SLEEP */ 463*7a01c190SPaul Cercueil 464*7a01c190SPaul Cercueil static void __init jz4770_cgu_init(struct device_node *np) 465*7a01c190SPaul Cercueil { 466*7a01c190SPaul Cercueil int retval; 467*7a01c190SPaul Cercueil 468*7a01c190SPaul Cercueil cgu = ingenic_cgu_new(jz4770_cgu_clocks, 469*7a01c190SPaul Cercueil ARRAY_SIZE(jz4770_cgu_clocks), np); 470*7a01c190SPaul Cercueil if (!cgu) 471*7a01c190SPaul Cercueil pr_err("%s: failed to initialise CGU\n", __func__); 472*7a01c190SPaul Cercueil 473*7a01c190SPaul Cercueil retval = ingenic_cgu_register_clocks(cgu); 474*7a01c190SPaul Cercueil if (retval) 475*7a01c190SPaul Cercueil pr_err("%s: failed to register CGU Clocks\n", __func__); 476*7a01c190SPaul Cercueil 477*7a01c190SPaul Cercueil #if IS_ENABLED(CONFIG_PM_SLEEP) 478*7a01c190SPaul Cercueil register_syscore_ops(&jz4770_cgu_pm_ops); 479*7a01c190SPaul Cercueil #endif 480*7a01c190SPaul Cercueil } 481*7a01c190SPaul Cercueil 482*7a01c190SPaul Cercueil /* We only probe via devicetree, no need for a platform driver */ 483*7a01c190SPaul Cercueil CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init); 484