Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab98e20a authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'v4.7-rockchip-clk1' of...

Merge tag 'v4.7-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip into clk-next

Pull rockchip clk updates from Heiko Stuebner:

This is first big chunk of Rockchip clock-related changes for 4.7.

Main change is probably the added support for the new rk3399 soc
and necessary infrastructure changes surrounding it.

The biggest chunk is probably that clock code is now able to
handle multiple clock providers in one system, as the rk3399
has two of those. A general one and another smaller one in a
separate power domain. The rk3399 also uses another new pll type.
Thankfully it just fits nicely into our current structure.
It also needs some parts like the cpuclk mux parameters to be
a bit more flexible and an new fractional divider subtype without
gate.

Apart from this big change we have some more fixes and removal
of forgotten variables.

* tag 'v4.7-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
  clk: rockchip: add clock controller for the RK3399
  dt-bindings: add bindings for rk3399 clock controller
  clk: rockchip: add dt-binding header for rk3399
  clk: rockchip: release io resource when failing to init clk
  clk: rockchip: remove redundant checking of device_node
  clk: rockchip: fix warning reported by kernel-doc
  clk: rockchip: remove mux_core_reg from rockchip_cpuclk_reg_data
  clk: rockchip: add new pll-type for rk3399 and similar socs
  clk: rockchip: Add support for multiple clock providers
  clk: rockchip: allow varying mux parameters for cpuclk pll-sources
  clk: rockchip: add a COMPOSITE_FRACMUX_NOGATE type
parents 56ad09e2 11551005
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
* Rockchip RK3399 Clock and Reset Unit

The RK3399 clock controller generates and supplies clock to various
controllers within the SoC and also implements a reset controller for SoC
peripherals.

Required Properties:

- compatible: PMU for CRU should be "rockchip,rk3399-pmucru"
- compatible: CRU should be "rockchip,rk3399-cru"
- reg: physical base address of the controller and length of memory mapped
  region.
- #clock-cells: should be 1.
- #reset-cells: should be 1.

Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
preprocessor macros in the dt-bindings/clock/rk3399-cru.h headers and can be
used in device tree sources. Similar macros exist for the reset sources in
these files.

External clocks:

There are several clocks that are generated outside the SoC. It is expected
that they are defined using standard clock bindings with following
clock-output-names:
 - "xin24m" - crystal input - required,
 - "xin32k" - rtc clock - optional,
 - "clkin_gmac" - external GMAC clock - optional,
 - "clkin_i2s" - external I2S clock - optional,
 - "pclkin_cif" - external ISP clock - optional,
 - "clk_usbphy0_480m" - output clock of the pll in the usbphy0
 - "clk_usbphy1_480m" - output clock of the pll in the usbphy1

Example: Clock controller node:

	pmucru: pmu-clock-controller@ff750000 {
		compatible = "rockchip,rk3399-pmucru";
		reg = <0x0 0xff750000 0x0 0x1000>;
		#clock-cells = <1>;
		#reset-cells = <1>;
	};

	cru: clock-controller@ff760000 {
		compatible = "rockchip,rk3399-cru";
		reg = <0x0 0xff760000 0x0 0x1000>;
		#clock-cells = <1>;
		#reset-cells = <1>;
	};

Example: UART controller node that consumes the clock generated by the clock
  controller:

	uart0: serial@ff1a0000 {
		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
		reg = <0x0 0xff180000 0x0 0x100>;
		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
		clock-names = "baudclk", "apb_pclk";
		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
		reg-shift = <2>;
		reg-io-width = <4>;
	};
