Commit d646d812 authored by Stephen Boyd's avatar Stephen Boyd

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
...@@ -42,6 +42,10 @@ Required Properties: ...@@ -42,6 +42,10 @@ Required Properties:
Domain bindings in Domain bindings in
Documentation/devicetree/bindings/power/power_domain.txt. 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 Examples
-------- --------
...@@ -55,6 +59,7 @@ Examples ...@@ -55,6 +59,7 @@ Examples
clock-names = "extal", "extalr"; clock-names = "extal", "extalr";
#clock-cells = <2>; #clock-cells = <2>;
#power-domain-cells = <0>; #power-domain-cells = <0>;
#reset-cells = <1>;
}; };
...@@ -69,5 +74,6 @@ Examples ...@@ -69,5 +74,6 @@ Examples
dmas = <&dmac1 0x13>, <&dmac1 0x12>; dmas = <&dmac1 0x13>, <&dmac1 0x12>;
dma-names = "tx", "rx"; dma-names = "tx", "rx";
power-domains = <&cpg>; power-domains = <&cpg>;
resets = <&cpg 310>;
status = "disabled"; status = "disabled";
}; };
...@@ -141,9 +141,9 @@ static const struct clk_ops cpg_mstp_clock_ops = { ...@@ -141,9 +141,9 @@ static const struct clk_ops cpg_mstp_clock_ops = {
.is_enabled = cpg_mstp_clock_is_enabled, .is_enabled = cpg_mstp_clock_is_enabled,
}; };
static struct clk * __init static struct clk * __init cpg_mstp_clock_register(const char *name,
cpg_mstp_clock_register(const char *name, const char *parent_name, const char *parent_name, unsigned int index,
unsigned int index, struct mstp_clock_group *group) struct mstp_clock_group *group)
{ {
struct clk_init_data init; struct clk_init_data init;
struct mstp_clock *clock; struct mstp_clock *clock;
...@@ -158,6 +158,11 @@ cpg_mstp_clock_register(const char *name, const char *parent_name, ...@@ -158,6 +158,11 @@ cpg_mstp_clock_register(const char *name, const char *parent_name,
init.name = name; init.name = name;
init.ops = &cpg_mstp_clock_ops; init.ops = &cpg_mstp_clock_ops;
init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; 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.parent_names = &parent_name;
init.num_parents = 1; init.num_parents = 1;
......
...@@ -221,6 +221,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { ...@@ -221,6 +221,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
DEF_MOD("can-if0", 916, R8A7795_CLK_S3D4), DEF_MOD("can-if0", 916, R8A7795_CLK_S3D4),
DEF_MOD("i2c6", 918, R8A7795_CLK_S3D2), DEF_MOD("i2c6", 918, R8A7795_CLK_S3D2),
DEF_MOD("i2c5", 919, 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("i2c4", 927, R8A7795_CLK_S3D2),
DEF_MOD("i2c3", 928, R8A7795_CLK_S3D2), DEF_MOD("i2c3", 928, R8A7795_CLK_S3D2),
DEF_MOD("i2c2", 929, R8A7795_CLK_S3D2), DEF_MOD("i2c2", 929, R8A7795_CLK_S3D2),
......
...@@ -192,6 +192,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { ...@@ -192,6 +192,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
DEF_MOD("can-if0", 916, R8A7796_CLK_S3D4), DEF_MOD("can-if0", 916, R8A7796_CLK_S3D4),
DEF_MOD("i2c6", 918, R8A7796_CLK_S0D6), DEF_MOD("i2c6", 918, R8A7796_CLK_S0D6),
DEF_MOD("i2c5", 919, 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("i2c4", 927, R8A7796_CLK_S0D6),
DEF_MOD("i2c3", 928, R8A7796_CLK_S0D6), DEF_MOD("i2c3", 928, R8A7796_CLK_S0D6),
DEF_MOD("i2c2", 929, R8A7796_CLK_S3D2), DEF_MOD("i2c2", 929, R8A7796_CLK_S3D2),
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/clk/renesas.h> #include <linux/clk/renesas.h>
#include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm_clock.h> #include <linux/pm_clock.h>
#include <linux/pm_domain.h> #include <linux/pm_domain.h>
#include <linux/reset-controller.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <dt-bindings/clock/renesas-cpg-mssr.h> #include <dt-bindings/clock/renesas-cpg-mssr.h>
...@@ -43,7 +45,7 @@ ...@@ -43,7 +45,7 @@
* Module Standby and Software Reset register offets. * Module Standby and Software Reset register offets.
* *
* If the registers exist, these are valid for SH-Mobile, R-Mobile, * 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! * These are NOT valid for R-Car Gen1 and RZ/A1!
*/ */
...@@ -96,18 +98,22 @@ static const u16 srcr[] = { ...@@ -96,18 +98,22 @@ static const u16 srcr[] = {
/** /**
* Clock Pulse Generator / Module Standby and Software Reset Private Data * Clock Pulse Generator / Module Standby and Software Reset Private Data
* *
* @rcdev: Optional reset controller entity
* @dev: CPG/MSSR device * @dev: CPG/MSSR device
* @base: CPG/MSSR register block base address * @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 * @clks: Array containing all Core and Module Clocks
* @num_core_clks: Number of Core Clocks in clks[] * @num_core_clks: Number of Core Clocks in clks[]
* @num_mod_clks: Number of Module 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 * @last_dt_core_clk: ID of the last Core Clock exported to DT
*/ */
struct cpg_mssr_priv { struct cpg_mssr_priv {
#ifdef CONFIG_RESET_CONTROLLER
struct reset_controller_dev rcdev;
#endif
struct device *dev; struct device *dev;
void __iomem *base; void __iomem *base;
spinlock_t mstp_lock; spinlock_t rmw_lock;
struct clk **clks; struct clk **clks;
unsigned int num_core_clks; unsigned int num_core_clks;
...@@ -144,7 +150,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) ...@@ -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, dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
enable ? "ON" : "OFF"); enable ? "ON" : "OFF");
spin_lock_irqsave(&priv->mstp_lock, flags); spin_lock_irqsave(&priv->rmw_lock, flags);
value = readl(priv->base + SMSTPCR(reg)); value = readl(priv->base + SMSTPCR(reg));
if (enable) if (enable)
...@@ -153,7 +159,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) ...@@ -153,7 +159,7 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
value |= bitmask; value |= bitmask;
writel(value, priv->base + SMSTPCR(reg)); writel(value, priv->base + SMSTPCR(reg));
spin_unlock_irqrestore(&priv->mstp_lock, flags); spin_unlock_irqrestore(&priv->rmw_lock, flags);
if (!enable) if (!enable)
return 0; return 0;
...@@ -346,17 +352,10 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, ...@@ -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; init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
for (i = 0; i < info->num_crit_mod_clks; i++) for (i = 0; i < info->num_crit_mod_clks; i++)
if (id == info->crit_mod_clks[i]) { if (id == info->crit_mod_clks[i]) {
#ifdef CLK_ENABLE_HAND_OFF dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n",
dev_dbg(dev, "MSTP %s setting CLK_ENABLE_HAND_OFF\n",
mod->name); mod->name);
init.flags |= CLK_ENABLE_HAND_OFF; init.flags |= CLK_IS_CRITICAL;
break; break;
#else
dev_dbg(dev, "Ignoring MSTP %s to prevent disabling\n",
mod->name);
kfree(clock);
return;
#endif
} }
parent_name = __clk_get_name(parent); parent_name = __clk_get_name(parent);
...@@ -501,6 +500,122 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev, ...@@ -501,6 +500,122 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
return 0; 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[] = { static const struct of_device_id cpg_mssr_match[] = {
#ifdef CONFIG_ARCH_R8A7743 #ifdef CONFIG_ARCH_R8A7743
{ {
...@@ -557,7 +672,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) ...@@ -557,7 +672,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
priv->dev = dev; priv->dev = dev;
spin_lock_init(&priv->mstp_lock); spin_lock_init(&priv->rmw_lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res); priv->base = devm_ioremap_resource(dev, res);
...@@ -598,6 +713,10 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) ...@@ -598,6 +713,10 @@ static int __init cpg_mssr_probe(struct platform_device *pdev)
if (error) if (error)
return error; return error;
error = cpg_mssr_reset_controller_register(priv);
if (error)
return error;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment