13a580e9eSGhennadi Procopciuc /* 23a580e9eSGhennadi Procopciuc * Copyright 2024 NXP 33a580e9eSGhennadi Procopciuc * 43a580e9eSGhennadi Procopciuc * SPDX-License-Identifier: BSD-3-Clause 53a580e9eSGhennadi Procopciuc */ 63a580e9eSGhennadi Procopciuc #include <errno.h> 73a580e9eSGhennadi Procopciuc 88ab34357SGhennadi Procopciuc #include <s32cc-clk-regs.h> 98ab34357SGhennadi Procopciuc 10d9373519SGhennadi Procopciuc #include <common/debug.h> 113a580e9eSGhennadi Procopciuc #include <drivers/clk.h> 128ab34357SGhennadi Procopciuc #include <lib/mmio.h> 13*b5101c45SGhennadi Procopciuc #include <s32cc-clk-ids.h> 14d9373519SGhennadi Procopciuc #include <s32cc-clk-modules.h> 15d9373519SGhennadi Procopciuc #include <s32cc-clk-utils.h> 16d9373519SGhennadi Procopciuc 17d9373519SGhennadi Procopciuc #define MAX_STACK_DEPTH (15U) 18d9373519SGhennadi Procopciuc 19*b5101c45SGhennadi Procopciuc /* This is used for floating-point precision calculations. */ 20*b5101c45SGhennadi Procopciuc #define FP_PRECISION (100000000UL) 21*b5101c45SGhennadi Procopciuc 228ab34357SGhennadi Procopciuc struct s32cc_clk_drv { 238ab34357SGhennadi Procopciuc uintptr_t fxosc_base; 24*b5101c45SGhennadi Procopciuc uintptr_t armpll_base; 258ab34357SGhennadi Procopciuc }; 268ab34357SGhennadi Procopciuc 27d9373519SGhennadi Procopciuc static int update_stack_depth(unsigned int *depth) 28d9373519SGhennadi Procopciuc { 29d9373519SGhennadi Procopciuc if (*depth == 0U) { 30d9373519SGhennadi Procopciuc return -ENOMEM; 31d9373519SGhennadi Procopciuc } 32d9373519SGhennadi Procopciuc 33d9373519SGhennadi Procopciuc (*depth)--; 34d9373519SGhennadi Procopciuc return 0; 35d9373519SGhennadi Procopciuc } 363a580e9eSGhennadi Procopciuc 378ab34357SGhennadi Procopciuc static struct s32cc_clk_drv *get_drv(void) 388ab34357SGhennadi Procopciuc { 398ab34357SGhennadi Procopciuc static struct s32cc_clk_drv driver = { 408ab34357SGhennadi Procopciuc .fxosc_base = FXOSC_BASE_ADDR, 41*b5101c45SGhennadi Procopciuc .armpll_base = ARMPLL_BASE_ADDR, 428ab34357SGhennadi Procopciuc }; 438ab34357SGhennadi Procopciuc 448ab34357SGhennadi Procopciuc return &driver; 458ab34357SGhennadi Procopciuc } 468ab34357SGhennadi Procopciuc 478ab34357SGhennadi Procopciuc static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth); 488ab34357SGhennadi Procopciuc 498ab34357SGhennadi Procopciuc static int enable_clk_module(const struct s32cc_clk_obj *module, 508ab34357SGhennadi Procopciuc const struct s32cc_clk_drv *drv, 518ab34357SGhennadi Procopciuc unsigned int *depth) 528ab34357SGhennadi Procopciuc { 538ab34357SGhennadi Procopciuc const struct s32cc_clk *clk = s32cc_obj2clk(module); 548ab34357SGhennadi Procopciuc int ret; 558ab34357SGhennadi Procopciuc 568ab34357SGhennadi Procopciuc ret = update_stack_depth(depth); 578ab34357SGhennadi Procopciuc if (ret != 0) { 588ab34357SGhennadi Procopciuc return ret; 598ab34357SGhennadi Procopciuc } 608ab34357SGhennadi Procopciuc 618ab34357SGhennadi Procopciuc if (clk == NULL) { 628ab34357SGhennadi Procopciuc return -EINVAL; 638ab34357SGhennadi Procopciuc } 648ab34357SGhennadi Procopciuc 658ab34357SGhennadi Procopciuc if (clk->module != NULL) { 668ab34357SGhennadi Procopciuc return enable_module(clk->module, depth); 678ab34357SGhennadi Procopciuc } 688ab34357SGhennadi Procopciuc 698ab34357SGhennadi Procopciuc if (clk->pclock != NULL) { 708ab34357SGhennadi Procopciuc return enable_clk_module(&clk->pclock->desc, drv, depth); 718ab34357SGhennadi Procopciuc } 728ab34357SGhennadi Procopciuc 738ab34357SGhennadi Procopciuc return -EINVAL; 748ab34357SGhennadi Procopciuc } 758ab34357SGhennadi Procopciuc 76*b5101c45SGhennadi Procopciuc static int get_base_addr(enum s32cc_clk_source id, const struct s32cc_clk_drv *drv, 77*b5101c45SGhennadi Procopciuc uintptr_t *base) 78*b5101c45SGhennadi Procopciuc { 79*b5101c45SGhennadi Procopciuc int ret = 0; 80*b5101c45SGhennadi Procopciuc 81*b5101c45SGhennadi Procopciuc switch (id) { 82*b5101c45SGhennadi Procopciuc case S32CC_FXOSC: 83*b5101c45SGhennadi Procopciuc *base = drv->fxosc_base; 84*b5101c45SGhennadi Procopciuc break; 85*b5101c45SGhennadi Procopciuc case S32CC_ARM_PLL: 86*b5101c45SGhennadi Procopciuc *base = drv->armpll_base; 87*b5101c45SGhennadi Procopciuc break; 88*b5101c45SGhennadi Procopciuc case S32CC_CGM1: 89*b5101c45SGhennadi Procopciuc ret = -ENOTSUP; 90*b5101c45SGhennadi Procopciuc break; 91*b5101c45SGhennadi Procopciuc case S32CC_FIRC: 92*b5101c45SGhennadi Procopciuc break; 93*b5101c45SGhennadi Procopciuc case S32CC_SIRC: 94*b5101c45SGhennadi Procopciuc break; 95*b5101c45SGhennadi Procopciuc default: 96*b5101c45SGhennadi Procopciuc ret = -EINVAL; 97*b5101c45SGhennadi Procopciuc break; 98*b5101c45SGhennadi Procopciuc } 99*b5101c45SGhennadi Procopciuc 100*b5101c45SGhennadi Procopciuc if (ret != 0) { 101*b5101c45SGhennadi Procopciuc ERROR("Unknown clock source id: %u\n", id); 102*b5101c45SGhennadi Procopciuc } 103*b5101c45SGhennadi Procopciuc 104*b5101c45SGhennadi Procopciuc return ret; 105*b5101c45SGhennadi Procopciuc } 106*b5101c45SGhennadi Procopciuc 1078ab34357SGhennadi Procopciuc static void enable_fxosc(const struct s32cc_clk_drv *drv) 1088ab34357SGhennadi Procopciuc { 1098ab34357SGhennadi Procopciuc uintptr_t fxosc_base = drv->fxosc_base; 1108ab34357SGhennadi Procopciuc uint32_t ctrl; 1118ab34357SGhennadi Procopciuc 1128ab34357SGhennadi Procopciuc ctrl = mmio_read_32(FXOSC_CTRL(fxosc_base)); 1138ab34357SGhennadi Procopciuc if ((ctrl & FXOSC_CTRL_OSCON) != U(0)) { 1148ab34357SGhennadi Procopciuc return; 1158ab34357SGhennadi Procopciuc } 1168ab34357SGhennadi Procopciuc 1178ab34357SGhennadi Procopciuc ctrl = FXOSC_CTRL_COMP_EN; 1188ab34357SGhennadi Procopciuc ctrl &= ~FXOSC_CTRL_OSC_BYP; 1198ab34357SGhennadi Procopciuc ctrl |= FXOSC_CTRL_EOCV(0x1); 1208ab34357SGhennadi Procopciuc ctrl |= FXOSC_CTRL_GM_SEL(0x7); 1218ab34357SGhennadi Procopciuc mmio_write_32(FXOSC_CTRL(fxosc_base), ctrl); 1228ab34357SGhennadi Procopciuc 1238ab34357SGhennadi Procopciuc /* Switch ON the crystal oscillator. */ 1248ab34357SGhennadi Procopciuc mmio_setbits_32(FXOSC_CTRL(fxosc_base), FXOSC_CTRL_OSCON); 1258ab34357SGhennadi Procopciuc 1268ab34357SGhennadi Procopciuc /* Wait until the clock is stable. */ 1278ab34357SGhennadi Procopciuc while ((mmio_read_32(FXOSC_STAT(fxosc_base)) & FXOSC_STAT_OSC_STAT) == U(0)) { 1288ab34357SGhennadi Procopciuc } 1298ab34357SGhennadi Procopciuc } 1308ab34357SGhennadi Procopciuc 1318ab34357SGhennadi Procopciuc static int enable_osc(const struct s32cc_clk_obj *module, 1328ab34357SGhennadi Procopciuc const struct s32cc_clk_drv *drv, 1338ab34357SGhennadi Procopciuc unsigned int *depth) 1348ab34357SGhennadi Procopciuc { 1358ab34357SGhennadi Procopciuc const struct s32cc_osc *osc = s32cc_obj2osc(module); 1368ab34357SGhennadi Procopciuc int ret = 0; 1378ab34357SGhennadi Procopciuc 1388ab34357SGhennadi Procopciuc ret = update_stack_depth(depth); 1398ab34357SGhennadi Procopciuc if (ret != 0) { 1408ab34357SGhennadi Procopciuc return ret; 1418ab34357SGhennadi Procopciuc } 1428ab34357SGhennadi Procopciuc 1438ab34357SGhennadi Procopciuc switch (osc->source) { 1448ab34357SGhennadi Procopciuc case S32CC_FXOSC: 1458ab34357SGhennadi Procopciuc enable_fxosc(drv); 1468ab34357SGhennadi Procopciuc break; 1478ab34357SGhennadi Procopciuc /* FIRC and SIRC oscillators are enabled by default */ 1488ab34357SGhennadi Procopciuc case S32CC_FIRC: 1498ab34357SGhennadi Procopciuc break; 1508ab34357SGhennadi Procopciuc case S32CC_SIRC: 1518ab34357SGhennadi Procopciuc break; 1528ab34357SGhennadi Procopciuc default: 1538ab34357SGhennadi Procopciuc ERROR("Invalid oscillator %d\n", osc->source); 1548ab34357SGhennadi Procopciuc ret = -EINVAL; 1558ab34357SGhennadi Procopciuc break; 1568ab34357SGhennadi Procopciuc }; 1578ab34357SGhennadi Procopciuc 1588ab34357SGhennadi Procopciuc return ret; 1598ab34357SGhennadi Procopciuc } 1608ab34357SGhennadi Procopciuc 161*b5101c45SGhennadi Procopciuc static int get_pll_mfi_mfn(unsigned long pll_vco, unsigned long ref_freq, 162*b5101c45SGhennadi Procopciuc uint32_t *mfi, uint32_t *mfn) 163*b5101c45SGhennadi Procopciuc 164*b5101c45SGhennadi Procopciuc { 165*b5101c45SGhennadi Procopciuc unsigned long vco; 166*b5101c45SGhennadi Procopciuc unsigned long mfn64; 167*b5101c45SGhennadi Procopciuc 168*b5101c45SGhennadi Procopciuc /* FRAC-N mode */ 169*b5101c45SGhennadi Procopciuc *mfi = (uint32_t)(pll_vco / ref_freq); 170*b5101c45SGhennadi Procopciuc 171*b5101c45SGhennadi Procopciuc /* MFN formula : (double)(pll_vco % ref_freq) / ref_freq * 18432.0 */ 172*b5101c45SGhennadi Procopciuc mfn64 = pll_vco % ref_freq; 173*b5101c45SGhennadi Procopciuc mfn64 *= FP_PRECISION; 174*b5101c45SGhennadi Procopciuc mfn64 /= ref_freq; 175*b5101c45SGhennadi Procopciuc mfn64 *= 18432UL; 176*b5101c45SGhennadi Procopciuc mfn64 /= FP_PRECISION; 177*b5101c45SGhennadi Procopciuc 178*b5101c45SGhennadi Procopciuc if (mfn64 > UINT32_MAX) { 179*b5101c45SGhennadi Procopciuc return -EINVAL; 180*b5101c45SGhennadi Procopciuc } 181*b5101c45SGhennadi Procopciuc 182*b5101c45SGhennadi Procopciuc *mfn = (uint32_t)mfn64; 183*b5101c45SGhennadi Procopciuc 184*b5101c45SGhennadi Procopciuc vco = ((unsigned long)*mfn * FP_PRECISION) / 18432UL; 185*b5101c45SGhennadi Procopciuc vco += (unsigned long)*mfi * FP_PRECISION; 186*b5101c45SGhennadi Procopciuc vco *= ref_freq; 187*b5101c45SGhennadi Procopciuc vco /= FP_PRECISION; 188*b5101c45SGhennadi Procopciuc 189*b5101c45SGhennadi Procopciuc if (vco != pll_vco) { 190*b5101c45SGhennadi Procopciuc ERROR("Failed to find MFI and MFN settings for PLL freq %lu. Nearest freq = %lu\n", 191*b5101c45SGhennadi Procopciuc pll_vco, vco); 192*b5101c45SGhennadi Procopciuc return -EINVAL; 193*b5101c45SGhennadi Procopciuc } 194*b5101c45SGhennadi Procopciuc 195*b5101c45SGhennadi Procopciuc return 0; 196*b5101c45SGhennadi Procopciuc } 197*b5101c45SGhennadi Procopciuc 198*b5101c45SGhennadi Procopciuc static struct s32cc_clkmux *get_pll_mux(const struct s32cc_pll *pll) 199*b5101c45SGhennadi Procopciuc { 200*b5101c45SGhennadi Procopciuc const struct s32cc_clk_obj *source = pll->source; 201*b5101c45SGhennadi Procopciuc const struct s32cc_clk *clk; 202*b5101c45SGhennadi Procopciuc 203*b5101c45SGhennadi Procopciuc if (source == NULL) { 204*b5101c45SGhennadi Procopciuc ERROR("Failed to identify PLL's parent\n"); 205*b5101c45SGhennadi Procopciuc return NULL; 206*b5101c45SGhennadi Procopciuc } 207*b5101c45SGhennadi Procopciuc 208*b5101c45SGhennadi Procopciuc if (source->type != s32cc_clk_t) { 209*b5101c45SGhennadi Procopciuc ERROR("The parent of the PLL isn't a clock\n"); 210*b5101c45SGhennadi Procopciuc return NULL; 211*b5101c45SGhennadi Procopciuc } 212*b5101c45SGhennadi Procopciuc 213*b5101c45SGhennadi Procopciuc clk = s32cc_obj2clk(source); 214*b5101c45SGhennadi Procopciuc 215*b5101c45SGhennadi Procopciuc if (clk->module == NULL) { 216*b5101c45SGhennadi Procopciuc ERROR("The clock isn't connected to a module\n"); 217*b5101c45SGhennadi Procopciuc return NULL; 218*b5101c45SGhennadi Procopciuc } 219*b5101c45SGhennadi Procopciuc 220*b5101c45SGhennadi Procopciuc source = clk->module; 221*b5101c45SGhennadi Procopciuc 222*b5101c45SGhennadi Procopciuc if ((source->type != s32cc_clkmux_t) && 223*b5101c45SGhennadi Procopciuc (source->type != s32cc_shared_clkmux_t)) { 224*b5101c45SGhennadi Procopciuc ERROR("The parent of the PLL isn't a MUX\n"); 225*b5101c45SGhennadi Procopciuc return NULL; 226*b5101c45SGhennadi Procopciuc } 227*b5101c45SGhennadi Procopciuc 228*b5101c45SGhennadi Procopciuc return s32cc_obj2clkmux(source); 229*b5101c45SGhennadi Procopciuc } 230*b5101c45SGhennadi Procopciuc 231*b5101c45SGhennadi Procopciuc static void disable_odiv(uintptr_t pll_addr, uint32_t div_index) 232*b5101c45SGhennadi Procopciuc { 233*b5101c45SGhennadi Procopciuc mmio_clrbits_32(PLLDIG_PLLODIV(pll_addr, div_index), PLLDIG_PLLODIV_DE); 234*b5101c45SGhennadi Procopciuc } 235*b5101c45SGhennadi Procopciuc 236*b5101c45SGhennadi Procopciuc static void disable_odivs(uintptr_t pll_addr, uint32_t ndivs) 237*b5101c45SGhennadi Procopciuc { 238*b5101c45SGhennadi Procopciuc uint32_t i; 239*b5101c45SGhennadi Procopciuc 240*b5101c45SGhennadi Procopciuc for (i = 0; i < ndivs; i++) { 241*b5101c45SGhennadi Procopciuc disable_odiv(pll_addr, i); 242*b5101c45SGhennadi Procopciuc } 243*b5101c45SGhennadi Procopciuc } 244*b5101c45SGhennadi Procopciuc 245*b5101c45SGhennadi Procopciuc static void enable_pll_hw(uintptr_t pll_addr) 246*b5101c45SGhennadi Procopciuc { 247*b5101c45SGhennadi Procopciuc /* Enable the PLL. */ 248*b5101c45SGhennadi Procopciuc mmio_write_32(PLLDIG_PLLCR(pll_addr), 0x0); 249*b5101c45SGhennadi Procopciuc 250*b5101c45SGhennadi Procopciuc /* Poll until PLL acquires lock. */ 251*b5101c45SGhennadi Procopciuc while ((mmio_read_32(PLLDIG_PLLSR(pll_addr)) & PLLDIG_PLLSR_LOCK) == 0U) { 252*b5101c45SGhennadi Procopciuc } 253*b5101c45SGhennadi Procopciuc } 254*b5101c45SGhennadi Procopciuc 255*b5101c45SGhennadi Procopciuc static void disable_pll_hw(uintptr_t pll_addr) 256*b5101c45SGhennadi Procopciuc { 257*b5101c45SGhennadi Procopciuc mmio_write_32(PLLDIG_PLLCR(pll_addr), PLLDIG_PLLCR_PLLPD); 258*b5101c45SGhennadi Procopciuc } 259*b5101c45SGhennadi Procopciuc 260*b5101c45SGhennadi Procopciuc static int program_pll(const struct s32cc_pll *pll, uintptr_t pll_addr, 261*b5101c45SGhennadi Procopciuc const struct s32cc_clk_drv *drv, uint32_t sclk_id, 262*b5101c45SGhennadi Procopciuc unsigned long sclk_freq) 263*b5101c45SGhennadi Procopciuc { 264*b5101c45SGhennadi Procopciuc uint32_t rdiv = 1, mfi, mfn; 265*b5101c45SGhennadi Procopciuc int ret; 266*b5101c45SGhennadi Procopciuc 267*b5101c45SGhennadi Procopciuc ret = get_pll_mfi_mfn(pll->vco_freq, sclk_freq, &mfi, &mfn); 268*b5101c45SGhennadi Procopciuc if (ret != 0) { 269*b5101c45SGhennadi Procopciuc return -EINVAL; 270*b5101c45SGhennadi Procopciuc } 271*b5101c45SGhennadi Procopciuc 272*b5101c45SGhennadi Procopciuc /* Disable ODIVs*/ 273*b5101c45SGhennadi Procopciuc disable_odivs(pll_addr, pll->ndividers); 274*b5101c45SGhennadi Procopciuc 275*b5101c45SGhennadi Procopciuc /* Disable PLL */ 276*b5101c45SGhennadi Procopciuc disable_pll_hw(pll_addr); 277*b5101c45SGhennadi Procopciuc 278*b5101c45SGhennadi Procopciuc /* Program PLLCLKMUX */ 279*b5101c45SGhennadi Procopciuc mmio_write_32(PLLDIG_PLLCLKMUX(pll_addr), sclk_id); 280*b5101c45SGhennadi Procopciuc 281*b5101c45SGhennadi Procopciuc /* Program VCO */ 282*b5101c45SGhennadi Procopciuc mmio_clrsetbits_32(PLLDIG_PLLDV(pll_addr), 283*b5101c45SGhennadi Procopciuc PLLDIG_PLLDV_RDIV_MASK | PLLDIG_PLLDV_MFI_MASK, 284*b5101c45SGhennadi Procopciuc PLLDIG_PLLDV_RDIV_SET(rdiv) | PLLDIG_PLLDV_MFI(mfi)); 285*b5101c45SGhennadi Procopciuc 286*b5101c45SGhennadi Procopciuc mmio_write_32(PLLDIG_PLLFD(pll_addr), 287*b5101c45SGhennadi Procopciuc PLLDIG_PLLFD_MFN_SET(mfn) | PLLDIG_PLLFD_SMDEN); 288*b5101c45SGhennadi Procopciuc 289*b5101c45SGhennadi Procopciuc enable_pll_hw(pll_addr); 290*b5101c45SGhennadi Procopciuc 291*b5101c45SGhennadi Procopciuc return ret; 292*b5101c45SGhennadi Procopciuc } 293*b5101c45SGhennadi Procopciuc 294*b5101c45SGhennadi Procopciuc static int enable_pll(const struct s32cc_clk_obj *module, 295*b5101c45SGhennadi Procopciuc const struct s32cc_clk_drv *drv, 296*b5101c45SGhennadi Procopciuc unsigned int *depth) 297*b5101c45SGhennadi Procopciuc { 298*b5101c45SGhennadi Procopciuc const struct s32cc_pll *pll = s32cc_obj2pll(module); 299*b5101c45SGhennadi Procopciuc const struct s32cc_clkmux *mux; 300*b5101c45SGhennadi Procopciuc uintptr_t pll_addr = UL(0x0); 301*b5101c45SGhennadi Procopciuc unsigned long sclk_freq; 302*b5101c45SGhennadi Procopciuc uint32_t sclk_id; 303*b5101c45SGhennadi Procopciuc int ret; 304*b5101c45SGhennadi Procopciuc 305*b5101c45SGhennadi Procopciuc ret = update_stack_depth(depth); 306*b5101c45SGhennadi Procopciuc if (ret != 0) { 307*b5101c45SGhennadi Procopciuc return ret; 308*b5101c45SGhennadi Procopciuc } 309*b5101c45SGhennadi Procopciuc 310*b5101c45SGhennadi Procopciuc mux = get_pll_mux(pll); 311*b5101c45SGhennadi Procopciuc if (mux == NULL) { 312*b5101c45SGhennadi Procopciuc return -EINVAL; 313*b5101c45SGhennadi Procopciuc } 314*b5101c45SGhennadi Procopciuc 315*b5101c45SGhennadi Procopciuc if (pll->instance != mux->module) { 316*b5101c45SGhennadi Procopciuc ERROR("MUX type is not in sync with PLL ID\n"); 317*b5101c45SGhennadi Procopciuc return -EINVAL; 318*b5101c45SGhennadi Procopciuc } 319*b5101c45SGhennadi Procopciuc 320*b5101c45SGhennadi Procopciuc ret = get_base_addr(pll->instance, drv, &pll_addr); 321*b5101c45SGhennadi Procopciuc if (ret != 0) { 322*b5101c45SGhennadi Procopciuc ERROR("Failed to detect PLL instance\n"); 323*b5101c45SGhennadi Procopciuc return ret; 324*b5101c45SGhennadi Procopciuc } 325*b5101c45SGhennadi Procopciuc 326*b5101c45SGhennadi Procopciuc switch (mux->source_id) { 327*b5101c45SGhennadi Procopciuc case S32CC_CLK_FIRC: 328*b5101c45SGhennadi Procopciuc sclk_freq = 48U * MHZ; 329*b5101c45SGhennadi Procopciuc sclk_id = 0; 330*b5101c45SGhennadi Procopciuc break; 331*b5101c45SGhennadi Procopciuc case S32CC_CLK_FXOSC: 332*b5101c45SGhennadi Procopciuc sclk_freq = 40U * MHZ; 333*b5101c45SGhennadi Procopciuc sclk_id = 1; 334*b5101c45SGhennadi Procopciuc break; 335*b5101c45SGhennadi Procopciuc default: 336*b5101c45SGhennadi Procopciuc ERROR("Invalid source selection for PLL 0x%lx\n", 337*b5101c45SGhennadi Procopciuc pll_addr); 338*b5101c45SGhennadi Procopciuc return -EINVAL; 339*b5101c45SGhennadi Procopciuc }; 340*b5101c45SGhennadi Procopciuc 341*b5101c45SGhennadi Procopciuc return program_pll(pll, pll_addr, drv, sclk_id, sclk_freq); 342*b5101c45SGhennadi Procopciuc } 343*b5101c45SGhennadi Procopciuc 3448ab34357SGhennadi Procopciuc static int enable_module(const struct s32cc_clk_obj *module, unsigned int *depth) 3458ab34357SGhennadi Procopciuc { 3468ab34357SGhennadi Procopciuc const struct s32cc_clk_drv *drv = get_drv(); 3478ab34357SGhennadi Procopciuc int ret = 0; 3488ab34357SGhennadi Procopciuc 3498ab34357SGhennadi Procopciuc ret = update_stack_depth(depth); 3508ab34357SGhennadi Procopciuc if (ret != 0) { 3518ab34357SGhennadi Procopciuc return ret; 3528ab34357SGhennadi Procopciuc } 3538ab34357SGhennadi Procopciuc 3548ab34357SGhennadi Procopciuc if (drv == NULL) { 3558ab34357SGhennadi Procopciuc return -EINVAL; 3568ab34357SGhennadi Procopciuc } 3578ab34357SGhennadi Procopciuc 3588ab34357SGhennadi Procopciuc switch (module->type) { 3598ab34357SGhennadi Procopciuc case s32cc_osc_t: 3608ab34357SGhennadi Procopciuc ret = enable_osc(module, drv, depth); 3618ab34357SGhennadi Procopciuc break; 3628ab34357SGhennadi Procopciuc case s32cc_clk_t: 3638ab34357SGhennadi Procopciuc ret = enable_clk_module(module, drv, depth); 3648ab34357SGhennadi Procopciuc break; 365*b5101c45SGhennadi Procopciuc case s32cc_pll_t: 366*b5101c45SGhennadi Procopciuc ret = enable_pll(module, drv, depth); 367*b5101c45SGhennadi Procopciuc break; 368a8be748aSGhennadi Procopciuc case s32cc_clkmux_t: 369a8be748aSGhennadi Procopciuc ret = -ENOTSUP; 370a8be748aSGhennadi Procopciuc break; 3713fa91a94SGhennadi Procopciuc case s32cc_shared_clkmux_t: 3723fa91a94SGhennadi Procopciuc ret = -ENOTSUP; 3733fa91a94SGhennadi Procopciuc break; 374*b5101c45SGhennadi Procopciuc case s32cc_pll_out_div_t: 375a8be748aSGhennadi Procopciuc ret = -ENOTSUP; 376a8be748aSGhennadi Procopciuc break; 37744e2130aSGhennadi Procopciuc case s32cc_fixed_div_t: 378a8be748aSGhennadi Procopciuc ret = -ENOTSUP; 379a8be748aSGhennadi Procopciuc break; 3808ab34357SGhennadi Procopciuc default: 3818ab34357SGhennadi Procopciuc ret = -EINVAL; 3828ab34357SGhennadi Procopciuc break; 3838ab34357SGhennadi Procopciuc } 3848ab34357SGhennadi Procopciuc 3858ab34357SGhennadi Procopciuc return ret; 3868ab34357SGhennadi Procopciuc } 3878ab34357SGhennadi Procopciuc 3883a580e9eSGhennadi Procopciuc static int s32cc_clk_enable(unsigned long id) 3893a580e9eSGhennadi Procopciuc { 3908ab34357SGhennadi Procopciuc unsigned int depth = MAX_STACK_DEPTH; 3918ab34357SGhennadi Procopciuc const struct s32cc_clk *clk; 3928ab34357SGhennadi Procopciuc 3938ab34357SGhennadi Procopciuc clk = s32cc_get_arch_clk(id); 3948ab34357SGhennadi Procopciuc if (clk == NULL) { 3958ab34357SGhennadi Procopciuc return -EINVAL; 3968ab34357SGhennadi Procopciuc } 3978ab34357SGhennadi Procopciuc 3988ab34357SGhennadi Procopciuc return enable_module(&clk->desc, &depth); 3993a580e9eSGhennadi Procopciuc } 4003a580e9eSGhennadi Procopciuc 4013a580e9eSGhennadi Procopciuc static void s32cc_clk_disable(unsigned long id) 4023a580e9eSGhennadi Procopciuc { 4033a580e9eSGhennadi Procopciuc } 4043a580e9eSGhennadi Procopciuc 4053a580e9eSGhennadi Procopciuc static bool s32cc_clk_is_enabled(unsigned long id) 4063a580e9eSGhennadi Procopciuc { 4073a580e9eSGhennadi Procopciuc return false; 4083a580e9eSGhennadi Procopciuc } 4093a580e9eSGhennadi Procopciuc 4103a580e9eSGhennadi Procopciuc static unsigned long s32cc_clk_get_rate(unsigned long id) 4113a580e9eSGhennadi Procopciuc { 4123a580e9eSGhennadi Procopciuc return 0; 4133a580e9eSGhennadi Procopciuc } 4143a580e9eSGhennadi Procopciuc 415d9373519SGhennadi Procopciuc static int set_module_rate(const struct s32cc_clk_obj *module, 416d9373519SGhennadi Procopciuc unsigned long rate, unsigned long *orate, 417d9373519SGhennadi Procopciuc unsigned int *depth); 418d9373519SGhennadi Procopciuc 419d9373519SGhennadi Procopciuc static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate, 420d9373519SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 421d9373519SGhennadi Procopciuc { 422d9373519SGhennadi Procopciuc struct s32cc_osc *osc = s32cc_obj2osc(module); 423d9373519SGhennadi Procopciuc int ret; 424d9373519SGhennadi Procopciuc 425d9373519SGhennadi Procopciuc ret = update_stack_depth(depth); 426d9373519SGhennadi Procopciuc if (ret != 0) { 427d9373519SGhennadi Procopciuc return ret; 428d9373519SGhennadi Procopciuc } 429d9373519SGhennadi Procopciuc 430d9373519SGhennadi Procopciuc if ((osc->freq != 0UL) && (rate != osc->freq)) { 431d9373519SGhennadi Procopciuc ERROR("Already initialized oscillator. freq = %lu\n", 432d9373519SGhennadi Procopciuc osc->freq); 433d9373519SGhennadi Procopciuc return -EINVAL; 434d9373519SGhennadi Procopciuc } 435d9373519SGhennadi Procopciuc 436d9373519SGhennadi Procopciuc osc->freq = rate; 437d9373519SGhennadi Procopciuc *orate = osc->freq; 438d9373519SGhennadi Procopciuc 439d9373519SGhennadi Procopciuc return 0; 440d9373519SGhennadi Procopciuc } 441d9373519SGhennadi Procopciuc 442d9373519SGhennadi Procopciuc static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate, 443d9373519SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 444d9373519SGhennadi Procopciuc { 445d9373519SGhennadi Procopciuc const struct s32cc_clk *clk = s32cc_obj2clk(module); 446d9373519SGhennadi Procopciuc int ret; 447d9373519SGhennadi Procopciuc 448d9373519SGhennadi Procopciuc ret = update_stack_depth(depth); 449d9373519SGhennadi Procopciuc if (ret != 0) { 450d9373519SGhennadi Procopciuc return ret; 451d9373519SGhennadi Procopciuc } 452d9373519SGhennadi Procopciuc 453d9373519SGhennadi Procopciuc if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) && 454d9373519SGhennadi Procopciuc ((rate < clk->min_freq) || (rate > clk->max_freq))) { 455d9373519SGhennadi Procopciuc ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n", 456d9373519SGhennadi Procopciuc rate, clk->min_freq, clk->max_freq); 457d9373519SGhennadi Procopciuc return -EINVAL; 458d9373519SGhennadi Procopciuc } 459d9373519SGhennadi Procopciuc 460d9373519SGhennadi Procopciuc if (clk->module != NULL) { 461d9373519SGhennadi Procopciuc return set_module_rate(clk->module, rate, orate, depth); 462d9373519SGhennadi Procopciuc } 463d9373519SGhennadi Procopciuc 464d9373519SGhennadi Procopciuc if (clk->pclock != NULL) { 465d9373519SGhennadi Procopciuc return set_clk_freq(&clk->pclock->desc, rate, orate, depth); 466d9373519SGhennadi Procopciuc } 467d9373519SGhennadi Procopciuc 468d9373519SGhennadi Procopciuc return -EINVAL; 469d9373519SGhennadi Procopciuc } 470d9373519SGhennadi Procopciuc 4717ad4e231SGhennadi Procopciuc static int set_pll_freq(const struct s32cc_clk_obj *module, unsigned long rate, 4727ad4e231SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 4737ad4e231SGhennadi Procopciuc { 4747ad4e231SGhennadi Procopciuc struct s32cc_pll *pll = s32cc_obj2pll(module); 4757ad4e231SGhennadi Procopciuc int ret; 4767ad4e231SGhennadi Procopciuc 4777ad4e231SGhennadi Procopciuc ret = update_stack_depth(depth); 4787ad4e231SGhennadi Procopciuc if (ret != 0) { 4797ad4e231SGhennadi Procopciuc return ret; 4807ad4e231SGhennadi Procopciuc } 4817ad4e231SGhennadi Procopciuc 4827ad4e231SGhennadi Procopciuc if ((pll->vco_freq != 0UL) && (pll->vco_freq != rate)) { 4837ad4e231SGhennadi Procopciuc ERROR("PLL frequency was already set\n"); 4847ad4e231SGhennadi Procopciuc return -EINVAL; 4857ad4e231SGhennadi Procopciuc } 4867ad4e231SGhennadi Procopciuc 4877ad4e231SGhennadi Procopciuc pll->vco_freq = rate; 4887ad4e231SGhennadi Procopciuc *orate = pll->vco_freq; 4897ad4e231SGhennadi Procopciuc 4907ad4e231SGhennadi Procopciuc return 0; 4917ad4e231SGhennadi Procopciuc } 4927ad4e231SGhennadi Procopciuc 493de950ef0SGhennadi Procopciuc static int set_pll_div_freq(const struct s32cc_clk_obj *module, unsigned long rate, 494de950ef0SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 495de950ef0SGhennadi Procopciuc { 496de950ef0SGhennadi Procopciuc struct s32cc_pll_out_div *pdiv = s32cc_obj2plldiv(module); 497de950ef0SGhennadi Procopciuc const struct s32cc_pll *pll; 498de950ef0SGhennadi Procopciuc unsigned long prate, dc; 499de950ef0SGhennadi Procopciuc int ret; 500de950ef0SGhennadi Procopciuc 501de950ef0SGhennadi Procopciuc ret = update_stack_depth(depth); 502de950ef0SGhennadi Procopciuc if (ret != 0) { 503de950ef0SGhennadi Procopciuc return ret; 504de950ef0SGhennadi Procopciuc } 505de950ef0SGhennadi Procopciuc 506de950ef0SGhennadi Procopciuc if (pdiv->parent == NULL) { 507de950ef0SGhennadi Procopciuc ERROR("Failed to identify PLL divider's parent\n"); 508de950ef0SGhennadi Procopciuc return -EINVAL; 509de950ef0SGhennadi Procopciuc } 510de950ef0SGhennadi Procopciuc 511de950ef0SGhennadi Procopciuc pll = s32cc_obj2pll(pdiv->parent); 512de950ef0SGhennadi Procopciuc if (pll == NULL) { 513de950ef0SGhennadi Procopciuc ERROR("The parent of the PLL DIV is invalid\n"); 514de950ef0SGhennadi Procopciuc return -EINVAL; 515de950ef0SGhennadi Procopciuc } 516de950ef0SGhennadi Procopciuc 517de950ef0SGhennadi Procopciuc prate = pll->vco_freq; 518de950ef0SGhennadi Procopciuc 519de950ef0SGhennadi Procopciuc /** 520de950ef0SGhennadi Procopciuc * The PLL is not initialized yet, so let's take a risk 521de950ef0SGhennadi Procopciuc * and accept the proposed rate. 522de950ef0SGhennadi Procopciuc */ 523de950ef0SGhennadi Procopciuc if (prate == 0UL) { 524de950ef0SGhennadi Procopciuc pdiv->freq = rate; 525de950ef0SGhennadi Procopciuc *orate = rate; 526de950ef0SGhennadi Procopciuc return 0; 527de950ef0SGhennadi Procopciuc } 528de950ef0SGhennadi Procopciuc 529de950ef0SGhennadi Procopciuc /* Decline in case the rate cannot fit PLL's requirements. */ 530de950ef0SGhennadi Procopciuc dc = prate / rate; 531de950ef0SGhennadi Procopciuc if ((prate / dc) != rate) { 532de950ef0SGhennadi Procopciuc return -EINVAL; 533de950ef0SGhennadi Procopciuc } 534de950ef0SGhennadi Procopciuc 535de950ef0SGhennadi Procopciuc pdiv->freq = rate; 536de950ef0SGhennadi Procopciuc *orate = pdiv->freq; 537de950ef0SGhennadi Procopciuc 538de950ef0SGhennadi Procopciuc return 0; 539de950ef0SGhennadi Procopciuc } 540de950ef0SGhennadi Procopciuc 54165739db2SGhennadi Procopciuc static int set_fixed_div_freq(const struct s32cc_clk_obj *module, unsigned long rate, 54265739db2SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 54365739db2SGhennadi Procopciuc { 54465739db2SGhennadi Procopciuc const struct s32cc_fixed_div *fdiv = s32cc_obj2fixeddiv(module); 54565739db2SGhennadi Procopciuc int ret; 54665739db2SGhennadi Procopciuc 54765739db2SGhennadi Procopciuc ret = update_stack_depth(depth); 54865739db2SGhennadi Procopciuc if (ret != 0) { 54965739db2SGhennadi Procopciuc return ret; 55065739db2SGhennadi Procopciuc } 55165739db2SGhennadi Procopciuc 55265739db2SGhennadi Procopciuc if (fdiv->parent == NULL) { 55365739db2SGhennadi Procopciuc ERROR("The divider doesn't have a valid parent\b"); 55465739db2SGhennadi Procopciuc return -EINVAL; 55565739db2SGhennadi Procopciuc } 55665739db2SGhennadi Procopciuc 55765739db2SGhennadi Procopciuc ret = set_module_rate(fdiv->parent, rate * fdiv->rate_div, orate, depth); 55865739db2SGhennadi Procopciuc 55965739db2SGhennadi Procopciuc /* Update the output rate based on the parent's rate */ 56065739db2SGhennadi Procopciuc *orate /= fdiv->rate_div; 56165739db2SGhennadi Procopciuc 56265739db2SGhennadi Procopciuc return ret; 56365739db2SGhennadi Procopciuc } 56465739db2SGhennadi Procopciuc 56564e0c226SGhennadi Procopciuc static int set_mux_freq(const struct s32cc_clk_obj *module, unsigned long rate, 56664e0c226SGhennadi Procopciuc unsigned long *orate, unsigned int *depth) 56764e0c226SGhennadi Procopciuc { 56864e0c226SGhennadi Procopciuc const struct s32cc_clkmux *mux = s32cc_obj2clkmux(module); 56964e0c226SGhennadi Procopciuc const struct s32cc_clk *clk = s32cc_get_arch_clk(mux->source_id); 57064e0c226SGhennadi Procopciuc int ret; 57164e0c226SGhennadi Procopciuc 57264e0c226SGhennadi Procopciuc ret = update_stack_depth(depth); 57364e0c226SGhennadi Procopciuc if (ret != 0) { 57464e0c226SGhennadi Procopciuc return ret; 57564e0c226SGhennadi Procopciuc } 57664e0c226SGhennadi Procopciuc 57764e0c226SGhennadi Procopciuc if (clk == NULL) { 57864e0c226SGhennadi Procopciuc ERROR("Mux (id:%" PRIu8 ") without a valid source (%lu)\n", 57964e0c226SGhennadi Procopciuc mux->index, mux->source_id); 58064e0c226SGhennadi Procopciuc return -EINVAL; 58164e0c226SGhennadi Procopciuc } 58264e0c226SGhennadi Procopciuc 58364e0c226SGhennadi Procopciuc return set_module_rate(&clk->desc, rate, orate, depth); 58464e0c226SGhennadi Procopciuc } 58564e0c226SGhennadi Procopciuc 586d9373519SGhennadi Procopciuc static int set_module_rate(const struct s32cc_clk_obj *module, 587d9373519SGhennadi Procopciuc unsigned long rate, unsigned long *orate, 588d9373519SGhennadi Procopciuc unsigned int *depth) 589d9373519SGhennadi Procopciuc { 590d9373519SGhennadi Procopciuc int ret = 0; 591d9373519SGhennadi Procopciuc 592d9373519SGhennadi Procopciuc ret = update_stack_depth(depth); 593d9373519SGhennadi Procopciuc if (ret != 0) { 594d9373519SGhennadi Procopciuc return ret; 595d9373519SGhennadi Procopciuc } 596d9373519SGhennadi Procopciuc 597d9373519SGhennadi Procopciuc switch (module->type) { 598d9373519SGhennadi Procopciuc case s32cc_clk_t: 599d9373519SGhennadi Procopciuc ret = set_clk_freq(module, rate, orate, depth); 600d9373519SGhennadi Procopciuc break; 601d9373519SGhennadi Procopciuc case s32cc_osc_t: 602d9373519SGhennadi Procopciuc ret = set_osc_freq(module, rate, orate, depth); 603d9373519SGhennadi Procopciuc break; 6047ad4e231SGhennadi Procopciuc case s32cc_pll_t: 6057ad4e231SGhennadi Procopciuc ret = set_pll_freq(module, rate, orate, depth); 6067ad4e231SGhennadi Procopciuc break; 607de950ef0SGhennadi Procopciuc case s32cc_pll_out_div_t: 608de950ef0SGhennadi Procopciuc ret = set_pll_div_freq(module, rate, orate, depth); 609de950ef0SGhennadi Procopciuc break; 61065739db2SGhennadi Procopciuc case s32cc_fixed_div_t: 61165739db2SGhennadi Procopciuc ret = set_fixed_div_freq(module, rate, orate, depth); 61265739db2SGhennadi Procopciuc break; 613a8be748aSGhennadi Procopciuc case s32cc_clkmux_t: 61464e0c226SGhennadi Procopciuc ret = set_mux_freq(module, rate, orate, depth); 61564e0c226SGhennadi Procopciuc break; 6163fa91a94SGhennadi Procopciuc case s32cc_shared_clkmux_t: 61764e0c226SGhennadi Procopciuc ret = set_mux_freq(module, rate, orate, depth); 618a8be748aSGhennadi Procopciuc break; 619d9373519SGhennadi Procopciuc default: 620d9373519SGhennadi Procopciuc ret = -EINVAL; 621d9373519SGhennadi Procopciuc break; 622d9373519SGhennadi Procopciuc } 623d9373519SGhennadi Procopciuc 624d9373519SGhennadi Procopciuc return ret; 625d9373519SGhennadi Procopciuc } 626d9373519SGhennadi Procopciuc 6273a580e9eSGhennadi Procopciuc static int s32cc_clk_set_rate(unsigned long id, unsigned long rate, 6283a580e9eSGhennadi Procopciuc unsigned long *orate) 6293a580e9eSGhennadi Procopciuc { 630d9373519SGhennadi Procopciuc unsigned int depth = MAX_STACK_DEPTH; 631d9373519SGhennadi Procopciuc const struct s32cc_clk *clk; 632d9373519SGhennadi Procopciuc int ret; 633d9373519SGhennadi Procopciuc 634d9373519SGhennadi Procopciuc clk = s32cc_get_arch_clk(id); 635d9373519SGhennadi Procopciuc if (clk == NULL) { 636d9373519SGhennadi Procopciuc return -EINVAL; 637d9373519SGhennadi Procopciuc } 638d9373519SGhennadi Procopciuc 639d9373519SGhennadi Procopciuc ret = set_module_rate(&clk->desc, rate, orate, &depth); 640d9373519SGhennadi Procopciuc if (ret != 0) { 641d9373519SGhennadi Procopciuc ERROR("Failed to set frequency (%lu MHz) for clock %lu\n", 642d9373519SGhennadi Procopciuc rate, id); 643d9373519SGhennadi Procopciuc } 644d9373519SGhennadi Procopciuc 645d9373519SGhennadi Procopciuc return ret; 6463a580e9eSGhennadi Procopciuc } 6473a580e9eSGhennadi Procopciuc 6483a580e9eSGhennadi Procopciuc static int s32cc_clk_get_parent(unsigned long id) 6493a580e9eSGhennadi Procopciuc { 6503a580e9eSGhennadi Procopciuc return -ENOTSUP; 6513a580e9eSGhennadi Procopciuc } 6523a580e9eSGhennadi Procopciuc 6533a580e9eSGhennadi Procopciuc static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id) 6543a580e9eSGhennadi Procopciuc { 65512e7a2cdSGhennadi Procopciuc const struct s32cc_clk *parent; 65612e7a2cdSGhennadi Procopciuc const struct s32cc_clk *clk; 65712e7a2cdSGhennadi Procopciuc bool valid_source = false; 65812e7a2cdSGhennadi Procopciuc struct s32cc_clkmux *mux; 65912e7a2cdSGhennadi Procopciuc uint8_t i; 66012e7a2cdSGhennadi Procopciuc 66112e7a2cdSGhennadi Procopciuc clk = s32cc_get_arch_clk(id); 66212e7a2cdSGhennadi Procopciuc if (clk == NULL) { 66312e7a2cdSGhennadi Procopciuc return -EINVAL; 66412e7a2cdSGhennadi Procopciuc } 66512e7a2cdSGhennadi Procopciuc 66612e7a2cdSGhennadi Procopciuc parent = s32cc_get_arch_clk(parent_id); 66712e7a2cdSGhennadi Procopciuc if (parent == NULL) { 66812e7a2cdSGhennadi Procopciuc return -EINVAL; 66912e7a2cdSGhennadi Procopciuc } 67012e7a2cdSGhennadi Procopciuc 67112e7a2cdSGhennadi Procopciuc if (!is_s32cc_clk_mux(clk)) { 67212e7a2cdSGhennadi Procopciuc ERROR("Clock %lu is not a mux\n", id); 67312e7a2cdSGhennadi Procopciuc return -EINVAL; 67412e7a2cdSGhennadi Procopciuc } 67512e7a2cdSGhennadi Procopciuc 67612e7a2cdSGhennadi Procopciuc mux = s32cc_clk2mux(clk); 67712e7a2cdSGhennadi Procopciuc if (mux == NULL) { 67812e7a2cdSGhennadi Procopciuc ERROR("Failed to cast clock %lu to clock mux\n", id); 67912e7a2cdSGhennadi Procopciuc return -EINVAL; 68012e7a2cdSGhennadi Procopciuc } 68112e7a2cdSGhennadi Procopciuc 68212e7a2cdSGhennadi Procopciuc for (i = 0; i < mux->nclks; i++) { 68312e7a2cdSGhennadi Procopciuc if (mux->clkids[i] == parent_id) { 68412e7a2cdSGhennadi Procopciuc valid_source = true; 68512e7a2cdSGhennadi Procopciuc break; 68612e7a2cdSGhennadi Procopciuc } 68712e7a2cdSGhennadi Procopciuc } 68812e7a2cdSGhennadi Procopciuc 68912e7a2cdSGhennadi Procopciuc if (!valid_source) { 69012e7a2cdSGhennadi Procopciuc ERROR("Clock %lu is not a valid clock for mux %lu\n", 69112e7a2cdSGhennadi Procopciuc parent_id, id); 69212e7a2cdSGhennadi Procopciuc return -EINVAL; 69312e7a2cdSGhennadi Procopciuc } 69412e7a2cdSGhennadi Procopciuc 69512e7a2cdSGhennadi Procopciuc mux->source_id = parent_id; 69612e7a2cdSGhennadi Procopciuc 69712e7a2cdSGhennadi Procopciuc return 0; 6983a580e9eSGhennadi Procopciuc } 6993a580e9eSGhennadi Procopciuc 7003a580e9eSGhennadi Procopciuc void s32cc_clk_register_drv(void) 7013a580e9eSGhennadi Procopciuc { 7023a580e9eSGhennadi Procopciuc static const struct clk_ops s32cc_clk_ops = { 7033a580e9eSGhennadi Procopciuc .enable = s32cc_clk_enable, 7043a580e9eSGhennadi Procopciuc .disable = s32cc_clk_disable, 7053a580e9eSGhennadi Procopciuc .is_enabled = s32cc_clk_is_enabled, 7063a580e9eSGhennadi Procopciuc .get_rate = s32cc_clk_get_rate, 7073a580e9eSGhennadi Procopciuc .set_rate = s32cc_clk_set_rate, 7083a580e9eSGhennadi Procopciuc .get_parent = s32cc_clk_get_parent, 7093a580e9eSGhennadi Procopciuc .set_parent = s32cc_clk_set_parent, 7103a580e9eSGhennadi Procopciuc }; 7113a580e9eSGhennadi Procopciuc 7123a580e9eSGhennadi Procopciuc clk_register(&s32cc_clk_ops); 7133a580e9eSGhennadi Procopciuc } 7143a580e9eSGhennadi Procopciuc 715