+1 −0
Original line number Diff line number Diff line
@@ -15,3 +15,4 @@ obj-y += clk-rk3188.o
obj-y	+= clk-rk3228.o
obj-y	+= clk-rk3288.o
obj-y	+= clk-rk3368.o
obj-y	+= clk-rk3399.o
+18 −11
Original line number Diff line number Diff line
@@ -158,11 +158,15 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,

		writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask,
					      reg_data->div_core_shift) |
		       HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
		       HIWORD_UPDATE(reg_data->mux_core_alt,
				     reg_data->mux_core_mask,
				     reg_data->mux_core_shift),
		       cpuclk->reg_base + reg_data->core_reg);
	} else {
		/* select alternate parent */
		writel(HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
		writel(HIWORD_UPDATE(reg_data->mux_core_alt,
				     reg_data->mux_core_mask,
				     reg_data->mux_core_shift),
		       cpuclk->reg_base + reg_data->core_reg);
	}

@@ -198,7 +202,9 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,

	writel(HIWORD_UPDATE(0, reg_data->div_core_mask,
				reg_data->div_core_shift) |
	       HIWORD_UPDATE(0, 1, reg_data->mux_core_shift),
	       HIWORD_UPDATE(reg_data->mux_core_main,
				reg_data->mux_core_mask,
				reg_data->mux_core_shift),
	       cpuclk->reg_base + reg_data->core_reg);

	if (ndata->old_rate > ndata->new_rate)
@@ -252,7 +258,7 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.parent_names = &parent_names[0];
	init.parent_names = &parent_names[reg_data->mux_core_main];
	init.num_parents = 1;
	init.ops = &rockchip_cpuclk_ops;

@@ -270,10 +276,10 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
	cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb;
	cpuclk->hw.init = &init;

	cpuclk->alt_parent = __clk_lookup(parent_names[1]);
	cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]);
	if (!cpuclk->alt_parent) {
		pr_err("%s: could not lookup alternate parent\n",
		       __func__);
		pr_err("%s: could not lookup alternate parent: (%d)\n",
		       __func__, reg_data->mux_core_alt);
		ret = -EINVAL;
		goto free_cpuclk;
	}
@@ -285,10 +291,11 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
		goto free_cpuclk;
	}

	clk = __clk_lookup(parent_names[0]);
	clk = __clk_lookup(parent_names[reg_data->mux_core_main]);
	if (!clk) {
		pr_err("%s: could not lookup parent clock %s\n",
		       __func__, parent_names[0]);
		pr_err("%s: could not lookup parent clock: (%d) %s\n",
		       __func__, reg_data->mux_core_main,
		       parent_names[reg_data->mux_core_main]);
		ret = -EINVAL;
		goto free_alt_parent;
	}
+287 −14
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ struct rockchip_clk_pll {
	const struct rockchip_pll_rate_table *rate_table;
	unsigned int		rate_count;
	spinlock_t		*lock;

	struct rockchip_clk_provider *ctx;
};

