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

Merge tag 'clk-renesas-for-v4.11-tag2' of...

Merge tag 'clk-renesas-for-v4.11-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into clk-next

Pull Renesas clk driver updates from Geert Uytterhoeven:

  - Use CLK_IS_CRITICAL to handle critical clocks,
  - Add Reset Control Support for R-Car Gen2 and Gen3, and RZ/G1,
  - Add IIC-DVFS clocks for R-Car H3 and M3-W,
  - Minor cleanups.

* tag 'clk-renesas-for-v4.11-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers:
  clk: renesas: r8a7796: Add IIC-DVFS clock
  clk: renesas: r8a7795: Add IIC-DVFS clock
  clk: renesas: cpg-mssr: Add support for reset control
  clk: renesas: cpg-mssr: Rename cpg_mssr_priv.mstp_lock
  clk: renesas: cpg-mssr: Document suitability for RZ/G1
  dt-bindings: clock: renesas: cpg-mssr: Document reset control support
  clk: renesas: mstp: Reformat cpg_mstp_clock_register() for git diff
  clk: renesas: mstp: Make INTC-SYS a critical clock
  clk: renesas: cpg-mssr: Migrate to CLK_IS_CRITICAL
parents e120c17a d963654e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -42,6 +42,10 @@ Required Properties:
	Domain bindings in
	Documentation/devicetree/bindings/power/power_domain.txt.

  - #reset-cells: Must be 1
      - The single reset specifier cell must be the module number, as defined
	in the datasheet.


Examples
--------
@@ -55,6 +59,7 @@ Examples
		clock-names = "extal", "extalr";
		#clock-cells = <2>;
		#power-domain-cells = <0>;
		#reset-cells = <1>;
	};


@@ -69,5 +74,6 @@ Examples
		dmas = <&dmac1 0x13>, <&dmac1 0x12>;
		dma-names = "tx", "rx";
		power-domains = <&cpg>;
		resets = <&cpg 310>;
		status = "disabled";
	};
+8 −3
Original line number Diff line number Diff line
@@ -141,9 +141,9 @@ static const struct clk_ops cpg_mstp_clock_ops = {
	.is_enabled = cpg_mstp_clock_is_enabled,
};

static struct clk * __init
cpg_mstp_clock_register(const char *name, const char *parent_name,
			unsigned int index, struct mstp_clock_group *group)
static struct clk * __init cpg_mstp_clock_register(const char *name,
	const char *parent_name, unsigned int index,
	struct mstp_clock_group *group)
{
	struct clk_init_data init;
	struct mstp_clock *clock;
@@ -158,6 +158,11 @@ cpg_mstp_clock_register(const char *name, const char *parent_name,
	init.name = name;
	init.ops = &cpg_mstp_clock_ops;
	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
	/* INTC-SYS is the module clock of the GIC, and must not be disabled */
	if (!strcmp(name, "intc-sys")) {
		pr_debug("MSTP %s setting CLK_IS_CRITICAL\n", name);
		init.flags |= CLK_IS_CRITICAL;
	}
	init.parent_names = &parent_name;
	init.num_parents = 1;

+1 −0
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
	DEF_MOD("can-if0",		 916,	R8A7795_CLK_S3D4),
	DEF_MOD("i2c6",			 918,	R8A7795_CLK_S3D2),
	DEF_MOD("i2c5",			 919,	R8A7795_CLK_S3D2),
	DEF_MOD("i2c-dvfs",		 926,	R8A7795_CLK_CP),
	DEF_MOD("i2c4",			 927,	R8A7795_CLK_S3D2),
	DEF_MOD("i2c3",			 928,	R8A7795_CLK_S3D2),
	DEF_MOD("i2c2",			 929,	R8A7795_CLK_S3D2),
+1 −0
Original line number Diff line number Diff line
@@ -192,6 +192,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
	DEF_MOD("can-if0",		 916,	R8A7796_CLK_S3D4),
	DEF_MOD("i2c6",			 918,	R8A7796_CLK_S0D6),
	DEF_MOD("i2c5",			 919,	R8A7796_CLK_S0D6),
	DEF_MOD("i2c-dvfs",		 926,	R8A7796_CLK_CP),
	DEF_MOD("i2c4",			 927,	R8A7796_CLK_S0D6),
	DEF_MOD("i2c3",			 928,	R8A7796_CLK_S0D6),
	DEF_MOD("i2c2",			 929,	R8A7796_CLK_S3D2),
+134 −15
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clk/renesas.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/mod_devicetable.h>
@@ -25,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/pm_clock.h>
#include <linux/pm_domain.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>

#include <dt-bindings/clock/renesas-cpg-mssr.h>
@@ -43,7 +45,7 @@
 * Module Standby and Software Reset register offets.
 *
 * If the registers exist, these are valid for SH-Mobile, R-Mobile,
 * R-Car Gen 2, and R-Car Gen 3.
 * R-Car Gen2, R-Car Gen3, and RZ/G1.
 * These are NOT valid for R-Car Gen1 and RZ/A1!
 */

@@ -96,18 +98,22 @@ static const u16 srcr[] = {
/**
 * Clock Pulse Generator / Module Standby and Software Reset Private Data
 *
 * @rcdev: Optional reset controller entity
 * @dev: CPG/MSSR device
 * @base: CPG/MSSR register block base address
 * @mstp_lock: protects writes to SMSTPCR
 * @rmw_lock: protects RMW register accesses
 * @clks: Array containing all Core and Module Clocks
 * @num_core_clks: Number of Core Clocks in clks[]
 * @num_mod_clks: Number of Module Clocks in clks[]
 * @last_dt_core_clk: ID of the last Core Clock exported to DT
 */
struct cpg_mssr_priv {
#ifdef CONFIG_RESET_CONTROLLER
	struct reset_controller_dev rcdev;
#endif
	struct device *dev;
	void __iomem *base;
	spinlock_t mstp_lock;
	spinlock_t rmw_lock;

	struct clk **clks;
	unsigned int num_core_clks;
@@ -144,7 +150,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)

	dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
		enable ? "ON" : "OFF");
	spin_lock_irqsave(&priv->mstp_lock, flags);
	spin_lock_irqsave(&priv->rmw_lock, flags);

	value = readl(priv->base + SMSTPCR(reg));
	if (enable)
@@ -153,7 +159,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
		value |= bitmask;
	writel(value, priv->base + SMSTPCR(reg));

	spin_unlock_irqrestore(&priv->mstp_lock, flags);
	spin_unlock_irqrestore(&priv->rmw_lock, flags);

	if (!enable)
		return 0;
@@ -346,17 +352,10 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
	init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
	for (i = 0; i < info->num_crit_mod_clks; i++)
		if (id == info->crit_mod_clks[i]) {
#ifdef CLK_ENABLE_HAND_OFF
			dev_dbg(dev, "MSTP %s setting CLK_ENABLE_HAND_OFF\n",
			dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
				mod->name);
			init.flags |= CLK_ENABLE_HAND_OFF;
			init.flags |= CLK_IS_CRITICAL;
			break;
#else
			dev_dbg(dev, "Ignoring MSTP %s to prevent disabling\n",
				mod->name);
			kfree(clock);
			return;
#endif
		}

	parent_name = __clk_get_name(parent);
@@ -501,6 +500,122 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
	return 0;
}

#ifdef CONFIG_RESET_CONTROLLER

#define rcdev_to_priv(x)	container_of(x, struct cpg_mssr_priv, rcdev)

static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
			  unsigned long id)
{
	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
	unsigned int reg = id / 32;
	unsigned int bit = id % 32;
	u32 bitmask = BIT(bit);
	unsigned long flags;
	u32 value;

	dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);

	/* Reset module */
	spin_lock_irqsave(&priv->rmw_lock, flags);
	value = readl(priv->base + SRCR(reg));
	value |= bitmask;
	writel(value, priv->base + SRCR(reg));
	spin_unlock_irqrestore(&priv->rmw_lock, flags);

	/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
	udelay(35);

	/* Release module from reset state */
	writel(bitmask, priv->base + SRSTCLR(reg));

	return 0;
}

