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

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

Merge tag 'v4.11-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:

A new clock-type for the 1-2 muxes per soc that are for whatever reason
controlled through the General Register Files, support for the rk3328
clock-controller (including a new pll-type) and the usual clock ids and
some fixes.

* tag 'v4.11-rockchip-clk1' of git://git.kernel.org/pub/scm/linux/kernel/git/mmind/linux-rockchip:
  dt-bindings: clk: add rockchip,grf property for RK3399
  clk: rockchip: use clock ids for memory controller parts on rk3066/rk3188
  clk: rockchip: use rk3288 isp_in clock ids
  clk: rockchip: add clock ids for memory controller parts on rk3066/rk3188
  clk: rockchip: add rk3288 isp_in clock ids
  clk: rockchip: Remove useless init of "grf" to -EPROBE_DEFER
  clk: rockchip: add clock controller for rk3328
  dt-bindings: add bindings for rk3328 clock controller
  clk: rockchip: add dt-binding header for rk3328
  clk: rockchip: add new pll-type for rk3328
  clk: rockchip: describe aclk_vcodec using the new muxgrf type on rk3288
  clk: rockchip: add a clock-type for muxes based in the grf
parents d07ed23f 1a0abcd6
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
* Rockchip RK3328 Clock and Reset Unit

The RK3328 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,rk3328-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/rk3328-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,
 - "clkin_i2s" - external I2S clock - optional,
 - "gmac_clkin" - external GMAC clock - optional
 - "phy_50m_out" - output clock of the pll in the mac phy

Example: Clock controller node:

	cru: clock-controller@ff440000 {
		compatible = "rockchip,rk3328-cru";
		reg = <0x0 0xff440000 0x0 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@ff120000 {
		compatible = "snps,dw-apb-uart";
		reg = <0xff120000 0x100>;
		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
		reg-shift = <2>;
		reg-io-width = <4>;
		clocks = <&cru SCLK_UART0>;
	};
+6 −0
Original line number Diff line number Diff line
@@ -13,6 +13,12 @@ Required Properties:
- #clock-cells: should be 1.
- #reset-cells: should be 1.

Optional Properties:

- rockchip,grf: phandle to the syscon managing the "general register files".
  It is used for GRF muxes, if missing any muxes present in the GRF will not
  be available.

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
+2 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ obj-y += clk-pll.o
obj-y	+= clk-cpu.o
obj-y	+= clk-inverter.o
obj-y	+= clk-mmc-phase.o
obj-y	+= clk-muxgrf.o
obj-y	+= clk-ddr.o
obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o

@@ -16,5 +17,6 @@ obj-y += clk-rk3036.o
obj-y	+= clk-rk3188.o
obj-y	+= clk-rk3228.o
obj-y	+= clk-rk3288.o
obj-y	+= clk-rk3328.o
obj-y	+= clk-rk3368.o
obj-y	+= clk-rk3399.o
+102 −0
Original line number Diff line number Diff line
/*
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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/slab.h>
#include <linux/bitops.h>
#include <linux/regmap.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include "clk.h"

struct rockchip_muxgrf_clock {
	struct clk_hw		hw;
	struct regmap		*regmap;
	u32			reg;
	u32			shift;
	u32			width;
	int			flags;
};

#define to_muxgrf_clock(_hw) container_of(_hw, struct rockchip_muxgrf_clock, hw)

static u8 rockchip_muxgrf_get_parent(struct clk_hw *hw)
{
	struct rockchip_muxgrf_clock *mux = to_muxgrf_clock(hw);
	unsigned int mask = GENMASK(mux->width - 1, 0);
	unsigned int val;

	regmap_read(mux->regmap, mux->reg, &val);

	val >>= mux->shift;
	val &= mask;

	return val;
}

static int rockchip_muxgrf_set_parent(struct clk_hw *hw, u8 index)
{
	struct rockchip_muxgrf_clock *mux = to_muxgrf_clock(hw);
	unsigned int mask = GENMASK(mux->width + mux->shift - 1, mux->shift);
	unsigned int val;

	val = index;
	val <<= mux->shift;

	if (mux->flags & CLK_MUX_HIWORD_MASK)
		return regmap_write(mux->regmap, mux->reg, val | (mask << 16));
	else
		return regmap_update_bits(mux->regmap, mux->reg, mask, val);
}

static const struct clk_ops rockchip_muxgrf_clk_ops = {
	.get_parent = rockchip_muxgrf_get_parent,
	.set_parent = rockchip_muxgrf_set_parent,
	.determine_rate = __clk_mux_determine_rate,
};

struct clk *rockchip_clk_register_muxgrf(const char *name,
				const char *const *parent_names, u8 num_parents,
				int flags, struct regmap *regmap, int reg,
				int shift, int width, int mux_flags)
{
	struct rockchip_muxgrf_clock *muxgrf_clock;
	struct clk_init_data init;
	struct clk *clk;

	if (IS_ERR(regmap)) {
		pr_err("%s: regmap not available\n", __func__);
		return ERR_PTR(-ENOTSUPP);
	}

	muxgrf_clock = kmalloc(sizeof(*muxgrf_clock), GFP_KERNEL);
	if (!muxgrf_clock)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.flags = flags;
	init.num_parents = num_parents;
	init.parent_names = parent_names;
	init.ops = &rockchip_muxgrf_clk_ops;

	muxgrf_clock->hw.init = &init;
	muxgrf_clock->regmap = regmap;
	muxgrf_clock->reg = reg;
	muxgrf_clock->shift = shift;
	muxgrf_clock->width = width;
	muxgrf_clock->flags = mux_flags;

	clk = clk_register(NULL, &muxgrf_clock->hw);
	if (IS_ERR(clk))
		kfree(muxgrf_clock);

	return clk;
}
+13 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#define PLL_MODE_SLOW		0x0
#define PLL_MODE_NORM		0x1
#define PLL_MODE_DEEP		0x2
#define PLL_RK3328_MODE_MASK	0x1

struct rockchip_clk_pll {
	struct clk_hw		hw;
@@ -848,7 +849,8 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
	struct clk *pll_clk, *mux_clk;
	char pll_name[20];

	if (num_parents != 2) {
	if ((pll_type != pll_rk3328 && num_parents != 2) ||
	    (pll_type == pll_rk3328 && num_parents != 1)) {
		pr_err("%s: needs two parent clocks\n", __func__);
		return ERR_PTR(-EINVAL);
	}
@@ -865,6 +867,9 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
	pll_mux = &pll->pll_mux;
	pll_mux->reg = ctx->reg_base + mode_offset;
	pll_mux->shift = mode_shift;
	if (pll_type == pll_rk3328)
		pll_mux->mask = PLL_RK3328_MODE_MASK;
	else
		pll_mux->mask = PLL_MODE_MASK;
	pll_mux->flags = 0;
	pll_mux->lock = &ctx->lock;
@@ -872,6 +877,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,

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

@@ -884,6 +890,9 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
	init.flags = CLK_SET_RATE_PARENT;
	init.ops = pll->pll_mux_ops;
	init.parent_names = pll_parents;
	if (pll_type == pll_rk3328)
		init.num_parents = 2;
	else
		init.num_parents = ARRAY_SIZE(pll_parents);

	mux_clk = clk_register(NULL, &pll_mux->hw);
@@ -918,6 +927,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,

	switch (pll_type) {
	case pll_rk3036:
	case pll_rk3328:
		if (!pll->rate_table || IS_ERR(ctx->grf))
			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
		else
Loading