#define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
@@ -90,7 +92,7 @@ static long rockchip_pll_round_rate(struct clk_hw *hw,
 */
static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
{
	struct regmap *grf = rockchip_clk_get_grf();
	struct regmap *grf = rockchip_clk_get_grf(pll->ctx);
	unsigned int val;
	int delay = 24000000, ret;

@@ -251,7 +253,7 @@ static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	const struct rockchip_pll_rate_table *rate;
	unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate);
	struct regmap *grf = rockchip_clk_get_grf();
	struct regmap *grf = rockchip_clk_get_grf(pll->ctx);

	if (IS_ERR(grf)) {
		pr_debug("%s: grf regmap not available, aborting rate change\n",
@@ -490,7 +492,7 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	const struct rockchip_pll_rate_table *rate;
	unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
	struct regmap *grf = rockchip_clk_get_grf();
	struct regmap *grf = rockchip_clk_get_grf(pll->ctx);

	if (IS_ERR(grf)) {
		pr_debug("%s: grf regmap not available, aborting rate change\n",
@@ -563,7 +565,7 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
		 rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
	if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf
						     || rate->nb != cur.nb) {
		struct regmap *grf = rockchip_clk_get_grf();
		struct regmap *grf = rockchip_clk_get_grf(pll->ctx);

		if (IS_ERR(grf))
			return;
@@ -591,16 +593,278 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = {
	.init = rockchip_rk3066_pll_init,
};

/**
 * PLL used in RK3399
 */

#define RK3399_PLLCON(i)			(i * 0x4)
#define RK3399_PLLCON0_FBDIV_MASK		0xfff
#define RK3399_PLLCON0_FBDIV_SHIFT		0
#define RK3399_PLLCON1_REFDIV_MASK		0x3f
#define RK3399_PLLCON1_REFDIV_SHIFT		0
#define RK3399_PLLCON1_POSTDIV1_MASK		0x7
#define RK3399_PLLCON1_POSTDIV1_SHIFT		8
#define RK3399_PLLCON1_POSTDIV2_MASK		0x7
#define RK3399_PLLCON1_POSTDIV2_SHIFT		12
#define RK3399_PLLCON2_FRAC_MASK		0xffffff
#define RK3399_PLLCON2_FRAC_SHIFT		0
#define RK3399_PLLCON2_LOCK_STATUS		BIT(31)
#define RK3399_PLLCON3_PWRDOWN			BIT(0)
#define RK3399_PLLCON3_DSMPD_MASK		0x1
#define RK3399_PLLCON3_DSMPD_SHIFT		3

static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)
{
	u32 pllcon;
	int delay = 24000000;

	/* poll check the lock status in rk3399 xPLLCON2 */
	while (delay > 0) {
		pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
		if (pllcon & RK3399_PLLCON2_LOCK_STATUS)
			return 0;

		delay--;
	}

	pr_err("%s: timeout waiting for pll to lock\n", __func__);
	return -ETIMEDOUT;
}

static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,
					struct rockchip_pll_rate_table *rate)
{
	u32 pllcon;

	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0));
	rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT)
				& RK3399_PLLCON0_FBDIV_MASK);

	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1));
	rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT)
				& RK3399_PLLCON1_REFDIV_MASK);
	rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT)
				& RK3399_PLLCON1_POSTDIV1_MASK);
	rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT)
				& RK3399_PLLCON1_POSTDIV2_MASK);

	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
	rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT)
				& RK3399_PLLCON2_FRAC_MASK);

	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3));
	rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT)
				& RK3399_PLLCON3_DSMPD_MASK);
}

static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw,
						     unsigned long prate)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	struct rockchip_pll_rate_table cur;
	u64 rate64 = prate;

	rockchip_rk3399_pll_get_params(pll, &cur);

	rate64 *= cur.fbdiv;
	do_div(rate64, cur.refdiv);

	if (cur.dsmpd == 0) {
		/* fractional mode */
		u64 frac_rate64 = prate * cur.frac;

		do_div(frac_rate64, cur.refdiv);
		rate64 += frac_rate64 >> 24;
	}

	do_div(rate64, cur.postdiv1);
	do_div(rate64, cur.postdiv2);

	return (unsigned long)rate64;
}

static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
				const struct rockchip_pll_rate_table *rate)
{
	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
	struct clk_mux *pll_mux = &pll->pll_mux;
	struct rockchip_pll_rate_table cur;
	u32 pllcon;
	int rate_change_remuxed = 0;
	int cur_parent;
	int ret;

	pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
		__func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
		rate->postdiv2, rate->dsmpd, rate->frac);

	rockchip_rk3399_pll_get_params(pll, &cur);
	cur.rate = 0;

	cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
	if (cur_parent == PLL_MODE_NORM) {
		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
		rate_change_remuxed = 1;
	}

	/* update pll values */
	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,
						  RK3399_PLLCON0_FBDIV_SHIFT),
		       pll->reg_base + RK3399_PLLCON(0));

	writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK,
						   RK3399_PLLCON1_REFDIV_SHIFT) |
		       HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK,
						     RK3399_PLLCON1_POSTDIV1_SHIFT) |
		       HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK,
						     RK3399_PLLCON1_POSTDIV2_SHIFT),
		       pll->reg_base + RK3399_PLLCON(1));

	/* xPLL CON2 is not HIWORD_MASK */
	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
	pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT);
	pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT;
	writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2));

	writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK,
					    RK3399_PLLCON3_DSMPD_SHIFT),
		       pll->reg_base + RK3399_PLLCON(3));

	/* wait for the pll to lock */
	ret = rockchip_rk3399_pll_wait_lock(pll);
	if (ret) {
		pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
			__func__);
		rockchip_rk3399_pll_set_params(pll, &cur);
	}

	if (rate_change_remuxed)
		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);

	return ret;
}

