1168404Spjd// SPDX-License-Identifier: GPL-2.0 2168404Spjd/* 3168404Spjd * (C) Copyright 2017 Rockchip Electronics Co., Ltd 4168404Spjd * Author: Andy Yan <andy.yan@rock-chips.com> 5168404Spjd * (C) Copyright 2017 Theobroma Systems Design und Consulting GmbH 6168404Spjd */ 7168404Spjd 8168404Spjd#include <common.h> 9168404Spjd#include <clk-uclass.h> 10168404Spjd#include <dm.h> 11168404Spjd#include <dt-structs.h> 12168404Spjd#include <errno.h> 13168404Spjd#include <log.h> 14168404Spjd#include <malloc.h> 15168404Spjd#include <mapmem.h> 16168404Spjd#include <syscon.h> 17168404Spjd#include <bitfield.h> 18168404Spjd#include <asm/arch-rockchip/clock.h> 19168404Spjd#include <asm/arch-rockchip/cru_rk3368.h> 20168404Spjd#include <asm/arch-rockchip/hardware.h> 21168404Spjd#include <dm/device-internal.h> 22219089Spjd#include <dm/lists.h> 23268123Sdelphij#include <dt-bindings/clock/rk3368-cru.h> 24260835Sdelphij#include <linux/delay.h> 25268085Sdelphij#include <linux/printk.h> 26168404Spjd#include <linux/stringify.h> 27168404Spjd 28168404Spjd#if CONFIG_IS_ENABLED(OF_PLATDATA) 29168404Spjdstruct rk3368_clk_plat { 30168404Spjd struct dtd_rockchip_rk3368_cru dtd; 31168404Spjd}; 32168404Spjd#endif 33168404Spjd 34168404Spjdstruct pll_div { 35168404Spjd u32 nr; 36168404Spjd u32 nf; 37168404Spjd u32 no; 38168404Spjd}; 39168404Spjd 40168404Spjd#define OSC_HZ (24 * 1000 * 1000) 41168404Spjd#define APLL_L_HZ (800 * 1000 * 1000) 42168404Spjd#define APLL_B_HZ (816 * 1000 * 1000) 43168404Spjd#define GPLL_HZ (576 * 1000 * 1000) 44168404Spjd#define CPLL_HZ (400 * 1000 * 1000) 45168404Spjd 46168404Spjd#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) 47168404Spjd 48168404Spjd#define PLL_DIVISORS(hz, _nr, _no) { \ 49168404Spjd .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no}; \ 50185029Spjd _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\ 51185029Spjd (_nr * _no) == hz, #hz "Hz cannot be hit with PLL " \ 52168404Spjd "divisors on line " __stringify(__LINE__)); 53168404Spjd 54168404Spjd#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 55168404Spjdstatic const struct pll_div apll_l_init_cfg = PLL_DIVISORS(APLL_L_HZ, 12, 2); 56185029Spjdstatic const struct pll_div apll_b_init_cfg = PLL_DIVISORS(APLL_B_HZ, 1, 2); 57168404Spjd#if !defined(CONFIG_TPL_BUILD) 58168404Spjdstatic const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 2); 59168404Spjdstatic const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 6); 60168404Spjd#endif 61251631Sdelphij#endif 62168404Spjd 63168404Spjdstatic ulong rk3368_clk_get_rate(struct clk *clk); 64168404Spjd 65251631Sdelphij/* Get pll rate by id */ 66168404Spjdstatic uint32_t rkclk_pll_get_rate(struct rk3368_cru *cru, 67168404Spjd enum rk3368_pll_id pll_id) 68168404Spjd{ 69168404Spjd uint32_t nr, no, nf; 70168404Spjd uint32_t con; 71168404Spjd struct rk3368_pll *pll = &cru->pll[pll_id]; 72168404Spjd 73168404Spjd con = readl(&pll->con3); 74168404Spjd 75168404Spjd switch ((con & PLL_MODE_MASK) >> PLL_MODE_SHIFT) { 76168404Spjd case PLL_MODE_SLOW: 77168404Spjd return OSC_HZ; 78185029Spjd case PLL_MODE_NORMAL: 79168404Spjd con = readl(&pll->con0); 80251631Sdelphij no = ((con & PLL_OD_MASK) >> PLL_OD_SHIFT) + 1; 81168404Spjd nr = ((con & PLL_NR_MASK) >> PLL_NR_SHIFT) + 1; 82168404Spjd con = readl(&pll->con1); 83168404Spjd nf = ((con & PLL_NF_MASK) >> PLL_NF_SHIFT) + 1; 84168404Spjd 85168404Spjd return (24 * nf / (nr * no)) * 1000000; 86168404Spjd case PLL_MODE_DEEP_SLOW: 87168404Spjd default: 88168404Spjd return 32768; 89168404Spjd } 90168404Spjd} 91168404Spjd 92168404Spjd#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 93168404Spjdstatic int rkclk_set_pll(struct rk3368_cru *cru, enum rk3368_pll_id pll_id, 94168404Spjd const struct pll_div *div) 95168404Spjd{ 96168404Spjd struct rk3368_pll *pll = &cru->pll[pll_id]; 97168404Spjd /* All PLLs have same VCO and output frequency range restrictions*/ 98168404Spjd uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000; 99168404Spjd uint output_hz = vco_hz / div->no; 100168404Spjd 101168404Spjd debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n", 102168404Spjd pll, div->nf, div->nr, div->no, vco_hz, output_hz); 103168404Spjd 104168404Spjd /* enter slow mode and reset pll */ 105168404Spjd rk_clrsetreg(&pll->con3, PLL_MODE_MASK | PLL_RESET_MASK, 106168404Spjd PLL_RESET << PLL_RESET_SHIFT); 107268858Sdelphij 108168404Spjd rk_clrsetreg(&pll->con0, PLL_NR_MASK | PLL_OD_MASK, 109168404Spjd ((div->nr - 1) << PLL_NR_SHIFT) | 110168404Spjd ((div->no - 1) << PLL_OD_SHIFT)); 111168404Spjd writel((div->nf - 1) << PLL_NF_SHIFT, &pll->con1); 112185029Spjd /* 113185029Spjd * BWADJ should be set to NF / 2 to ensure the nominal bandwidth. 114185029Spjd * Compare the RK3368 TRM, section "3.6.4 PLL Bandwidth Adjustment". 115185029Spjd */ 116185029Spjd clrsetbits_le32(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1); 117185029Spjd 118185029Spjd udelay(10); 119185029Spjd 120168404Spjd /* return from reset */ 121168404Spjd rk_clrreg(&pll->con3, PLL_RESET_MASK); 122168404Spjd 123168404Spjd /* waiting for pll lock */ 124251478Sdelphij while (!(readl(&pll->con1) & PLL_LOCK_STA)) 125168404Spjd udelay(1); 126168404Spjd 127168404Spjd rk_clrsetreg(&pll->con3, PLL_MODE_MASK, 128185029Spjd PLL_MODE_NORMAL << PLL_MODE_SHIFT); 129219089Spjd 130258632Savg return 0; 131168404Spjd} 132168404Spjd#endif 133168404Spjd 134168404Spjd#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 135168404Spjdstatic void rkclk_init(struct rk3368_cru *cru) 136248572Ssmh{ 137219089Spjd u32 apllb, aplll, dpll, cpll, gpll; 138168404Spjd 139168404Spjd rkclk_set_pll(cru, APLLB, &apll_b_init_cfg); 140191902Skmacy rkclk_set_pll(cru, APLLL, &apll_l_init_cfg); 141272483Ssmh#if !defined(CONFIG_TPL_BUILD) 142191902Skmacy /* 143240133Smm * If we plan to return to the boot ROM, we can't increase the 144240133Smm * GPLL rate from the SPL stage. 145240133Smm */ 146240133Smm rkclk_set_pll(cru, GPLL, &gpll_init_cfg); 147240133Smm rkclk_set_pll(cru, CPLL, &cpll_init_cfg); 148240133Smm#endif 149240133Smm 150240133Smm apllb = rkclk_pll_get_rate(cru, APLLB); 151168404Spjd aplll = rkclk_pll_get_rate(cru, APLLL); 152168404Spjd dpll = rkclk_pll_get_rate(cru, DPLL); 153168404Spjd cpll = rkclk_pll_get_rate(cru, CPLL); 154168404Spjd gpll = rkclk_pll_get_rate(cru, GPLL); 155168404Spjd 156168404Spjd debug("%s apllb(%d) apll(%d) dpll(%d) cpll(%d) gpll(%d)\n", 157168404Spjd __func__, apllb, aplll, dpll, cpll, gpll); 158168404Spjd} 159168404Spjd#endif 160168404Spjd 161168404Spjd#if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC) 162168404Spjdstatic ulong rk3368_mmc_get_clk(struct rk3368_cru *cru, uint clk_id) 163258632Savg{ 164258632Savg u32 div, con, con_id, rate; 165258632Savg u32 pll_rate; 166258632Savg 167258632Savg switch (clk_id) { 168258632Savg case HCLK_SDMMC: 169168404Spjd con_id = 50; 170168404Spjd break; 171168404Spjd case HCLK_EMMC: 172208373Smm con_id = 51; 173208373Smm break; 174208373Smm case SCLK_SDIO0: 175208373Smm con_id = 48; 176208373Smm break; 177208373Smm default: 178168404Spjd return -EINVAL; 179168404Spjd } 180168404Spjd 181168404Spjd con = readl(&cru->clksel_con[con_id]); 182168404Spjd switch (con & MMC_PLL_SEL_MASK) { 183168404Spjd case MMC_PLL_SEL_GPLL: 184258632Savg pll_rate = rkclk_pll_get_rate(cru, GPLL); 185258632Savg break; 186258632Savg case MMC_PLL_SEL_24M: 187258632Savg pll_rate = OSC_HZ; 188258632Savg break; 189208373Smm case MMC_PLL_SEL_CPLL: 190194043Skmacy pll_rate = rkclk_pll_get_rate(cru, CPLL); 191168404Spjd break; 192168404Spjd case MMC_PLL_SEL_USBPHY_480M: 193185029Spjd default: 194185029Spjd return -EINVAL; 195185029Spjd } 196185029Spjd div = (con & MMC_CLK_DIV_MASK) >> MMC_CLK_DIV_SHIFT; 197185029Spjd rate = DIV_TO_RATE(pll_rate, div); 198185029Spjd 199185029Spjd debug("%s: raw rate %d (post-divide by 2)\n", __func__, rate); 200275780Sdelphij return rate >> 1; 201208373Smm} 202208373Smm 203208373Smmstatic ulong rk3368_mmc_find_best_rate_and_parent(struct clk *clk, 204242845Sdelphij ulong rate, 205269230Sdelphij u32 *best_mux, 206272483Ssmh u32 *best_div) 207185029Spjd{ 208270759Ssmh int i; 209275748Sdelphij ulong best_rate = 0; 210270759Ssmh const ulong MHz = 1000000; 211270759Ssmh const struct { 212270759Ssmh u32 mux; 213270759Ssmh ulong rate; 214270759Ssmh } parents[] = { 215270759Ssmh { .mux = MMC_PLL_SEL_CPLL, .rate = CPLL_HZ }, 216272483Ssmh { .mux = MMC_PLL_SEL_GPLL, .rate = GPLL_HZ }, 217270759Ssmh { .mux = MMC_PLL_SEL_24M, .rate = 24 * MHz } 218270759Ssmh }; 219270759Ssmh 220270759Ssmh debug("%s: target rate %ld\n", __func__, rate); 221185029Spjd for (i = 0; i < ARRAY_SIZE(parents); ++i) { 222275780Sdelphij /* 223273026Sdelphij * Find the largest rate no larger than the target-rate for 224168473Spjd * the current parent. 225217367Smdf */ 226168473Spjd ulong parent_rate = parents[i].rate; 227217367Smdf u32 div = DIV_ROUND_UP(parent_rate, rate); 228168473Spjd u32 adj_div = div; 229269230Sdelphij ulong new_rate = parent_rate / adj_div; 230269230Sdelphij 231269230Sdelphij debug("%s: rate %ld, parent-mux %d, parent-rate %ld, div %d\n", 232273026Sdelphij __func__, rate, parents[i].mux, parents[i].rate, div); 233273026Sdelphij 234273026Sdelphij /* Skip, if not representable */ 235273026Sdelphij if ((div - 1) > MMC_CLK_DIV_MASK) 236270759Ssmh continue; 237270759Ssmh 238270759Ssmh /* Skip, if we already have a better (or equal) solution */ 239270759Ssmh if (new_rate <= best_rate) 240270759Ssmh continue; 241270759Ssmh 242270759Ssmh /* This is our new best rate. */ 243270759Ssmh best_rate = new_rate; 244168404Spjd *best_mux = parents[i].mux; 245270759Ssmh *best_div = div - 1; 246270759Ssmh } 247270759Ssmh 248270759Ssmh debug("%s: best_mux = %x, best_div = %d, best_rate = %ld\n", 249270759Ssmh __func__, *best_mux, *best_div, best_rate); 250270759Ssmh 251270759Ssmh return best_rate; 252270759Ssmh} 253270759Ssmh 254270759Ssmhstatic ulong rk3368_mmc_set_clk(struct clk *clk, ulong rate) 255270759Ssmh{ 256272483Ssmh struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 257270759Ssmh struct rk3368_cru *cru = priv->cru; 258272483Ssmh ulong clk_id = clk->id; 259270759Ssmh u32 con_id, mux = 0, div = 0; 260270759Ssmh 261270759Ssmh /* Find the best parent and rate */ 262270759Ssmh rk3368_mmc_find_best_rate_and_parent(clk, rate << 1, &mux, &div); 263270759Ssmh 264270759Ssmh switch (clk_id) { 265275748Sdelphij case HCLK_SDMMC: 266275748Sdelphij con_id = 50; 267275748Sdelphij break; 268275748Sdelphij case HCLK_EMMC: 269275748Sdelphij con_id = 51; 270275748Sdelphij break; 271275748Sdelphij case SCLK_SDIO0: 272275748Sdelphij con_id = 48; 273275748Sdelphij break; 274272483Ssmh default: 275270759Ssmh return -EINVAL; 276168404Spjd } 277185029Spjd 278168404Spjd rk_clrsetreg(&cru->clksel_con[con_id], 279168404Spjd MMC_PLL_SEL_MASK | MMC_CLK_DIV_MASK, 280168404Spjd mux | div); 281168404Spjd 282168404Spjd return rk3368_mmc_get_clk(cru, clk_id); 283185029Spjd} 284185029Spjd#endif 285185029Spjd 286185029Spjd#if IS_ENABLED(CONFIG_TPL_BUILD) 287185029Spjdstatic ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate) 288185029Spjd{ 289185029Spjd const struct pll_div *dpll_cfg = NULL; 290185029Spjd const ulong MHz = 1000000; 291168404Spjd 292168404Spjd /* Fout = ((Fin /NR) * NF )/ NO */ 293168404Spjd static const struct pll_div dpll_1200 = PLL_DIVISORS(1200 * MHz, 1, 1); 294168404Spjd static const struct pll_div dpll_1332 = PLL_DIVISORS(1332 * MHz, 2, 1); 295168404Spjd static const struct pll_div dpll_1600 = PLL_DIVISORS(1600 * MHz, 3, 2); 296168404Spjd 297168404Spjd switch (set_rate) { 298185029Spjd case 1200*MHz: 299185029Spjd dpll_cfg = &dpll_1200; 300185029Spjd break; 301185029Spjd case 1332*MHz: 302185029Spjd dpll_cfg = &dpll_1332; 303185029Spjd break; 304185029Spjd case 1600*MHz: 305185029Spjd dpll_cfg = &dpll_1600; 306168404Spjd break; 307168404Spjd default: 308205264Skmacy pr_err("Unsupported SDRAM frequency!,%ld\n", set_rate); 309205231Skmacy } 310205231Skmacy rkclk_set_pll(cru, DPLL, dpll_cfg); 311205231Skmacy 312205231Skmacy return set_rate; 313205231Skmacy} 314205231Skmacy#endif 315205231Skmacy 316205231Skmacy#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 317205231Skmacystatic ulong rk3368_gmac_set_clk(struct rk3368_cru *cru, ulong set_rate) 318205231Skmacy{ 319205231Skmacy ulong ret; 320205231Skmacy 321205231Skmacy /* 322206796Spjd * The gmac clock can be derived either from an external clock 323205231Skmacy * or can be generated from internally by a divider from SCLK_MAC. 324168404Spjd */ 325185029Spjd if (readl(&cru->clksel_con[43]) & GMAC_MUX_SEL_EXTCLK) { 326185029Spjd /* An external clock will always generate the right rate... */ 327205231Skmacy ret = set_rate; 328205264Skmacy } else { 329168404Spjd u32 con = readl(&cru->clksel_con[43]); 330168404Spjd ulong pll_rate; 331206796Spjd u8 div; 332205231Skmacy 333185029Spjd if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) == 334168404Spjd GMAC_PLL_SELECT_GENERAL) 335168404Spjd pll_rate = GPLL_HZ; 336168404Spjd else if (((con >> GMAC_PLL_SHIFT) & GMAC_PLL_MASK) == 337168404Spjd GMAC_PLL_SELECT_CODEC) 338168404Spjd pll_rate = CPLL_HZ; 339185029Spjd else 340168404Spjd /* CPLL is not set */ 341168404Spjd return -EPERM; 342168404Spjd 343168404Spjd div = DIV_ROUND_UP(pll_rate, set_rate) - 1; 344168404Spjd if (div <= 0x1f) 345168404Spjd rk_clrsetreg(&cru->clksel_con[43], GMAC_DIV_CON_MASK, 346168404Spjd div << GMAC_DIV_CON_SHIFT); 347168404Spjd else 348168404Spjd debug("Unsupported div for gmac:%d\n", div); 349168404Spjd 350168404Spjd return DIV_TO_RATE(pll_rate, div); 351168404Spjd } 352168404Spjd 353168404Spjd return ret; 354168404Spjd} 355168404Spjd#endif 356205231Skmacy 357168404Spjd/* 358205231Skmacy * RK3368 SPI clocks have a common divider-width (7 bits) and a single bit 359168404Spjd * to select either CPLL or GPLL as the clock-parent. The location within 360251629Sdelphij * the enclosing CLKSEL_CON (i.e. div_shift and sel_shift) are variable. 361251629Sdelphij */ 362251629Sdelphij 363251629Sdelphijstruct spi_clkreg { 364251629Sdelphij uint8_t reg; /* CLKSEL_CON[reg] register in CRU */ 365251629Sdelphij uint8_t div_shift; 366168404Spjd uint8_t sel_shift; 367251629Sdelphij}; 368251629Sdelphij 369251629Sdelphij/* 370251629Sdelphij * The entries are numbered relative to their offset from SCLK_SPI0. 371251629Sdelphij */ 372168404Spjdstatic const struct spi_clkreg spi_clkregs[] = { 373208373Smm [0] = { .reg = 45, .div_shift = 0, .sel_shift = 7, }, 374208373Smm [1] = { .reg = 45, .div_shift = 8, .sel_shift = 15, }, 375208373Smm [2] = { .reg = 46, .div_shift = 8, .sel_shift = 15, }, 376168404Spjd}; 377168404Spjd 378168404Spjdstatic inline u32 extract_bits(u32 val, unsigned width, unsigned shift) 379168404Spjd{ 380168404Spjd return (val >> shift) & ((1 << width) - 1); 381168404Spjd} 382168404Spjd 383168404Spjdstatic ulong rk3368_spi_get_clk(struct rk3368_cru *cru, ulong clk_id) 384168404Spjd{ 385168404Spjd const struct spi_clkreg *spiclk = NULL; 386185029Spjd u32 div, val; 387208373Smm 388208373Smm switch (clk_id) { 389185029Spjd case SCLK_SPI0 ... SCLK_SPI2: 390185029Spjd spiclk = &spi_clkregs[clk_id - SCLK_SPI0]; 391185029Spjd break; 392185029Spjd 393208373Smm default: 394208373Smm pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id); 395185029Spjd return -EINVAL; 396185029Spjd } 397185029Spjd 398185029Spjd val = readl(&cru->clksel_con[spiclk->reg]); 399185029Spjd div = extract_bits(val, 7, spiclk->div_shift); 400185029Spjd 401185029Spjd debug("%s: div 0x%x\n", __func__, div); 402274172Savg return DIV_TO_RATE(GPLL_HZ, div); 403185029Spjd} 404185029Spjd 405185029Spjdstatic ulong rk3368_spi_set_clk(struct rk3368_cru *cru, ulong clk_id, uint hz) 406185029Spjd{ 407251478Sdelphij const struct spi_clkreg *spiclk = NULL; 408185029Spjd int src_clk_div; 409251478Sdelphij 410251478Sdelphij src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz); 411251478Sdelphij assert(src_clk_div < 127); 412205231Skmacy 413205231Skmacy switch (clk_id) { 414205231Skmacy case SCLK_SPI0 ... SCLK_SPI2: 415206796Spjd spiclk = &spi_clkregs[clk_id - SCLK_SPI0]; 416205231Skmacy break; 417205231Skmacy 418205231Skmacy default: 419205231Skmacy pr_err("%s: SPI clk-id %ld not supported\n", __func__, clk_id); 420205231Skmacy return -EINVAL; 421205231Skmacy } 422205231Skmacy 423205231Skmacy rk_clrsetreg(&cru->clksel_con[spiclk->reg], 424242845Sdelphij ((0x7f << spiclk->div_shift) | 425242845Sdelphij (0x1 << spiclk->sel_shift)), 426242845Sdelphij ((src_clk_div << spiclk->div_shift) | 427242845Sdelphij (1 << spiclk->sel_shift))); 428275748Sdelphij 429275748Sdelphij return rk3368_spi_get_clk(cru, clk_id); 430275748Sdelphij} 431275780Sdelphij 432168404Spjdstatic ulong rk3368_saradc_get_clk(struct rk3368_cru *cru) 433168404Spjd{ 434168404Spjd u32 div, val; 435168404Spjd 436168404Spjd val = readl(&cru->clksel_con[25]); 437168404Spjd div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT, 438168404Spjd CLK_SARADC_DIV_CON_WIDTH); 439168404Spjd 440168404Spjd return DIV_TO_RATE(OSC_HZ, div); 441168404Spjd} 442168404Spjd 443168404Spjdstatic ulong rk3368_saradc_set_clk(struct rk3368_cru *cru, uint hz) 444168404Spjd{ 445168404Spjd int src_clk_div; 446168404Spjd 447168404Spjd src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1; 448168404Spjd assert(src_clk_div < 128); 449205231Skmacy 450168404Spjd rk_clrsetreg(&cru->clksel_con[25], 451205231Skmacy CLK_SARADC_DIV_CON_MASK, 452168404Spjd src_clk_div << CLK_SARADC_DIV_CON_SHIFT); 453168404Spjd 454168404Spjd return rk3368_saradc_get_clk(cru); 455208373Smm} 456208373Smm 457208373Smmstatic ulong rk3368_clk_get_rate(struct clk *clk) 458168404Spjd{ 459168404Spjd struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 460168404Spjd ulong rate = 0; 461168404Spjd 462168404Spjd debug("%s: id %ld\n", __func__, clk->id); 463168404Spjd switch (clk->id) { 464168404Spjd case PLL_CPLL: 465168404Spjd rate = rkclk_pll_get_rate(priv->cru, CPLL); 466168404Spjd break; 467185029Spjd case PLL_GPLL: 468185029Spjd rate = rkclk_pll_get_rate(priv->cru, GPLL); 469208373Smm break; 470208373Smm case SCLK_SPI0 ... SCLK_SPI2: 471185029Spjd rate = rk3368_spi_get_clk(priv->cru, clk->id); 472185029Spjd break; 473185029Spjd#if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC) 474185029Spjd case HCLK_SDMMC: 475208373Smm case HCLK_EMMC: 476208373Smm rate = rk3368_mmc_get_clk(priv->cru, clk->id); 477185029Spjd break; 478185029Spjd#endif 479185029Spjd case SCLK_SARADC: 480185029Spjd rate = rk3368_saradc_get_clk(priv->cru); 481185029Spjd break; 482185029Spjd default: 483185029Spjd return -ENOENT; 484274172Savg } 485185029Spjd 486185029Spjd return rate; 487185029Spjd} 488185029Spjd 489251478Sdelphijstatic ulong rk3368_clk_set_rate(struct clk *clk, ulong rate) 490185029Spjd{ 491251478Sdelphij __maybe_unused struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 492251478Sdelphij ulong ret = 0; 493251478Sdelphij 494206796Spjd debug("%s id:%ld rate:%ld\n", __func__, clk->id, rate); 495206796Spjd switch (clk->id) { 496206796Spjd case SCLK_SPI0 ... SCLK_SPI2: 497206796Spjd ret = rk3368_spi_set_clk(priv->cru, clk->id, rate); 498206796Spjd break; 499206796Spjd#if IS_ENABLED(CONFIG_TPL_BUILD) 500206796Spjd case CLK_DDR: 501206796Spjd ret = rk3368_ddr_set_clk(priv->cru, rate); 502206796Spjd break; 503206796Spjd#endif 504206796Spjd#if !IS_ENABLED(CONFIG_SPL_BUILD) || CONFIG_IS_ENABLED(MMC) 505242845Sdelphij case HCLK_SDMMC: 506242845Sdelphij case HCLK_EMMC: 507242845Sdelphij ret = rk3368_mmc_set_clk(clk, rate); 508242845Sdelphij break; 509275748Sdelphij#endif 510275748Sdelphij#if CONFIG_IS_ENABLED(GMAC_ROCKCHIP) 511275748Sdelphij case SCLK_MAC: 512275780Sdelphij /* select the external clock */ 513275780Sdelphij ret = rk3368_gmac_set_clk(priv->cru, rate); 514168404Spjd break; 515168404Spjd#endif 516168404Spjd case SCLK_SARADC: 517168404Spjd ret = rk3368_saradc_set_clk(priv->cru, rate); 518168404Spjd break; 519251631Sdelphij default: 520168404Spjd return -ENOENT; 521206796Spjd } 522168404Spjd 523168404Spjd return ret; 524168404Spjd} 525168404Spjd 526168404Spjdstatic int __maybe_unused rk3368_gmac_set_parent(struct clk *clk, struct clk *parent) 527168404Spjd{ 528168404Spjd struct rk3368_clk_priv *priv = dev_get_priv(clk->dev); 529168404Spjd struct rk3368_cru *cru = priv->cru; 530168404Spjd const char *clock_output_name; 531168404Spjd int ret; 532168404Spjd 533168404Spjd /* 534168404Spjd * If the requested parent is in the same clock-controller and 535168404Spjd * the id is SCLK_MAC ("sclk_mac"), switch to the internal 536168404Spjd * clock. 537168404Spjd */ 538168404Spjd if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC)) { 539168404Spjd debug("%s: switching GAMC to SCLK_MAC\n", __func__); 540168404Spjd rk_clrreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 541168404Spjd return 0; 542168404Spjd } 543168404Spjd 544168404Spjd /* 545168404Spjd * Otherwise, we need to check the clock-output-names of the 546168404Spjd * requested parent to see if the requested id is "ext_gmac". 547168404Spjd */ 548168404Spjd ret = dev_read_string_index(parent->dev, "clock-output-names", 549168404Spjd parent->id, &clock_output_name); 550168404Spjd if (ret < 0) 551168404Spjd return -ENODATA; 552168404Spjd 553168404Spjd /* If this is "ext_gmac", switch to the external clock input */ 554168404Spjd if (!strcmp(clock_output_name, "ext_gmac")) { 555206796Spjd debug("%s: switching GMAC to external clock\n", __func__); 556168404Spjd rk_setreg(&cru->clksel_con[43], GMAC_MUX_SEL_EXTCLK); 557168404Spjd return 0; 558168404Spjd } 559168404Spjd 560185029Spjd return -EINVAL; 561168404Spjd} 562168404Spjd 563168404Spjdstatic int __maybe_unused rk3368_clk_set_parent(struct clk *clk, struct clk *parent) 564168404Spjd{ 565168404Spjd switch (clk->id) { 566168404Spjd case SCLK_MAC: 567168404Spjd return rk3368_gmac_set_parent(clk, parent); 568168404Spjd } 569168404Spjd 570168404Spjd debug("%s: unsupported clk %ld\n", __func__, clk->id); 571168404Spjd return -ENOENT; 572168404Spjd} 573168404Spjd 574168404Spjdstatic struct clk_ops rk3368_clk_ops = { 575275748Sdelphij .get_rate = rk3368_clk_get_rate, 576275780Sdelphij .set_rate = rk3368_clk_set_rate, 577275748Sdelphij#if CONFIG_IS_ENABLED(OF_REAL) 578275748Sdelphij .set_parent = rk3368_clk_set_parent, 579168404Spjd#endif 580251478Sdelphij}; 581251478Sdelphij 582251478Sdelphijstatic int rk3368_clk_probe(struct udevice *dev) 583168404Spjd{ 584168404Spjd struct rk3368_clk_priv __maybe_unused *priv = dev_get_priv(dev); 585209962Smm#if CONFIG_IS_ENABLED(OF_PLATDATA) 586168404Spjd struct rk3368_clk_plat *plat = dev_get_plat(dev); 587185029Spjd 588185029Spjd priv->cru = map_sysmem(plat->dtd.reg[0], plat->dtd.reg[1]); 589168404Spjd#endif 590168404Spjd#if IS_ENABLED(CONFIG_SPL_BUILD) || IS_ENABLED(CONFIG_TPL_BUILD) 591168404Spjd rkclk_init(priv->cru); 592168404Spjd#endif 593168404Spjd 594168404Spjd return 0; 595168404Spjd} 596168404Spjd 597168404Spjdstatic int rk3368_clk_of_to_plat(struct udevice *dev) 598168404Spjd{ 599168404Spjd if (CONFIG_IS_ENABLED(OF_REAL)) { 600168404Spjd struct rk3368_clk_priv *priv = dev_get_priv(dev); 601168404Spjd 602168404Spjd priv->cru = dev_read_addr_ptr(dev); 603168404Spjd } 604258632Savg 605168404Spjd return 0; 606168404Spjd} 607168404Spjd 608168404Spjdstatic int rk3368_clk_bind(struct udevice *dev) 609168404Spjd{ 610168404Spjd int ret; 611168404Spjd struct udevice *sys_child; 612168404Spjd struct sysreset_reg *priv; 613168404Spjd 614168404Spjd /* The reset driver does not have a device node, so bind it here */ 615168404Spjd ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset", 616168404Spjd &sys_child); 617219089Spjd if (ret) { 618168404Spjd debug("Warning: No sysreset driver: ret=%d\n", ret); 619168404Spjd } else { 620168404Spjd priv = malloc(sizeof(struct sysreset_reg)); 621275811Sdelphij priv->glb_srst_fst_value = offsetof(struct rk3368_cru, 622168404Spjd glb_srst_fst_val); 623168404Spjd priv->glb_srst_snd_value = offsetof(struct rk3368_cru, 624168404Spjd glb_srst_snd_val); 625168404Spjd dev_set_priv(sys_child, priv); 626168404Spjd } 627168404Spjd 628168404Spjd#if CONFIG_IS_ENABLED(RESET_ROCKCHIP) 629168404Spjd ret = offsetof(struct rk3368_cru, softrst_con[0]); 630209962Smm ret = rockchip_reset_bind(dev, ret, 15); 631168404Spjd if (ret) 632168404Spjd debug("Warning: software reset driver bind failed\n"); 633168404Spjd#endif 634168404Spjd 635168404Spjd return ret; 636168404Spjd} 637168404Spjd 638168404Spjdstatic const struct udevice_id rk3368_clk_ids[] = { 639168404Spjd { .compatible = "rockchip,rk3368-cru" }, 640168404Spjd { } 641185029Spjd}; 642185029Spjd 643185029SpjdU_BOOT_DRIVER(rockchip_rk3368_cru) = { 644168404Spjd .name = "rockchip_rk3368_cru", 645168404Spjd .id = UCLASS_CLK, 646275748Sdelphij .of_match = rk3368_clk_ids, 647275748Sdelphij .priv_auto = sizeof(struct rk3368_clk_priv), 648275748Sdelphij#if CONFIG_IS_ENABLED(OF_PLATDATA) 649275748Sdelphij .plat_auto = sizeof(struct rk3368_clk_plat), 650275748Sdelphij#endif 651275748Sdelphij .of_to_plat = rk3368_clk_of_to_plat, 652275748Sdelphij .ops = &rk3368_clk_ops, 653275748Sdelphij .bind = rk3368_clk_bind, 654275748Sdelphij .probe = rk3368_clk_probe, 655275748Sdelphij}; 656275748Sdelphij