static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
	unsigned int reg = id / 32;
	unsigned int bit = id % 32;
	u32 bitmask = BIT(bit);
	unsigned long flags;
	u32 value;

	dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);

	spin_lock_irqsave(&priv->rmw_lock, flags);
	value = readl(priv->base + SRCR(reg));
	value |= bitmask;
	writel(value, priv->base + SRCR(reg));
	spin_unlock_irqrestore(&priv->rmw_lock, flags);
	return 0;
}

static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
			     unsigned long id)
{
	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
	unsigned int reg = id / 32;
	unsigned int bit = id % 32;
	u32 bitmask = BIT(bit);

	dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit);

	writel(bitmask, priv->base + SRSTCLR(reg));
	return 0;
}

static int cpg_mssr_status(struct reset_controller_dev *rcdev,
			   unsigned long id)
{
	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
	unsigned int reg = id / 32;
	unsigned int bit = id % 32;
	u32 bitmask = BIT(bit);

	return !!(readl(priv->base + SRCR(reg)) & bitmask);
}

static const struct reset_control_ops cpg_mssr_reset_ops = {
	.reset = cpg_mssr_reset,
	.assert = cpg_mssr_assert,
	.deassert = cpg_mssr_deassert,
	.status = cpg_mssr_status,
};

static int cpg_mssr_reset_xlate(struct reset_controller_dev *rcdev,
				const struct of_phandle_args *reset_spec)
{
	struct cpg_mssr_priv *priv = rcdev_to_priv(rcdev);
	unsigned int unpacked = reset_spec->args[0];
	unsigned int idx = MOD_CLK_PACK(unpacked);

	if (unpacked % 100 > 31 || idx >= rcdev->nr_resets) {
		dev_err(priv->dev, "Invalid reset index %u\n", unpacked);
		return -EINVAL;
	}

	return idx;
}

static int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
{
	priv->rcdev.ops = &cpg_mssr_reset_ops;
	priv->rcdev.of_node = priv->dev->of_node;
	priv->rcdev.of_reset_n_cells = 1;
	priv->rcdev.of_xlate = cpg_mssr_reset_xlate;
	priv->rcdev.nr_resets = priv->num_mod_clks;
	return devm_reset_controller_register(priv->dev, &priv->rcdev);
}

#else /* !CONFIG_RESET_CONTROLLER */
static inline int cpg_mssr_reset_controller_register(struct cpg_mssr_priv *priv)
{
	return 0;
}
#endif /* !CONFIG_RESET_CONTROLLER */


static const struct of_device_id cpg_mssr_match[] = {
#ifdef CONFIG_ARCH_R8A7743
	{
@@ -557,7 +672,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
		return -ENOMEM;

	priv->dev = dev;
	spin_lock_init(&priv->mstp_lock);
	spin_lock_init(&priv->rmw_lock);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->base = devm_ioremap_resource(dev, res);
@@ -598,6 +713,10 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
	if (error)
		return error;

	error = cpg_mssr_reset_controller_register(priv);
	if (error)
		return error;

	return 0;
}