static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate,
					unsigned long prate)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	const struct rockchip_pll_rate_table *rate;
	unsigned long old_rate = rockchip_rk3399_pll_recalc_rate(hw, prate);

	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
		 __func__, __clk_get_name(hw->clk), old_rate, drate, prate);

	/* Get required rate settings from table */
	rate = rockchip_get_pll_settings(pll, drate);
	if (!rate) {
		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
			drate, __clk_get_name(hw->clk));
		return -EINVAL;
	}

	return rockchip_rk3399_pll_set_params(pll, rate);
}

static int rockchip_rk3399_pll_enable(struct clk_hw *hw)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);

	writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0),
	       pll->reg_base + RK3399_PLLCON(3));

	return 0;
}

static void rockchip_rk3399_pll_disable(struct clk_hw *hw)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);

	writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,
			     RK3399_PLLCON3_PWRDOWN, 0),
	       pll->reg_base + RK3399_PLLCON(3));
}

static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3));

	return !(pllcon & RK3399_PLLCON3_PWRDOWN);
}

static void rockchip_rk3399_pll_init(struct clk_hw *hw)
{
	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
	const struct rockchip_pll_rate_table *rate;
	struct rockchip_pll_rate_table cur;
	unsigned long drate;

	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
		return;

	drate = clk_hw_get_rate(hw);
	rate = rockchip_get_pll_settings(pll, drate);

	/* when no rate setting for the current rate, rely on clk_set_rate */
	if (!rate)
		return;

	rockchip_rk3399_pll_get_params(pll, &cur);

	pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),
		 drate);
	pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
		 cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
		 cur.dsmpd, cur.frac);
	pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
		 rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
		 rate->dsmpd, rate->frac);

	if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
		rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
		rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
		struct clk *parent = clk_get_parent(hw->clk);

		if (!parent) {
			pr_warn("%s: parent of %s not available\n",
				__func__, __clk_get_name(hw->clk));
			return;
		}

		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
			 __func__, __clk_get_name(hw->clk));
		rockchip_rk3399_pll_set_params(pll, rate);
	}
}

static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = {
	.recalc_rate = rockchip_rk3399_pll_recalc_rate,
	.enable = rockchip_rk3399_pll_enable,
	.disable = rockchip_rk3399_pll_disable,
	.is_enabled = rockchip_rk3399_pll_is_enabled,
};

static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
	.recalc_rate = rockchip_rk3399_pll_recalc_rate,
	.round_rate = rockchip_pll_round_rate,
	.set_rate = rockchip_rk3399_pll_set_rate,
	.enable = rockchip_rk3399_pll_enable,
	.disable = rockchip_rk3399_pll_disable,
	.is_enabled = rockchip_rk3399_pll_is_enabled,
	.init = rockchip_rk3399_pll_init,
};

/*
 * Common registering of pll clocks
 */

struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
		enum rockchip_pll_type pll_type,
		const char *name, const char *const *parent_names,
		u8 num_parents, void __iomem *base, int con_offset,
		int grf_lock_offset, int lock_shift, int mode_offset,
		int mode_shift, struct rockchip_pll_rate_table *rate_table,
		u8 clk_pll_flags, spinlock_t *lock)
		u8 num_parents, int con_offset, int grf_lock_offset,
		int lock_shift, int mode_offset, int mode_shift,
		struct rockchip_pll_rate_table *rate_table,
		u8 clk_pll_flags)
{
	const char *pll_parents[3];
	struct clk_init_data init;
@@ -624,14 +888,16 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
	/* create the mux on top of the real pll */
	pll->pll_mux_ops = &clk_mux_ops;
	pll_mux = &pll->pll_mux;
	pll_mux->reg = base + mode_offset;
	pll_mux->reg = ctx->reg_base + mode_offset;
	pll_mux->shift = mode_shift;
	pll_mux->mask = PLL_MODE_MASK;
	pll_mux->flags = 0;
	pll_mux->lock = lock;
	pll_mux->lock = &ctx->lock;
	pll_mux->hw.init = &init;

	if (pll_type == pll_rk3036 || pll_type == pll_rk3066)
	if (pll_type == pll_rk3036 ||
	    pll_type == pll_rk3066 ||
	    pll_type == pll_rk3399)
		pll_mux->flags |= CLK_MUX_HIWORD_MASK;

	/* the actual muxing is xin24m, pll-output, xin32k */
@@ -688,6 +954,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
		else
			init.ops = &rockchip_rk3066_pll_clk_ops;
		break;
	case pll_rk3399:
		if (!pll->rate_table)
			init.ops = &rockchip_rk3399_pll_clk_norate_ops;
		else
			init.ops = &rockchip_rk3399_pll_clk_ops;
		break;
	default:
		pr_warn("%s: Unknown pll type for pll clk %s\n",
			__func__, name);
@@ -695,11 +967,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,

	pll->hw.init = &init;
	pll->type = pll_type;
	pll->reg_base = base + con_offset;
	pll->reg_base = ctx->reg_base + con_offset;
	pll->lock_offset = grf_lock_offset;
	pll->lock_shift = lock_shift;
	pll->flags = clk_pll_flags;
	pll->lock = lock;
	pll->lock = &ctx->lock;
	pll->ctx = ctx;

	pll_clk = clk_register(NULL, &pll->hw);
	if (IS_ERR(pll_clk)) {
+16 −5
Original line number Diff line number Diff line
@@ -113,7 +113,10 @@ static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
	.core_reg = RK2928_CLKSEL_CON(0),
	.div_core_shift = 0,
	.div_core_mask = 0x1f,
	.mux_core_alt = 1,
	.mux_core_main = 0,
	.mux_core_shift = 7,
	.mux_core_mask = 0x1,
};

PNAME(mux_pll_p)		= { "xin24m", "xin24m" };
@@ -437,6 +440,7 @@ static const char *const rk3036_critical_clocks[] __initconst = {

static void __init rk3036_clk_init(struct device_node *np)
{
	struct rockchip_clk_provider *ctx;
	void __iomem *reg_base;
	struct clk *clk;

@@ -446,22 +450,27 @@ static void __init rk3036_clk_init(struct device_node *np)
		return;
	}

	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
	if (IS_ERR(ctx)) {
		pr_err("%s: rockchip clk init failed\n", __func__);
		iounmap(reg_base);
		return;
	}

	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
	if (IS_ERR(clk))
		pr_warn("%s: could not register clock usb480m: %ld\n",
			__func__, PTR_ERR(clk));

	rockchip_clk_register_plls(rk3036_pll_clks,
	rockchip_clk_register_plls(ctx, rk3036_pll_clks,
				   ARRAY_SIZE(rk3036_pll_clks),
				   RK3036_GRF_SOC_STATUS0);
	rockchip_clk_register_branches(rk3036_clk_branches,
	rockchip_clk_register_branches(ctx, rk3036_clk_branches,
				  ARRAY_SIZE(rk3036_clk_branches));
	rockchip_clk_protect_critical(rk3036_critical_clocks,
				      ARRAY_SIZE(rk3036_critical_clocks));

	rockchip_clk_register_armclk(ARMCLK, "armclk",
	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
			ARRAY_SIZE(rk3036_cpuclk_rates));
@@ -469,6 +478,8 @@ static void __init rk3036_clk_init(struct device_node *np)
	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
				  ROCKCHIP_SOFTRST_HIWORD_MASK);

	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
	rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL);

	rockchip_clk_of_add_provider(np, ctx);
}
CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
Loading