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

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

Merge tag 'v4.10-rockchip-clk2' of...

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

Pull rockchip clk driver updates from Heiko Stuebner:

A new clock controller for the rk1108 soc (single-core Cortex-A7+DSP),
a fix making sure the cpuclk rate is actually valid, before trying to
set it and a copy-paste fix for the rk3399's testclk.

* tag 'v4.10-rockchip-clk2' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
  clk: rockchip: add clock controller for rk1108
  dt-bindings: add documentation for rk1108 cru
  clk: rockchip: add dt-binding header for rk1108
  clk: rockchip: fix copy-paste error in rk3399 testclk
  clk: rockchip: validity should be checked prior to cpu clock rate change
parents 96893e10 e44dde27
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
* Rockchip RK1108 Clock and Reset Unit

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

Required Properties:

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

Optional Properties:

- rockchip,grf: phandle to the syscon managing the "general register files"
  If missing pll rates are not changeable, due to the missing pll lock status.

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/rk1108-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,
 - "ext_vip" - external VIP clock - optional
 - "ext_i2s" - external I2S clock - optional
 - "ext_gmac" - external GMAC clock - optional
 - "hdmiphy" - external clock input derived from HDMI PHY - optional
 - "usbphy" - external clock input derived from USB PHY - optional

Example: Clock controller node:

	cru: cru@20200000 {
		compatible = "rockchip,rk1108-cru";
		reg = <0x20200000 0x1000>;
		rockchip,grf = <&grf>;

		#clock-cells = <1>;
		#reset-cells = <1>;
	};

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

	uart0: serial@10230000 {
		compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
		reg = <0x10230000 0x100>;
		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
		reg-shift = <2>;
		reg-io-width = <4>;
		clocks = <&cru SCLK_UART0>;
	};
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ obj-y += clk-mmc-phase.o
obj-y	+= clk-ddr.o
obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o

obj-y	+= clk-rk1108.o
obj-y	+= clk-rk3036.o
obj-y	+= clk-rk3188.o
obj-y	+= clk-rk3228.o
+9 −0
Original line number Diff line number Diff line
@@ -124,9 +124,18 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
					   struct clk_notifier_data *ndata)
{
	const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
	const struct rockchip_cpuclk_rate_table *rate;
	unsigned long alt_prate, alt_div;
	unsigned long flags;

	/* check validity of the new rate */
	rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
	if (!rate) {
		pr_err("%s: Invalid rate : %lu for cpuclk\n",
		       __func__, ndata->new_rate);
		return -EINVAL;
	}

	alt_prate = clk_get_rate(cpuclk->alt_parent);

	spin_lock_irqsave(cpuclk->lock, flags);
+531 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
 * Author: Shawn Lin <shawn.lin@rock-chips.com>
 *         Andy Yan <andy.yan@rock-chips.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/syscore_ops.h>
#include <dt-bindings/clock/rk1108-cru.h>
#include "clk.h"

#define RK1108_GRF_SOC_STATUS0	0x480

enum rk1108_plls {
	apll, dpll, gpll,
};

static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
	{ /* sentinel */ },
};

#define RK1108_DIV_CORE_MASK		0xf
#define RK1108_DIV_CORE_SHIFT		4

#define RK1108_CLKSEL0(_core_peri_div)	\
	{				\
		.reg = RK1108_CLKSEL_CON(1),	\
		.val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
				RK1108_DIV_CORE_SHIFT)	\
	}

#define RK1108_CPUCLK_RATE(_prate, _core_peri_div)			\
	{								\
		.prate = _prate,					\
		.divs = {						\
			RK1108_CLKSEL0(_core_peri_div),		\
		},							\
	}

static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
	RK1108_CPUCLK_RATE(816000000, 4),
	RK1108_CPUCLK_RATE(600000000, 4),
	RK1108_CPUCLK_RATE(312000000, 4),
};

static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
	.core_reg = RK1108_CLKSEL_CON(0),
	.div_core_shift = 0,
	.div_core_mask = 0x1f,
	.mux_core_alt = 1,
	.mux_core_main = 0,
	.mux_core_shift = 8,
	.mux_core_mask = 0x1,
};

