1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
241793000SKever Yang /*
341793000SKever Yang  * (C) Copyright 2017 Rockchip Electronics Co., Ltd
441793000SKever Yang  */
541793000SKever Yang 
641793000SKever Yang #include <common.h>
7b375d841SDavid Wu #include <bitfield.h>
841793000SKever Yang #include <clk-uclass.h>
941793000SKever Yang #include <dm.h>
1041793000SKever Yang #include <errno.h>
1141793000SKever Yang #include <syscon.h>
1241793000SKever Yang #include <asm/arch/clock.h>
1341793000SKever Yang #include <asm/arch/cru_rk3328.h>
1441793000SKever Yang #include <asm/arch/hardware.h>
157cd4ebabSDavid Wu #include <asm/arch/grf_rk3328.h>
1641793000SKever Yang #include <asm/io.h>
1741793000SKever Yang #include <dm/lists.h>
1841793000SKever Yang #include <dt-bindings/clock/rk3328-cru.h>
1941793000SKever Yang 
2041793000SKever Yang struct pll_div {
2141793000SKever Yang 	u32 refdiv;
2241793000SKever Yang 	u32 fbdiv;
2341793000SKever Yang 	u32 postdiv1;
2441793000SKever Yang 	u32 postdiv2;
2541793000SKever Yang 	u32 frac;
2641793000SKever Yang };
2741793000SKever Yang 
2841793000SKever Yang #define RATE_TO_DIV(input_rate, output_rate) \
2941793000SKever Yang 	((input_rate) / (output_rate) - 1);
3041793000SKever Yang #define DIV_TO_RATE(input_rate, div)    ((input_rate) / ((div) + 1))
3141793000SKever Yang 
3241793000SKever Yang #define PLL_DIVISORS(hz, _refdiv, _postdiv1, _postdiv2) {\
3341793000SKever Yang 	.refdiv = _refdiv,\
3441793000SKever Yang 	.fbdiv = (u32)((u64)hz * _refdiv * _postdiv1 * _postdiv2 / OSC_HZ),\
3541793000SKever Yang 	.postdiv1 = _postdiv1, .postdiv2 = _postdiv2};
3641793000SKever Yang 
3741793000SKever Yang static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 1, 4, 1);
3841793000SKever Yang static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 2, 2, 1);
3941793000SKever Yang 
4041793000SKever Yang static const struct pll_div apll_816_cfg = PLL_DIVISORS(816 * MHz, 1, 2, 1);
4141793000SKever Yang static const struct pll_div apll_600_cfg = PLL_DIVISORS(600 * MHz, 1, 3, 1);
4241793000SKever Yang 
4341793000SKever Yang static const struct pll_div *apll_cfgs[] = {
4441793000SKever Yang 	[APLL_816_MHZ] = &apll_816_cfg,
4541793000SKever Yang 	[APLL_600_MHZ] = &apll_600_cfg,
4641793000SKever Yang };
4741793000SKever Yang 
4841793000SKever Yang enum {
4941793000SKever Yang 	/* PLL_CON0 */
5041793000SKever Yang 	PLL_POSTDIV1_SHIFT		= 12,
5141793000SKever Yang 	PLL_POSTDIV1_MASK		= 0x7 << PLL_POSTDIV1_SHIFT,
5241793000SKever Yang 	PLL_FBDIV_SHIFT			= 0,
5341793000SKever Yang 	PLL_FBDIV_MASK			= 0xfff,
5441793000SKever Yang 
5541793000SKever Yang 	/* PLL_CON1 */
5641793000SKever Yang 	PLL_DSMPD_SHIFT			= 12,
5741793000SKever Yang 	PLL_DSMPD_MASK			= 1 << PLL_DSMPD_SHIFT,
5841793000SKever Yang 	PLL_INTEGER_MODE		= 1,
5941793000SKever Yang 	PLL_LOCK_STATUS_SHIFT		= 10,
6041793000SKever Yang 	PLL_LOCK_STATUS_MASK		= 1 << PLL_LOCK_STATUS_SHIFT,
6141793000SKever Yang 	PLL_POSTDIV2_SHIFT		= 6,
6241793000SKever Yang 	PLL_POSTDIV2_MASK		= 0x7 << PLL_POSTDIV2_SHIFT,
6341793000SKever Yang 	PLL_REFDIV_SHIFT		= 0,
6441793000SKever Yang 	PLL_REFDIV_MASK			= 0x3f,
6541793000SKever Yang 
6641793000SKever Yang 	/* PLL_CON2 */
6741793000SKever Yang 	PLL_FRACDIV_SHIFT		= 0,
6841793000SKever Yang 	PLL_FRACDIV_MASK		= 0xffffff,
6941793000SKever Yang 
7041793000SKever Yang 	/* MODE_CON */
7141793000SKever Yang 	APLL_MODE_SHIFT			= 0,
7241793000SKever Yang 	NPLL_MODE_SHIFT			= 1,
7341793000SKever Yang 	DPLL_MODE_SHIFT			= 4,
7441793000SKever Yang 	CPLL_MODE_SHIFT			= 8,
7541793000SKever Yang 	GPLL_MODE_SHIFT			= 12,
7641793000SKever Yang 	PLL_MODE_SLOW			= 0,
7741793000SKever Yang 	PLL_MODE_NORM,
7841793000SKever Yang 
7941793000SKever Yang 	/* CLKSEL_CON0 */
8041793000SKever Yang 	CLK_CORE_PLL_SEL_APLL		= 0,
8141793000SKever Yang 	CLK_CORE_PLL_SEL_GPLL,
8241793000SKever Yang 	CLK_CORE_PLL_SEL_DPLL,
8341793000SKever Yang 	CLK_CORE_PLL_SEL_NPLL,
8441793000SKever Yang 	CLK_CORE_PLL_SEL_SHIFT		= 6,
8541793000SKever Yang 	CLK_CORE_PLL_SEL_MASK		= 3 << CLK_CORE_PLL_SEL_SHIFT,
8641793000SKever Yang 	CLK_CORE_DIV_SHIFT		= 0,
8741793000SKever Yang 	CLK_CORE_DIV_MASK		= 0x1f,
8841793000SKever Yang 
8941793000SKever Yang 	/* CLKSEL_CON1 */
9041793000SKever Yang 	ACLKM_CORE_DIV_SHIFT		= 4,
9141793000SKever Yang 	ACLKM_CORE_DIV_MASK		= 0x7 << ACLKM_CORE_DIV_SHIFT,
9241793000SKever Yang 	PCLK_DBG_DIV_SHIFT		= 0,
9341793000SKever Yang 	PCLK_DBG_DIV_MASK		= 0xF << PCLK_DBG_DIV_SHIFT,
9441793000SKever Yang 
957cd4ebabSDavid Wu 	/* CLKSEL_CON27 */
967cd4ebabSDavid Wu 	GMAC2IO_PLL_SEL_SHIFT		= 7,
977cd4ebabSDavid Wu 	GMAC2IO_PLL_SEL_MASK		= 1 << GMAC2IO_PLL_SEL_SHIFT,
987cd4ebabSDavid Wu 	GMAC2IO_PLL_SEL_CPLL		= 0,
997cd4ebabSDavid Wu 	GMAC2IO_PLL_SEL_GPLL		= 1,
1007cd4ebabSDavid Wu 	GMAC2IO_CLK_DIV_MASK		= 0x1f,
1017cd4ebabSDavid Wu 	GMAC2IO_CLK_DIV_SHIFT		= 0,
1027cd4ebabSDavid Wu 
10341793000SKever Yang 	/* CLKSEL_CON28 */
10441793000SKever Yang 	ACLK_PERIHP_PLL_SEL_CPLL	= 0,
10541793000SKever Yang 	ACLK_PERIHP_PLL_SEL_GPLL,
10641793000SKever Yang 	ACLK_PERIHP_PLL_SEL_HDMIPHY,
10741793000SKever Yang 	ACLK_PERIHP_PLL_SEL_SHIFT	= 6,
10841793000SKever Yang 	ACLK_PERIHP_PLL_SEL_MASK	= 3 << ACLK_PERIHP_PLL_SEL_SHIFT,
10941793000SKever Yang 	ACLK_PERIHP_DIV_CON_SHIFT	= 0,
11041793000SKever Yang 	ACLK_PERIHP_DIV_CON_MASK	= 0x1f,
11141793000SKever Yang 
11241793000SKever Yang 	/* CLKSEL_CON29 */
11341793000SKever Yang 	PCLK_PERIHP_DIV_CON_SHIFT	= 4,
11441793000SKever Yang 	PCLK_PERIHP_DIV_CON_MASK	= 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
11541793000SKever Yang 	HCLK_PERIHP_DIV_CON_SHIFT	= 0,
11641793000SKever Yang 	HCLK_PERIHP_DIV_CON_MASK	= 3 << HCLK_PERIHP_DIV_CON_SHIFT,
11741793000SKever Yang 
11841793000SKever Yang 	/* CLKSEL_CON22 */
11941793000SKever Yang 	CLK_TSADC_DIV_CON_SHIFT		= 0,
12041793000SKever Yang 	CLK_TSADC_DIV_CON_MASK		= 0x3ff,
12141793000SKever Yang 
12241793000SKever Yang 	/* CLKSEL_CON23 */
12341793000SKever Yang 	CLK_SARADC_DIV_CON_SHIFT	= 0,
124b375d841SDavid Wu 	CLK_SARADC_DIV_CON_MASK		= GENMASK(9, 0),
125b375d841SDavid Wu 	CLK_SARADC_DIV_CON_WIDTH	= 10,
12641793000SKever Yang 
12741793000SKever Yang 	/* CLKSEL_CON24 */
12841793000SKever Yang 	CLK_PWM_PLL_SEL_CPLL		= 0,
12941793000SKever Yang 	CLK_PWM_PLL_SEL_GPLL,
13041793000SKever Yang 	CLK_PWM_PLL_SEL_SHIFT		= 15,
13141793000SKever Yang 	CLK_PWM_PLL_SEL_MASK		= 1 << CLK_PWM_PLL_SEL_SHIFT,
13241793000SKever Yang 	CLK_PWM_DIV_CON_SHIFT		= 8,
13341793000SKever Yang 	CLK_PWM_DIV_CON_MASK		= 0x7f << CLK_PWM_DIV_CON_SHIFT,
13441793000SKever Yang 
13541793000SKever Yang 	CLK_SPI_PLL_SEL_CPLL		= 0,
13641793000SKever Yang 	CLK_SPI_PLL_SEL_GPLL,
13741793000SKever Yang 	CLK_SPI_PLL_SEL_SHIFT		= 7,
13841793000SKever Yang 	CLK_SPI_PLL_SEL_MASK		= 1 << CLK_SPI_PLL_SEL_SHIFT,
13941793000SKever Yang 	CLK_SPI_DIV_CON_SHIFT		= 0,
14041793000SKever Yang 	CLK_SPI_DIV_CON_MASK		= 0x7f << CLK_SPI_DIV_CON_SHIFT,
14141793000SKever Yang 
14241793000SKever Yang 	/* CLKSEL_CON30 */
14341793000SKever Yang 	CLK_SDMMC_PLL_SEL_CPLL		= 0,
14441793000SKever Yang 	CLK_SDMMC_PLL_SEL_GPLL,
14541793000SKever Yang 	CLK_SDMMC_PLL_SEL_24M,
14641793000SKever Yang 	CLK_SDMMC_PLL_SEL_USBPHY,
14741793000SKever Yang 	CLK_SDMMC_PLL_SHIFT		= 8,
14841793000SKever Yang 	CLK_SDMMC_PLL_MASK		= 0x3 << CLK_SDMMC_PLL_SHIFT,
14941793000SKever Yang 	CLK_SDMMC_DIV_CON_SHIFT          = 0,
15041793000SKever Yang 	CLK_SDMMC_DIV_CON_MASK           = 0xff << CLK_SDMMC_DIV_CON_SHIFT,
15141793000SKever Yang 
15241793000SKever Yang 	/* CLKSEL_CON32 */
15341793000SKever Yang 	CLK_EMMC_PLL_SEL_CPLL		= 0,
15441793000SKever Yang 	CLK_EMMC_PLL_SEL_GPLL,
15541793000SKever Yang 	CLK_EMMC_PLL_SEL_24M,
15641793000SKever Yang 	CLK_EMMC_PLL_SEL_USBPHY,
15741793000SKever Yang 	CLK_EMMC_PLL_SHIFT		= 8,
15841793000SKever Yang 	CLK_EMMC_PLL_MASK		= 0x3 << CLK_EMMC_PLL_SHIFT,
15941793000SKever Yang 	CLK_EMMC_DIV_CON_SHIFT          = 0,
16041793000SKever Yang 	CLK_EMMC_DIV_CON_MASK           = 0xff << CLK_EMMC_DIV_CON_SHIFT,
16141793000SKever Yang 
16241793000SKever Yang 	/* CLKSEL_CON34 */
16341793000SKever Yang 	CLK_I2C_PLL_SEL_CPLL		= 0,
16441793000SKever Yang 	CLK_I2C_PLL_SEL_GPLL,
16541793000SKever Yang 	CLK_I2C_DIV_CON_MASK		= 0x7f,
16641793000SKever Yang 	CLK_I2C_PLL_SEL_MASK		= 1,
16741793000SKever Yang 	CLK_I2C1_PLL_SEL_SHIFT		= 15,
16841793000SKever Yang 	CLK_I2C1_DIV_CON_SHIFT		= 8,
16941793000SKever Yang 	CLK_I2C0_PLL_SEL_SHIFT		= 7,
17041793000SKever Yang 	CLK_I2C0_DIV_CON_SHIFT		= 0,
17141793000SKever Yang 
17241793000SKever Yang 	/* CLKSEL_CON35 */
17341793000SKever Yang 	CLK_I2C3_PLL_SEL_SHIFT		= 15,
17441793000SKever Yang 	CLK_I2C3_DIV_CON_SHIFT		= 8,
17541793000SKever Yang 	CLK_I2C2_PLL_SEL_SHIFT		= 7,
17641793000SKever Yang 	CLK_I2C2_DIV_CON_SHIFT		= 0,
17741793000SKever Yang };
17841793000SKever Yang 
17941793000SKever Yang #define VCO_MAX_KHZ	(3200 * (MHz / KHz))
18041793000SKever Yang #define VCO_MIN_KHZ	(800 * (MHz / KHz))
18141793000SKever Yang #define OUTPUT_MAX_KHZ	(3200 * (MHz / KHz))
18241793000SKever Yang #define OUTPUT_MIN_KHZ	(16 * (MHz / KHz))
18341793000SKever Yang 
18441793000SKever Yang /*
18541793000SKever Yang  *  the div restructions of pll in integer mode, these are defined in
18641793000SKever Yang  *  * CRU_*PLL_CON0 or PMUCRU_*PLL_CON0
18741793000SKever Yang  */
18841793000SKever Yang #define PLL_DIV_MIN	16
18941793000SKever Yang #define PLL_DIV_MAX	3200
19041793000SKever Yang 
19141793000SKever Yang /*
19241793000SKever Yang  * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
19341793000SKever Yang  * Formulas also embedded within the Fractional PLL Verilog model:
19441793000SKever Yang  * If DSMPD = 1 (DSM is disabled, "integer mode")
19541793000SKever Yang  * FOUTVCO = FREF / REFDIV * FBDIV
19641793000SKever Yang  * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
19741793000SKever Yang  * Where:
19841793000SKever Yang  * FOUTVCO = Fractional PLL non-divided output frequency
19941793000SKever Yang  * FOUTPOSTDIV = Fractional PLL divided output frequency
20041793000SKever Yang  *               (output of second post divider)
20141793000SKever Yang  * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
20241793000SKever Yang  * REFDIV = Fractional PLL input reference clock divider
20341793000SKever Yang  * FBDIV = Integer value programmed into feedback divide
20441793000SKever Yang  *
20541793000SKever Yang  */
rkclk_set_pll(struct rk3328_cru * cru,enum rk_clk_id clk_id,const struct pll_div * div)20641793000SKever Yang static void rkclk_set_pll(struct rk3328_cru *cru, enum rk_clk_id clk_id,
20741793000SKever Yang 			const struct pll_div *div)
20841793000SKever Yang {
20941793000SKever Yang 	u32 *pll_con;
21041793000SKever Yang 	u32 mode_shift, mode_mask;
21141793000SKever Yang 
21241793000SKever Yang 	pll_con = NULL;
21341793000SKever Yang 	mode_shift = 0;
21441793000SKever Yang 	switch (clk_id) {
21541793000SKever Yang 	case CLK_ARM:
21641793000SKever Yang 		pll_con = cru->apll_con;
21741793000SKever Yang 		mode_shift = APLL_MODE_SHIFT;
21841793000SKever Yang 		break;
21941793000SKever Yang 	case CLK_DDR:
22041793000SKever Yang 		pll_con = cru->dpll_con;
22141793000SKever Yang 		mode_shift = DPLL_MODE_SHIFT;
22241793000SKever Yang 		break;
22341793000SKever Yang 	case CLK_CODEC:
22441793000SKever Yang 		pll_con = cru->cpll_con;
22541793000SKever Yang 		mode_shift = CPLL_MODE_SHIFT;
22641793000SKever Yang 		break;
22741793000SKever Yang 	case CLK_GENERAL:
22841793000SKever Yang 		pll_con = cru->gpll_con;
22941793000SKever Yang 		mode_shift = GPLL_MODE_SHIFT;
23041793000SKever Yang 		break;
23141793000SKever Yang 	case CLK_NEW:
23241793000SKever Yang 		pll_con = cru->npll_con;
23341793000SKever Yang 		mode_shift = NPLL_MODE_SHIFT;
23441793000SKever Yang 		break;
23541793000SKever Yang 	default:
23641793000SKever Yang 		break;
23741793000SKever Yang 	}
23841793000SKever Yang 	mode_mask = 1 << mode_shift;
23941793000SKever Yang 
24041793000SKever Yang 	/* All 8 PLLs have same VCO and output frequency range restrictions. */
24141793000SKever Yang 	u32 vco_khz = OSC_HZ / 1000 * div->fbdiv / div->refdiv;
24241793000SKever Yang 	u32 output_khz = vco_khz / div->postdiv1 / div->postdiv2;
24341793000SKever Yang 
24441793000SKever Yang 	debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, \
24541793000SKever Yang 	      postdiv2=%d, vco=%u khz, output=%u khz\n",
24641793000SKever Yang 	      pll_con, div->fbdiv, div->refdiv, div->postdiv1,
24741793000SKever Yang 	      div->postdiv2, vco_khz, output_khz);
24841793000SKever Yang 	assert(vco_khz >= VCO_MIN_KHZ && vco_khz <= VCO_MAX_KHZ &&
24941793000SKever Yang 	       output_khz >= OUTPUT_MIN_KHZ && output_khz <= OUTPUT_MAX_KHZ &&
25041793000SKever Yang 	       div->fbdiv >= PLL_DIV_MIN && div->fbdiv <= PLL_DIV_MAX);
25141793000SKever Yang 
25241793000SKever Yang 	/*
25341793000SKever Yang 	 * When power on or changing PLL setting,
25441793000SKever Yang 	 * we must force PLL into slow mode to ensure output stable clock.
25541793000SKever Yang 	 */
25641793000SKever Yang 	rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_SLOW << mode_shift);
25741793000SKever Yang 
25841793000SKever Yang 	/* use integer mode */
25941793000SKever Yang 	rk_clrsetreg(&pll_con[1], PLL_DSMPD_MASK,
26041793000SKever Yang 		     PLL_INTEGER_MODE << PLL_DSMPD_SHIFT);
26141793000SKever Yang 
26241793000SKever Yang 	rk_clrsetreg(&pll_con[0],
26341793000SKever Yang 		     PLL_FBDIV_MASK | PLL_POSTDIV1_MASK,
26441793000SKever Yang 		     (div->fbdiv << PLL_FBDIV_SHIFT) |
26541793000SKever Yang 		     (div->postdiv1 << PLL_POSTDIV1_SHIFT));
26641793000SKever Yang 	rk_clrsetreg(&pll_con[1],
26741793000SKever Yang 		     PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
26841793000SKever Yang 		     (div->postdiv2 << PLL_POSTDIV2_SHIFT) |
26941793000SKever Yang 		     (div->refdiv << PLL_REFDIV_SHIFT));
27041793000SKever Yang 
27141793000SKever Yang 	/* waiting for pll lock */
27241793000SKever Yang 	while (!(readl(&pll_con[1]) & (1 << PLL_LOCK_STATUS_SHIFT)))
27341793000SKever Yang 		udelay(1);
27441793000SKever Yang 
27541793000SKever Yang 	/* pll enter normal mode */
27641793000SKever Yang 	rk_clrsetreg(&cru->mode_con, mode_mask, PLL_MODE_NORM << mode_shift);
27741793000SKever Yang }
27841793000SKever Yang 
rkclk_init(struct rk3328_cru * cru)27941793000SKever Yang static void rkclk_init(struct rk3328_cru *cru)
28041793000SKever Yang {
28141793000SKever Yang 	u32 aclk_div;
28241793000SKever Yang 	u32 hclk_div;
28341793000SKever Yang 	u32 pclk_div;
28441793000SKever Yang 
28541793000SKever Yang 	/* configure gpll cpll */
28641793000SKever Yang 	rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
28741793000SKever Yang 	rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
28841793000SKever Yang 
28941793000SKever Yang 	/* configure perihp aclk, hclk, pclk */
29041793000SKever Yang 	aclk_div = GPLL_HZ / PERIHP_ACLK_HZ - 1;
29141793000SKever Yang 	hclk_div = PERIHP_ACLK_HZ / PERIHP_HCLK_HZ - 1;
29241793000SKever Yang 	pclk_div = PERIHP_ACLK_HZ / PERIHP_PCLK_HZ - 1;
29341793000SKever Yang 
29441793000SKever Yang 	rk_clrsetreg(&cru->clksel_con[28],
29541793000SKever Yang 		     ACLK_PERIHP_PLL_SEL_MASK | ACLK_PERIHP_DIV_CON_MASK,
29641793000SKever Yang 		     ACLK_PERIHP_PLL_SEL_GPLL << ACLK_PERIHP_PLL_SEL_SHIFT |
29741793000SKever Yang 		     aclk_div << ACLK_PERIHP_DIV_CON_SHIFT);
29841793000SKever Yang 	rk_clrsetreg(&cru->clksel_con[29],
29941793000SKever Yang 		     PCLK_PERIHP_DIV_CON_MASK | HCLK_PERIHP_DIV_CON_MASK,
30041793000SKever Yang 		     pclk_div << PCLK_PERIHP_DIV_CON_SHIFT |
30141793000SKever Yang 		     hclk_div << HCLK_PERIHP_DIV_CON_SHIFT);
30241793000SKever Yang }
30341793000SKever Yang 
rk3328_configure_cpu(struct rk3328_cru * cru,enum apll_frequencies apll_freq)30441793000SKever Yang void rk3328_configure_cpu(struct rk3328_cru *cru,
30541793000SKever Yang 			  enum apll_frequencies apll_freq)
30641793000SKever Yang {
30741793000SKever Yang 	u32 clk_core_div;
30841793000SKever Yang 	u32 aclkm_div;
30941793000SKever Yang 	u32 pclk_dbg_div;
31041793000SKever Yang 
31141793000SKever Yang 	rkclk_set_pll(cru, CLK_ARM, apll_cfgs[apll_freq]);
31241793000SKever Yang 
31341793000SKever Yang 	clk_core_div = APLL_HZ / CLK_CORE_HZ - 1;
31441793000SKever Yang 	aclkm_div = APLL_HZ / ACLKM_CORE_HZ / (clk_core_div + 1) - 1;
31541793000SKever Yang 	pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ / (clk_core_div + 1) - 1;
31641793000SKever Yang 
31741793000SKever Yang 	rk_clrsetreg(&cru->clksel_con[0],
31841793000SKever Yang 		     CLK_CORE_PLL_SEL_MASK | CLK_CORE_DIV_MASK,
31941793000SKever Yang 		     CLK_CORE_PLL_SEL_APLL << CLK_CORE_PLL_SEL_SHIFT |
32041793000SKever Yang 		     clk_core_div << CLK_CORE_DIV_SHIFT);
32141793000SKever Yang 
32241793000SKever Yang 	rk_clrsetreg(&cru->clksel_con[1],
32341793000SKever Yang 		     PCLK_DBG_DIV_MASK | ACLKM_CORE_DIV_MASK,
32441793000SKever Yang 		     pclk_dbg_div << PCLK_DBG_DIV_SHIFT |
32541793000SKever Yang 		     aclkm_div << ACLKM_CORE_DIV_SHIFT);
32641793000SKever Yang }
32741793000SKever Yang 
32841793000SKever Yang 
rk3328_i2c_get_clk(struct rk3328_cru * cru,ulong clk_id)32941793000SKever Yang static ulong rk3328_i2c_get_clk(struct rk3328_cru *cru, ulong clk_id)
33041793000SKever Yang {
33141793000SKever Yang 	u32 div, con;
33241793000SKever Yang 
33341793000SKever Yang 	switch (clk_id) {
33441793000SKever Yang 	case SCLK_I2C0:
33541793000SKever Yang 		con = readl(&cru->clksel_con[34]);
33641793000SKever Yang 		div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
33741793000SKever Yang 		break;
33841793000SKever Yang 	case SCLK_I2C1:
33941793000SKever Yang 		con = readl(&cru->clksel_con[34]);
34041793000SKever Yang 		div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
34141793000SKever Yang 		break;
34241793000SKever Yang 	case SCLK_I2C2:
34341793000SKever Yang 		con = readl(&cru->clksel_con[35]);
34441793000SKever Yang 		div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
34541793000SKever Yang 		break;
34641793000SKever Yang 	case SCLK_I2C3:
34741793000SKever Yang 		con = readl(&cru->clksel_con[35]);
34841793000SKever Yang 		div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
34941793000SKever Yang 		break;
35041793000SKever Yang 	default:
35141793000SKever Yang 		printf("do not support this i2c bus\n");
35241793000SKever Yang 		return -EINVAL;
35341793000SKever Yang 	}
35441793000SKever Yang 
35541793000SKever Yang 	return DIV_TO_RATE(GPLL_HZ, div);
35641793000SKever Yang }
35741793000SKever Yang 
rk3328_i2c_set_clk(struct rk3328_cru * cru,ulong clk_id,uint hz)35841793000SKever Yang static ulong rk3328_i2c_set_clk(struct rk3328_cru *cru, ulong clk_id, uint hz)
35941793000SKever Yang {
36041793000SKever Yang 	int src_clk_div;
36141793000SKever Yang 
36241793000SKever Yang 	src_clk_div = GPLL_HZ / hz;
36341793000SKever Yang 	assert(src_clk_div - 1 < 127);
36441793000SKever Yang 
36541793000SKever Yang 	switch (clk_id) {
36641793000SKever Yang 	case SCLK_I2C0:
36741793000SKever Yang 		rk_clrsetreg(&cru->clksel_con[34],
36841793000SKever Yang 			     CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
36941793000SKever Yang 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
37041793000SKever Yang 			     (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
37141793000SKever Yang 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
37241793000SKever Yang 		break;
37341793000SKever Yang 	case SCLK_I2C1:
37441793000SKever Yang 		rk_clrsetreg(&cru->clksel_con[34],
37541793000SKever Yang 			     CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
37641793000SKever Yang 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
37741793000SKever Yang 			     (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
37841793000SKever Yang 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
37941793000SKever Yang 		break;
38041793000SKever Yang 	case SCLK_I2C2:
38141793000SKever Yang 		rk_clrsetreg(&cru->clksel_con[35],
38241793000SKever Yang 			     CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
38341793000SKever Yang 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
38441793000SKever Yang 			     (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
38541793000SKever Yang 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
38641793000SKever Yang 		break;
38741793000SKever Yang 	case SCLK_I2C3:
38841793000SKever Yang 		rk_clrsetreg(&cru->clksel_con[35],
38941793000SKever Yang 			     CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
39041793000SKever Yang 			     CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
39141793000SKever Yang 			     (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
39241793000SKever Yang 			     CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
39341793000SKever Yang 		break;
39441793000SKever Yang 	default:
39541793000SKever Yang 		printf("do not support this i2c bus\n");
39641793000SKever Yang 		return -EINVAL;
39741793000SKever Yang 	}
39841793000SKever Yang 
39941793000SKever Yang 	return DIV_TO_RATE(GPLL_HZ, src_clk_div);
40041793000SKever Yang }
40141793000SKever Yang 
rk3328_gmac2io_set_clk(struct rk3328_cru * cru,ulong rate)4027cd4ebabSDavid Wu static ulong rk3328_gmac2io_set_clk(struct rk3328_cru *cru, ulong rate)
4037cd4ebabSDavid Wu {
4047cd4ebabSDavid Wu 	struct rk3328_grf_regs *grf;
4057cd4ebabSDavid Wu 	ulong ret;
4067cd4ebabSDavid Wu 
4077cd4ebabSDavid Wu 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
4087cd4ebabSDavid Wu 
4097cd4ebabSDavid Wu 	/*
4107cd4ebabSDavid Wu 	 * The RGMII CLK can be derived either from an external "clkin"
4117cd4ebabSDavid Wu 	 * or can be generated from internally by a divider from SCLK_MAC.
4127cd4ebabSDavid Wu 	 */
4137cd4ebabSDavid Wu 	if (readl(&grf->mac_con[1]) & BIT(10) &&
4147cd4ebabSDavid Wu 	    readl(&grf->soc_con[4]) & BIT(14)) {
4157cd4ebabSDavid Wu 		/* An external clock will always generate the right rate... */
4167cd4ebabSDavid Wu 		ret = rate;
4177cd4ebabSDavid Wu 	} else {
4187cd4ebabSDavid Wu 		u32 con = readl(&cru->clksel_con[27]);
4197cd4ebabSDavid Wu 		ulong pll_rate;
4207cd4ebabSDavid Wu 		u8 div;
4217cd4ebabSDavid Wu 
4227cd4ebabSDavid Wu 		if ((con >> GMAC2IO_PLL_SEL_SHIFT) & GMAC2IO_PLL_SEL_GPLL)
4237cd4ebabSDavid Wu 			pll_rate = GPLL_HZ;
4247cd4ebabSDavid Wu 		else
4257cd4ebabSDavid Wu 			pll_rate = CPLL_HZ;
4267cd4ebabSDavid Wu 
4277cd4ebabSDavid Wu 		div = DIV_ROUND_UP(pll_rate, rate) - 1;
4287cd4ebabSDavid Wu 		if (div <= 0x1f)
4297cd4ebabSDavid Wu 			rk_clrsetreg(&cru->clksel_con[27], GMAC2IO_CLK_DIV_MASK,
4307cd4ebabSDavid Wu 				     div << GMAC2IO_CLK_DIV_SHIFT);
4317cd4ebabSDavid Wu 		else
4327cd4ebabSDavid Wu 			debug("Unsupported div for gmac:%d\n", div);
4337cd4ebabSDavid Wu 
4347cd4ebabSDavid Wu 		return DIV_TO_RATE(pll_rate, div);
4357cd4ebabSDavid Wu 	}
4367cd4ebabSDavid Wu 
4377cd4ebabSDavid Wu 	return ret;
4387cd4ebabSDavid Wu }
4397cd4ebabSDavid Wu 
rk3328_mmc_get_clk(struct rk3328_cru * cru,uint clk_id)44041793000SKever Yang static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id)
44141793000SKever Yang {
44241793000SKever Yang 	u32 div, con, con_id;
44341793000SKever Yang 
44441793000SKever Yang 	switch (clk_id) {
44541793000SKever Yang 	case HCLK_SDMMC:
44685c91cb6SXu Ziyuan 	case SCLK_SDMMC:
44741793000SKever Yang 		con_id = 30;
44841793000SKever Yang 		break;
44941793000SKever Yang 	case HCLK_EMMC:
45085c91cb6SXu Ziyuan 	case SCLK_EMMC:
45141793000SKever Yang 		con_id = 32;
45241793000SKever Yang 		break;
45341793000SKever Yang 	default:
45441793000SKever Yang 		return -EINVAL;
45541793000SKever Yang 	}
45641793000SKever Yang 	con = readl(&cru->clksel_con[con_id]);
45741793000SKever Yang 	div = (con & CLK_EMMC_DIV_CON_MASK) >> CLK_EMMC_DIV_CON_SHIFT;
45841793000SKever Yang 
45941793000SKever Yang 	if ((con & CLK_EMMC_PLL_MASK) >> CLK_EMMC_PLL_SHIFT
46041793000SKever Yang 	    == CLK_EMMC_PLL_SEL_24M)
4613a94d75dSKever Yang 		return DIV_TO_RATE(OSC_HZ, div) / 2;
46241793000SKever Yang 	else
4633a94d75dSKever Yang 		return DIV_TO_RATE(GPLL_HZ, div) / 2;
46441793000SKever Yang }
46541793000SKever Yang 
rk3328_mmc_set_clk(struct rk3328_cru * cru,ulong clk_id,ulong set_rate)46641793000SKever Yang static ulong rk3328_mmc_set_clk(struct rk3328_cru *cru,
46741793000SKever Yang 				ulong clk_id, ulong set_rate)
46841793000SKever Yang {
46941793000SKever Yang 	int src_clk_div;
47041793000SKever Yang 	u32 con_id;
47141793000SKever Yang 
47241793000SKever Yang 	switch (clk_id) {
47341793000SKever Yang 	case HCLK_SDMMC:
47485c91cb6SXu Ziyuan 	case SCLK_SDMMC:
47541793000SKever Yang 		con_id = 30;
47641793000SKever Yang 		break;
47741793000SKever Yang 	case HCLK_EMMC:
47885c91cb6SXu Ziyuan 	case SCLK_EMMC:
47941793000SKever Yang 		con_id = 32;
48041793000SKever Yang 		break;
48141793000SKever Yang 	default:
48241793000SKever Yang 		return -EINVAL;
48341793000SKever Yang 	}
48441793000SKever Yang 	/* Select clk_sdmmc/emmc source from GPLL by default */
4853a94d75dSKever Yang 	/* mmc clock defaulg div 2 internal, need provide double in cru */
4863a94d75dSKever Yang 	src_clk_div = DIV_ROUND_UP(GPLL_HZ / 2, set_rate);
48741793000SKever Yang 
48841793000SKever Yang 	if (src_clk_div > 127) {
48941793000SKever Yang 		/* use 24MHz source for 400KHz clock */
4903a94d75dSKever Yang 		src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
49141793000SKever Yang 		rk_clrsetreg(&cru->clksel_con[con_id],
49241793000SKever Yang 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
49341793000SKever Yang 			     CLK_EMMC_PLL_SEL_24M << CLK_EMMC_PLL_SHIFT |
49441793000SKever Yang 			     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
49541793000SKever Yang 	} else {
49641793000SKever Yang 		rk_clrsetreg(&cru->clksel_con[con_id],
49741793000SKever Yang 			     CLK_EMMC_PLL_MASK | CLK_EMMC_DIV_CON_MASK,
49841793000SKever Yang 			     CLK_EMMC_PLL_SEL_GPLL << CLK_EMMC_PLL_SHIFT |
49941793000SKever Yang 			     (src_clk_div - 1) << CLK_EMMC_DIV_CON_SHIFT);
50041793000SKever Yang 	}
50141793000SKever Yang 
50241793000SKever Yang 	return rk3328_mmc_get_clk(cru, clk_id);
50341793000SKever Yang }
50441793000SKever Yang 
rk3328_pwm_get_clk(struct rk3328_cru * cru)50541793000SKever Yang static ulong rk3328_pwm_get_clk(struct rk3328_cru *cru)
50641793000SKever Yang {
50741793000SKever Yang 	u32 div, con;
50841793000SKever Yang 
50941793000SKever Yang 	con = readl(&cru->clksel_con[24]);
51041793000SKever Yang 	div = (con & CLK_PWM_DIV_CON_MASK) >> CLK_PWM_DIV_CON_SHIFT;
51141793000SKever Yang 
51241793000SKever Yang 	return DIV_TO_RATE(GPLL_HZ, div);
51341793000SKever Yang }
51441793000SKever Yang 
rk3328_pwm_set_clk(struct rk3328_cru * cru,uint hz)51541793000SKever Yang static ulong rk3328_pwm_set_clk(struct rk3328_cru *cru, uint hz)
51641793000SKever Yang {
51741793000SKever Yang 	u32 div = GPLL_HZ / hz;
51841793000SKever Yang 
51941793000SKever Yang 	rk_clrsetreg(&cru->clksel_con[24],
52041793000SKever Yang 		     CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK,
52141793000SKever Yang 		     CLK_PWM_PLL_SEL_GPLL << CLK_PWM_PLL_SEL_SHIFT |
52241793000SKever Yang 		     (div - 1) << CLK_PWM_DIV_CON_SHIFT);
52341793000SKever Yang 
52441793000SKever Yang 	return DIV_TO_RATE(GPLL_HZ, div);
52541793000SKever Yang }
52641793000SKever Yang 
rk3328_saradc_get_clk(struct rk3328_cru * cru)527b375d841SDavid Wu static ulong rk3328_saradc_get_clk(struct rk3328_cru *cru)
528b375d841SDavid Wu {
529b375d841SDavid Wu 	u32 div, val;
530b375d841SDavid Wu 
531b375d841SDavid Wu 	val = readl(&cru->clksel_con[23]);
532b375d841SDavid Wu 	div = bitfield_extract(val, CLK_SARADC_DIV_CON_SHIFT,
533b375d841SDavid Wu 			       CLK_SARADC_DIV_CON_WIDTH);
534b375d841SDavid Wu 
535b375d841SDavid Wu 	return DIV_TO_RATE(OSC_HZ, div);
536b375d841SDavid Wu }
537b375d841SDavid Wu 
rk3328_saradc_set_clk(struct rk3328_cru * cru,uint hz)538b375d841SDavid Wu static ulong rk3328_saradc_set_clk(struct rk3328_cru *cru, uint hz)
539b375d841SDavid Wu {
540b375d841SDavid Wu 	int src_clk_div;
541b375d841SDavid Wu 
542b375d841SDavid Wu 	src_clk_div = DIV_ROUND_UP(OSC_HZ, hz) - 1;
543b375d841SDavid Wu 	assert(src_clk_div < 128);
544b375d841SDavid Wu 
545b375d841SDavid Wu 	rk_clrsetreg(&cru->clksel_con[23],
546b375d841SDavid Wu 		     CLK_SARADC_DIV_CON_MASK,
547b375d841SDavid Wu 		     src_clk_div << CLK_SARADC_DIV_CON_SHIFT);
548b375d841SDavid Wu 
549b375d841SDavid Wu 	return rk3328_saradc_get_clk(cru);
550b375d841SDavid Wu }
551b375d841SDavid Wu 
rk3328_clk_get_rate(struct clk * clk)55241793000SKever Yang static ulong rk3328_clk_get_rate(struct clk *clk)
55341793000SKever Yang {
55441793000SKever Yang 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
55541793000SKever Yang 	ulong rate = 0;
55641793000SKever Yang 
55741793000SKever Yang 	switch (clk->id) {
55841793000SKever Yang 	case 0 ... 29:
55941793000SKever Yang 		return 0;
56041793000SKever Yang 	case HCLK_SDMMC:
56141793000SKever Yang 	case HCLK_EMMC:
56285c91cb6SXu Ziyuan 	case SCLK_SDMMC:
56385c91cb6SXu Ziyuan 	case SCLK_EMMC:
56441793000SKever Yang 		rate = rk3328_mmc_get_clk(priv->cru, clk->id);
56541793000SKever Yang 		break;
56641793000SKever Yang 	case SCLK_I2C0:
56741793000SKever Yang 	case SCLK_I2C1:
56841793000SKever Yang 	case SCLK_I2C2:
56941793000SKever Yang 	case SCLK_I2C3:
57041793000SKever Yang 		rate = rk3328_i2c_get_clk(priv->cru, clk->id);
57141793000SKever Yang 		break;
57241793000SKever Yang 	case SCLK_PWM:
57341793000SKever Yang 		rate = rk3328_pwm_get_clk(priv->cru);
57441793000SKever Yang 		break;
575b375d841SDavid Wu 	case SCLK_SARADC:
576b375d841SDavid Wu 		rate = rk3328_saradc_get_clk(priv->cru);
577b375d841SDavid Wu 		break;
57841793000SKever Yang 	default:
57941793000SKever Yang 		return -ENOENT;
58041793000SKever Yang 	}
58141793000SKever Yang 
58241793000SKever Yang 	return rate;
58341793000SKever Yang }
58441793000SKever Yang 
rk3328_clk_set_rate(struct clk * clk,ulong rate)58541793000SKever Yang static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate)
58641793000SKever Yang {
58741793000SKever Yang 	struct rk3328_clk_priv *priv = dev_get_priv(clk->dev);
58841793000SKever Yang 	ulong ret = 0;
58941793000SKever Yang 
59041793000SKever Yang 	switch (clk->id) {
59141793000SKever Yang 	case 0 ... 29:
59241793000SKever Yang 		return 0;
59341793000SKever Yang 	case HCLK_SDMMC:
59441793000SKever Yang 	case HCLK_EMMC:
59585c91cb6SXu Ziyuan 	case SCLK_SDMMC:
59685c91cb6SXu Ziyuan 	case SCLK_EMMC:
59741793000SKever Yang 		ret = rk3328_mmc_set_clk(priv->cru, clk->id, rate);
59841793000SKever Yang 		break;
59941793000SKever Yang 	case SCLK_I2C0:
60041793000SKever Yang 	case SCLK_I2C1:
60141793000SKever Yang 	case SCLK_I2C2:
60241793000SKever Yang 	case SCLK_I2C3:
60341793000SKever Yang 		ret = rk3328_i2c_set_clk(priv->cru, clk->id, rate);
60441793000SKever Yang 		break;
6057cd4ebabSDavid Wu 	case SCLK_MAC2IO:
6067cd4ebabSDavid Wu 		ret = rk3328_gmac2io_set_clk(priv->cru, rate);
6077cd4ebabSDavid Wu 		break;
60841793000SKever Yang 	case SCLK_PWM:
60941793000SKever Yang 		ret = rk3328_pwm_set_clk(priv->cru, rate);
61041793000SKever Yang 		break;
611b375d841SDavid Wu 	case SCLK_SARADC:
612b375d841SDavid Wu 		ret = rk3328_saradc_set_clk(priv->cru, rate);
613b375d841SDavid Wu 		break;
6147cd4ebabSDavid Wu 	case DCLK_LCDC:
6157cd4ebabSDavid Wu 	case SCLK_PDM:
6167cd4ebabSDavid Wu 	case SCLK_RTC32K:
6177cd4ebabSDavid Wu 	case SCLK_UART0:
6187cd4ebabSDavid Wu 	case SCLK_UART1:
6197cd4ebabSDavid Wu 	case SCLK_UART2:
6207cd4ebabSDavid Wu 	case SCLK_SDIO:
6217cd4ebabSDavid Wu 	case SCLK_TSP:
6227cd4ebabSDavid Wu 	case SCLK_WIFI:
6237cd4ebabSDavid Wu 	case ACLK_BUS_PRE:
6247cd4ebabSDavid Wu 	case HCLK_BUS_PRE:
6257cd4ebabSDavid Wu 	case PCLK_BUS_PRE:
6267cd4ebabSDavid Wu 	case ACLK_PERI_PRE:
6277cd4ebabSDavid Wu 	case HCLK_PERI:
6287cd4ebabSDavid Wu 	case PCLK_PERI:
6297cd4ebabSDavid Wu 	case ACLK_VIO_PRE:
6307cd4ebabSDavid Wu 	case HCLK_VIO_PRE:
6317cd4ebabSDavid Wu 	case ACLK_RGA_PRE:
6327cd4ebabSDavid Wu 	case SCLK_RGA:
6337cd4ebabSDavid Wu 	case ACLK_VOP_PRE:
6347cd4ebabSDavid Wu 	case ACLK_RKVDEC_PRE:
6357cd4ebabSDavid Wu 	case ACLK_RKVENC:
6367cd4ebabSDavid Wu 	case ACLK_VPU_PRE:
6377cd4ebabSDavid Wu 	case SCLK_VDEC_CABAC:
6387cd4ebabSDavid Wu 	case SCLK_VDEC_CORE:
6397cd4ebabSDavid Wu 	case SCLK_VENC_CORE:
6407cd4ebabSDavid Wu 	case SCLK_VENC_DSP:
6417cd4ebabSDavid Wu 	case SCLK_EFUSE:
6427cd4ebabSDavid Wu 	case PCLK_DDR:
6437cd4ebabSDavid Wu 	case ACLK_GMAC:
6447cd4ebabSDavid Wu 	case PCLK_GMAC:
6457cd4ebabSDavid Wu 	case SCLK_USB3OTG_SUSPEND:
6467cd4ebabSDavid Wu 		return 0;
64741793000SKever Yang 	default:
64841793000SKever Yang 		return -ENOENT;
64941793000SKever Yang 	}
65041793000SKever Yang 
65141793000SKever Yang 	return ret;
65241793000SKever Yang }
65341793000SKever Yang 
rk3328_gmac2io_set_parent(struct clk * clk,struct clk * parent)6547cd4ebabSDavid Wu static int rk3328_gmac2io_set_parent(struct clk *clk, struct clk *parent)
6557cd4ebabSDavid Wu {
6567cd4ebabSDavid Wu 	struct rk3328_grf_regs *grf;
6577cd4ebabSDavid Wu 	const char *clock_output_name;
6587cd4ebabSDavid Wu 	int ret;
6597cd4ebabSDavid Wu 
6607cd4ebabSDavid Wu 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
6617cd4ebabSDavid Wu 
6627cd4ebabSDavid Wu 	/*
6637cd4ebabSDavid Wu 	 * If the requested parent is in the same clock-controller and the id
6647cd4ebabSDavid Wu 	 * is SCLK_MAC2IO_SRC ("clk_mac2io_src"), switch to the internal clock.
6657cd4ebabSDavid Wu 	 */
6667cd4ebabSDavid Wu 	if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO_SRC)) {
6677cd4ebabSDavid Wu 		debug("%s: switching RGMII to SCLK_MAC2IO_SRC\n", __func__);
6687cd4ebabSDavid Wu 		rk_clrreg(&grf->mac_con[1], BIT(10));
6697cd4ebabSDavid Wu 		return 0;
6707cd4ebabSDavid Wu 	}
6717cd4ebabSDavid Wu 
6727cd4ebabSDavid Wu 	/*
6737cd4ebabSDavid Wu 	 * Otherwise, we need to check the clock-output-names of the
6747cd4ebabSDavid Wu 	 * requested parent to see if the requested id is "gmac_clkin".
6757cd4ebabSDavid Wu 	 */
6767cd4ebabSDavid Wu 	ret = dev_read_string_index(parent->dev, "clock-output-names",
6777cd4ebabSDavid Wu 				    parent->id, &clock_output_name);
6787cd4ebabSDavid Wu 	if (ret < 0)
6797cd4ebabSDavid Wu 		return -ENODATA;
6807cd4ebabSDavid Wu 
6817cd4ebabSDavid Wu 	/* If this is "gmac_clkin", switch to the external clock input */
6827cd4ebabSDavid Wu 	if (!strcmp(clock_output_name, "gmac_clkin")) {
6837cd4ebabSDavid Wu 		debug("%s: switching RGMII to CLKIN\n", __func__);
6847cd4ebabSDavid Wu 		rk_setreg(&grf->mac_con[1], BIT(10));
6857cd4ebabSDavid Wu 		return 0;
6867cd4ebabSDavid Wu 	}
6877cd4ebabSDavid Wu 
6887cd4ebabSDavid Wu 	return -EINVAL;
6897cd4ebabSDavid Wu }
6907cd4ebabSDavid Wu 
rk3328_gmac2io_ext_set_parent(struct clk * clk,struct clk * parent)6917cd4ebabSDavid Wu static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent)
6927cd4ebabSDavid Wu {
6937cd4ebabSDavid Wu 	struct rk3328_grf_regs *grf;
6947cd4ebabSDavid Wu 	const char *clock_output_name;
6957cd4ebabSDavid Wu 	int ret;
6967cd4ebabSDavid Wu 
6977cd4ebabSDavid Wu 	grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
6987cd4ebabSDavid Wu 
6997cd4ebabSDavid Wu 	/*
7007cd4ebabSDavid Wu 	 * If the requested parent is in the same clock-controller and the id
7017cd4ebabSDavid Wu 	 * is SCLK_MAC2IO ("clk_mac2io"), switch to the internal clock.
7027cd4ebabSDavid Wu 	 */
7037cd4ebabSDavid Wu 	if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2IO)) {
7047cd4ebabSDavid Wu 		debug("%s: switching RGMII to SCLK_MAC2IO\n", __func__);
7057cd4ebabSDavid Wu 		rk_clrreg(&grf->soc_con[4], BIT(14));
7067cd4ebabSDavid Wu 		return 0;
7077cd4ebabSDavid Wu 	}
7087cd4ebabSDavid Wu 
7097cd4ebabSDavid Wu 	/*
7107cd4ebabSDavid Wu 	 * Otherwise, we need to check the clock-output-names of the
7117cd4ebabSDavid Wu 	 * requested parent to see if the requested id is "gmac_clkin".
7127cd4ebabSDavid Wu 	 */
7137cd4ebabSDavid Wu 	ret = dev_read_string_index(parent->dev, "clock-output-names",
7147cd4ebabSDavid Wu 				    parent->id, &clock_output_name);
7157cd4ebabSDavid Wu 	if (ret < 0)
7167cd4ebabSDavid Wu 		return -ENODATA;
7177cd4ebabSDavid Wu 
7187cd4ebabSDavid Wu 	/* If this is "gmac_clkin", switch to the external clock input */
7197cd4ebabSDavid Wu 	if (!strcmp(clock_output_name, "gmac_clkin")) {
7207cd4ebabSDavid Wu 		debug("%s: switching RGMII to CLKIN\n", __func__);
7217cd4ebabSDavid Wu 		rk_setreg(&grf->soc_con[4], BIT(14));
7227cd4ebabSDavid Wu 		return 0;
7237cd4ebabSDavid Wu 	}
7247cd4ebabSDavid Wu 
7257cd4ebabSDavid Wu 	return -EINVAL;
7267cd4ebabSDavid Wu }
7277cd4ebabSDavid Wu 
rk3328_clk_set_parent(struct clk * clk,struct clk * parent)7287cd4ebabSDavid Wu static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent)
7297cd4ebabSDavid Wu {
7307cd4ebabSDavid Wu 	switch (clk->id) {
7317cd4ebabSDavid Wu 	case SCLK_MAC2IO:
7327cd4ebabSDavid Wu 		return rk3328_gmac2io_set_parent(clk, parent);
7337cd4ebabSDavid Wu 	case SCLK_MAC2IO_EXT:
7347cd4ebabSDavid Wu 		return rk3328_gmac2io_ext_set_parent(clk, parent);
7357cd4ebabSDavid Wu 	case DCLK_LCDC:
7367cd4ebabSDavid Wu 	case SCLK_PDM:
7377cd4ebabSDavid Wu 	case SCLK_RTC32K:
7387cd4ebabSDavid Wu 	case SCLK_UART0:
7397cd4ebabSDavid Wu 	case SCLK_UART1:
7407cd4ebabSDavid Wu 	case SCLK_UART2:
7417cd4ebabSDavid Wu 		return 0;
7427cd4ebabSDavid Wu 	}
7437cd4ebabSDavid Wu 
7447cd4ebabSDavid Wu 	debug("%s: unsupported clk %ld\n", __func__, clk->id);
7457cd4ebabSDavid Wu 	return -ENOENT;
7467cd4ebabSDavid Wu }
7477cd4ebabSDavid Wu 
74841793000SKever Yang static struct clk_ops rk3328_clk_ops = {
74941793000SKever Yang 	.get_rate = rk3328_clk_get_rate,
75041793000SKever Yang 	.set_rate = rk3328_clk_set_rate,
7517cd4ebabSDavid Wu 	.set_parent = rk3328_clk_set_parent,
75241793000SKever Yang };
75341793000SKever Yang 
rk3328_clk_probe(struct udevice * dev)75441793000SKever Yang static int rk3328_clk_probe(struct udevice *dev)
75541793000SKever Yang {
75641793000SKever Yang 	struct rk3328_clk_priv *priv = dev_get_priv(dev);
75741793000SKever Yang 
75841793000SKever Yang 	rkclk_init(priv->cru);
75941793000SKever Yang 
76041793000SKever Yang 	return 0;
76141793000SKever Yang }
76241793000SKever Yang 
rk3328_clk_ofdata_to_platdata(struct udevice * dev)76341793000SKever Yang static int rk3328_clk_ofdata_to_platdata(struct udevice *dev)
76441793000SKever Yang {
76541793000SKever Yang 	struct rk3328_clk_priv *priv = dev_get_priv(dev);
76641793000SKever Yang 
76708516431SKever Yang 	priv->cru = dev_read_addr_ptr(dev);
76841793000SKever Yang 
76941793000SKever Yang 	return 0;
77041793000SKever Yang }
77141793000SKever Yang 
rk3328_clk_bind(struct udevice * dev)77241793000SKever Yang static int rk3328_clk_bind(struct udevice *dev)
77341793000SKever Yang {
77441793000SKever Yang 	int ret;
775f24e36daSKever Yang 	struct udevice *sys_child;
776f24e36daSKever Yang 	struct sysreset_reg *priv;
77741793000SKever Yang 
77841793000SKever Yang 	/* The reset driver does not have a device node, so bind it here */
779f24e36daSKever Yang 	ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
780f24e36daSKever Yang 				 &sys_child);
781f24e36daSKever Yang 	if (ret) {
782f24e36daSKever Yang 		debug("Warning: No sysreset driver: ret=%d\n", ret);
783f24e36daSKever Yang 	} else {
784f24e36daSKever Yang 		priv = malloc(sizeof(struct sysreset_reg));
785f24e36daSKever Yang 		priv->glb_srst_fst_value = offsetof(struct rk3328_cru,
786f24e36daSKever Yang 						    glb_srst_fst_value);
787f24e36daSKever Yang 		priv->glb_srst_snd_value = offsetof(struct rk3328_cru,
788f24e36daSKever Yang 						    glb_srst_snd_value);
789f24e36daSKever Yang 		sys_child->priv = priv;
790f24e36daSKever Yang 	}
79141793000SKever Yang 
792538f67c3SElaine Zhang #if CONFIG_IS_ENABLED(CONFIG_RESET_ROCKCHIP)
793538f67c3SElaine Zhang 	ret = offsetof(struct rk3328_cru, softrst_con[0]);
794538f67c3SElaine Zhang 	ret = rockchip_reset_bind(dev, ret, 12);
795538f67c3SElaine Zhang 	if (ret)
796538f67c3SElaine Zhang 		debug("Warning: software reset driver bind faile\n");
797538f67c3SElaine Zhang #endif
798538f67c3SElaine Zhang 
79941793000SKever Yang 	return ret;
80041793000SKever Yang }
80141793000SKever Yang 
80241793000SKever Yang static const struct udevice_id rk3328_clk_ids[] = {
80341793000SKever Yang 	{ .compatible = "rockchip,rk3328-cru" },
80441793000SKever Yang 	{ }
80541793000SKever Yang };
80641793000SKever Yang 
80741793000SKever Yang U_BOOT_DRIVER(rockchip_rk3328_cru) = {
80841793000SKever Yang 	.name		= "rockchip_rk3328_cru",
80941793000SKever Yang 	.id		= UCLASS_CLK,
81041793000SKever Yang 	.of_match	= rk3328_clk_ids,
81141793000SKever Yang 	.priv_auto_alloc_size = sizeof(struct rk3328_clk_priv),
81241793000SKever Yang 	.ofdata_to_platdata = rk3328_clk_ofdata_to_platdata,
81341793000SKever Yang 	.ops		= &rk3328_clk_ops,
81441793000SKever Yang 	.bind		= rk3328_clk_bind,
81541793000SKever Yang 	.probe		= rk3328_clk_probe,
81641793000SKever Yang };
817