mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 00:21:59 +00:00
clk: renesas: Updates for v4.11 (take two)
- 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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYiw4ZAAoJEEgEtLw/Ve77TfgQAJexnyItLU6fs3X5gx6smoWQ rPYXw0tWWfYEkmHJbF/vcfgC+sh/6sMVIn4IS6HqDWd1HdOtJPYTX8CvwlsQx0Ry NrcoConiFlatEM5sNf6w0aAUkwrDxIjZMNNnShfZRkZL7s9Jlhs5UUUbBY4uYPGG kJ7qr6hUoxQQ1S3z8iz/ol++tp/A+8zN0J+zLDdxcV0SRjxh/NWOOtjno9tWXXqd 60eseC5FJNQOYV/6DXkpHsxNLsG6N2i7CVPC3SWxrijTQB1BDYAj/Pc3rD4u7Exo g2QTb8ywufWFi5ANhQX2oirewaiw6B2PoQyw7+7a/86OlTQVM7lfRb8hNnOJycqd X2YKBCNGeg4sysGURSYIDlzoq0ZDZnw7URc2+0HfeZXJjRCTmswpzRAv/wq4ILLK uAy5skI+XWKCuVk/w8lsWBo29hcu9Mm1lTsW739niJR4Kk9WQkK+JgF7x8FxzmLx 7W8Rpbiz1N1D8ajlJWo/FAMdfx0SqevLlQlhCNVjExl7szmOcsF8RPnx542oRfwe wgJLCmCc9msP6FdWWSXB5BLNgPbaCAOoPfzpn5xouOe2xj6V5Ctv5kBTLfTqs+5S 3SxsU08UZ4mxBeynjtuNwaX35KVs5Y1+FZQQD5MNxq8C2OvDx5ioWkH+YWFjOmgA 9zghcMX9FG1KNLWh+RUD =WluB -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
d646d812f3
@ -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";
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user