PNAME(mux_pll_p)		= { "xin24m", "xin24m"};
PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr", "apll_ddr" };
PNAME(mux_armclk_p)		= { "apll_core", "gpll_core", "dpll_core" };
PNAME(mux_usb480m_pre_p)	= { "usbphy", "xin24m" };
PNAME(mux_hdmiphy_phy_p)	= { "hdmiphy", "xin24m" };
PNAME(mux_dclk_hdmiphy_pre_p)	= { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" };
PNAME(mux_pll_src_4plls_p)	= { "dpll", "hdmiphy", "gpll", "usb480m" };
PNAME(mux_pll_src_3plls_p)	= { "apll", "gpll", "dpll" };
PNAME(mux_pll_src_2plls_p)	= { "dpll", "gpll" };
PNAME(mux_pll_src_apll_gpll_p)	= { "apll", "gpll" };
PNAME(mux_aclk_peri_src_p)	= { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
PNAME(mux_aclk_bus_src_p)	= { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
PNAME(mux_mmc_src_p)		= { "dpll", "gpll", "xin24m", "usb480m" };
PNAME(mux_pll_src_dpll_gpll_usb480m_p)	= { "dpll", "gpll", "usb480m" };
PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
PNAME(mux_uart2_p)		= { "uart2_src", "uart2_frac", "xin24m" };
PNAME(mux_sclk_macphy_p)	= { "sclk_macphy_pre", "ext_gmac" };
PNAME(mux_i2s0_pre_p)		= { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
PNAME(mux_i2s_out_p)		= { "i2s0_pre", "xin12m" };
PNAME(mux_i2s1_p)		= { "i2s1_src", "i2s1_frac", "xin12m" };
PNAME(mux_i2s2_p)		= { "i2s2_src", "i2s2_frac", "xin12m" };

static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
	[apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
		     RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
	[dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
		     RK1108_PLL_CON(11), 8, 31, 0, NULL),
	[gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
		     RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
};

#define MFLAGS CLK_MUX_HIWORD_MASK
#define DFLAGS CLK_DIVIDER_HIWORD_MASK
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK

static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);

static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);

static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);

static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
	MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);

static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
	MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);

static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
	MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);

static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
	MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
			RK1108_MISC_CON, 13, 2, MFLAGS),
	MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
			RK1108_MISC_CON, 15, 2, MFLAGS),
	/*
	 * Clock-Architecture Diagram 2
	 */

	/* PD_CORE */
	GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 1, GFLAGS),
	GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 0, GFLAGS),
	GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 2, GFLAGS),
	COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
			RK1108_CLKGATE_CON(0), 5, GFLAGS),
	COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
			RK1108_CLKGATE_CON(0), 4, GFLAGS),
	GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(11), 0, GFLAGS),
	GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(11), 1, GFLAGS),

	/* PD_RKVENC */

	/* PD_RKVDEC */

	/* PD_PMU_wrapper */
	COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
			RK1108_CLKGATE_CON(8), 12, GFLAGS),
	GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 0, GFLAGS),
	GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 1, GFLAGS),
	GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 2, GFLAGS),
	GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 3, GFLAGS),
	GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 4, GFLAGS),
	GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 5, GFLAGS),
	GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(10), 6, GFLAGS),
	COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(8), 15, GFLAGS),
	COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(8), 14, GFLAGS),
	GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(8), 13, GFLAGS),

	/*
	 * Clock-Architecture Diagram 4
	 */
	COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
			RK1108_CLKGATE_CON(6), 0, GFLAGS),
	GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(17), 0, GFLAGS),
	COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
			RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
			RK1108_CLKGATE_CON(7), 2, GFLAGS),
	COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
			RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
			RK1108_CLKGATE_CON(7), 3, GFLAGS),

	INVERTER(0, "pclk_vip", "ext_vip",
			RK1108_CLKSEL_CON(31), 8, IFLAGS),
	GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(7), 6, GFLAGS),
	GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(18), 10, GFLAGS),
	GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(6), 5, GFLAGS),
	GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(6), 4, GFLAGS),
	COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
			RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),

	/*
	 * Clock-Architecture Diagram 5
	 */

	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),

	COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
			RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(2), 0, GFLAGS),
	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(8), 0,
			RK1108_CLKGATE_CON(2), 1, GFLAGS,
			&rk1108_i2s0_fracmux),
	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
			RK1108_CLKGATE_CON(2), 2, GFLAGS),
	COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
			RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
			RK1108_CLKGATE_CON(2), 3, GFLAGS),

	COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
			RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(2), 4, GFLAGS),
	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
			RK2928_CLKSEL_CON(9), 0,
			RK2928_CLKGATE_CON(2), 5, GFLAGS,
			&rk1108_i2s1_fracmux),
	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
			RK1108_CLKGATE_CON(2), 6, GFLAGS),

	COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
			RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 8, GFLAGS),
	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(10), 0,
			RK1108_CLKGATE_CON(2), 9, GFLAGS,
			&rk1108_i2s2_fracmux),
	GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
			RK1108_CLKGATE_CON(2), 10, GFLAGS),

	/* PD_BUS */
	GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 0, GFLAGS),
	GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 1, GFLAGS),
	GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 2, GFLAGS),
	COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
			RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
	COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
			RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
			RK1108_CLKGATE_CON(1), 4, GFLAGS),
	COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
			RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
			RK1108_CLKGATE_CON(1), 5, GFLAGS),
	GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 6, GFLAGS),
	GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 7, GFLAGS),
	GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 8, GFLAGS),
	GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 9, GFLAGS),
	GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(1), 10, GFLAGS),
	GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 4, GFLAGS),

	COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 1, GFLAGS),
	COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 3, GFLAGS),
	COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 5, GFLAGS),

	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(16), 0,
			RK1108_CLKGATE_CON(3), 2, GFLAGS,
			&rk1108_uart0_fracmux),
	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(17), 0,
			RK1108_CLKGATE_CON(3), 4, GFLAGS,
			&rk1108_uart1_fracmux),
	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(18), 0,
			RK1108_CLKGATE_CON(3), 6, GFLAGS,
			&rk1108_uart2_fracmux),
	GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 10, GFLAGS),
	GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 11, GFLAGS),
	GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 12, GFLAGS),

	COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 7, GFLAGS),
	COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 8, GFLAGS),
	COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 9, GFLAGS),
	GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 0, GFLAGS),
	GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 1, GFLAGS),
	GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 2, GFLAGS),
	COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
			RK1108_CLKGATE_CON(3), 10, GFLAGS),
	GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 6, GFLAGS),
	GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 3, GFLAGS),
	GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 7, GFLAGS),
	GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 8, GFLAGS),
	GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(13), 9, GFLAGS),

	GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(14), 0, GFLAGS),

	GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
	     RK1108_CLKGATE_CON(12), 2, GFLAGS),
	GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(12), 3, GFLAGS),
	GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(12), 1, GFLAGS),

	/* PD_DDR */
	GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 8, GFLAGS),
	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 9, GFLAGS),
	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 10, GFLAGS),
	COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
			DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
			RK1108_CLKGATE_CON(10), 9, GFLAGS),
	GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(12), 4, GFLAGS),
	GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(12), 5, GFLAGS),
	GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(12), 6, GFLAGS),
	GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(0), 11, GFLAGS),

	/*
	 * Clock-Architecture Diagram 6
	 */

	/* PD_PERI */
	COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
			RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
			RK1108_CLKGATE_CON(4), 5, GFLAGS),
	GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(15), 13, GFLAGS),
	COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
			RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
			RK1108_CLKGATE_CON(4), 4, GFLAGS),
	GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(15), 12, GFLAGS),

	GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(4), 1, GFLAGS),
	GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
			RK1108_CLKGATE_CON(4), 2, GFLAGS),
	COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
			RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
			RK1108_CLKGATE_CON(15), 11, GFLAGS),

	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
			RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
			RK1108_CLKGATE_CON(5), 0, GFLAGS),

	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
			RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
			RK1108_CLKGATE_CON(5), 2, GFLAGS),
	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
			RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),

	COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
			RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
			RK1108_CLKGATE_CON(5), 1, GFLAGS),
	DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
			RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
	GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
	GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),

	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
			RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
			RK1108_CLKGATE_CON(5), 3, GFLAGS),
	GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),

	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
			RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
			RK1108_CLKGATE_CON(5), 4, GFLAGS),
	GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),

	COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
			RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
			RK1108_CLKGATE_CON(4), 10, GFLAGS),
	MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
			RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
	GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
	GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
	GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),

	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),

	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK1108_SDIO_CON0,  1),
	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK1108_SDIO_CON1,  1),

	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK1108_EMMC_CON0,  1),
	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK1108_EMMC_CON1,  1),
};

static const char *const rk1108_critical_clocks[] __initconst = {
	"aclk_core",
	"aclk_bus_src_gpll",
	"aclk_periph",
	"hclk_periph",
	"pclk_periph",
};

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

	reg_base = of_iomap(np, 0);
	if (!reg_base) {
		pr_err("%s: could not map cru region\n", __func__);
		return;
	}

	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;
	}

	rockchip_clk_register_plls(ctx, rk1108_pll_clks,
				   ARRAY_SIZE(rk1108_pll_clks),
				   RK1108_GRF_SOC_STATUS0);
	rockchip_clk_register_branches(ctx, rk1108_clk_branches,
				  ARRAY_SIZE(rk1108_clk_branches));
	rockchip_clk_protect_critical(rk1108_critical_clocks,
				      ARRAY_SIZE(rk1108_critical_clocks));

	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
			&rk1108_cpuclk_data, rk1108_cpuclk_rates,
			ARRAY_SIZE(rk1108_cpuclk_rates));

	rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
				  ROCKCHIP_SOFTRST_HIWORD_MASK);

	rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);

	rockchip_clk_of_add_provider(np, ctx);
}
CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
+2 −2
Original line number Diff line number Diff line
@@ -1383,8 +1383,8 @@ static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
	/* clk_test */
	/* clk_test_pre is controlled by CRU_MISC_CON[3] */
	COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
			RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
			RK3368_CLKGATE_CON(13), 11, GFLAGS),
			RK3399_CLKSEL_CON(58), 0, 5, DFLAGS,
			RK3399_CLKGATE_CON(13), 11, GFLAGS),

	/* ddrc */
	GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
Loading