summaryrefslogtreecommitdiffstats
path: root/drivers/clk/renesas/rzg2l-cpg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/renesas/rzg2l-cpg.c')
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c91
1 files changed, 56 insertions, 35 deletions
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 764bd72cf059..3d2daa4ba2a4 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -1410,41 +1410,33 @@ fail:
#define rcdev_to_priv(x) container_of(x, struct rzg2l_cpg_priv, rcdev)
-static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev,
- unsigned long id)
-{
- struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
- const struct rzg2l_cpg_info *info = priv->info;
- unsigned int reg = info->resets[id].off;
- u32 dis = BIT(info->resets[id].bit);
- u32 we = dis << 16;
-
- dev_dbg(rcdev->dev, "reset id:%ld offset:0x%x\n", id, CLK_RST_R(reg));
-
- /* Reset module */
- writel(we, priv->base + CLK_RST_R(reg));
-
- /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
- udelay(35);
-
- /* Release module from reset state */
- writel(we | dis, priv->base + CLK_RST_R(reg));
-
- return 0;
-}
-
static int rzg2l_cpg_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
const struct rzg2l_cpg_info *info = priv->info;
unsigned int reg = info->resets[id].off;
- u32 value = BIT(info->resets[id].bit) << 16;
+ u32 mask = BIT(info->resets[id].bit);
+ s8 monbit = info->resets[id].monbit;
+ u32 value = mask << 16;
dev_dbg(rcdev->dev, "assert id:%ld offset:0x%x\n", id, CLK_RST_R(reg));
writel(value, priv->base + CLK_RST_R(reg));
- return 0;
+
+ if (info->has_clk_mon_regs) {
+ reg = CLK_MRST_R(reg);
+ } else if (monbit >= 0) {
+ reg = CPG_RST_MON;
+ mask = BIT(monbit);
+ } else {
+ /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
+ udelay(35);
+ return 0;
+ }
+
+ return readl_poll_timeout_atomic(priv->base + reg, value,
+ value & mask, 10, 200);
}
static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev,
@@ -1453,14 +1445,40 @@ static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev,
struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
const struct rzg2l_cpg_info *info = priv->info;
unsigned int reg = info->resets[id].off;
- u32 dis = BIT(info->resets[id].bit);
- u32 value = (dis << 16) | dis;
+ u32 mask = BIT(info->resets[id].bit);
+ s8 monbit = info->resets[id].monbit;
+ u32 value = (mask << 16) | mask;
dev_dbg(rcdev->dev, "deassert id:%ld offset:0x%x\n", id,
CLK_RST_R(reg));
writel(value, priv->base + CLK_RST_R(reg));
- return 0;
+
+ if (info->has_clk_mon_regs) {
+ reg = CLK_MRST_R(reg);
+ } else if (monbit >= 0) {
+ reg = CPG_RST_MON;
+ mask = BIT(monbit);
+ } else {
+ /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
+ udelay(35);
+ return 0;
+ }
+
+ return readl_poll_timeout_atomic(priv->base + reg, value,
+ !(value & mask), 10, 200);
+}
+
+static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = rzg2l_cpg_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return rzg2l_cpg_deassert(rcdev, id);
}
static int rzg2l_cpg_status(struct reset_controller_dev *rcdev,
@@ -1468,18 +1486,21 @@ static int rzg2l_cpg_status(struct reset_controller_dev *rcdev,
{
struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev);
const struct rzg2l_cpg_info *info = priv->info;
- unsigned int reg = info->resets[id].off;
- u32 bitmask = BIT(info->resets[id].bit);
s8 monbit = info->resets[id].monbit;
+ unsigned int reg;
+ u32 bitmask;
if (info->has_clk_mon_regs) {
- return !!(readl(priv->base + CLK_MRST_R(reg)) & bitmask);
+ reg = CLK_MRST_R(info->resets[id].off);
+ bitmask = BIT(info->resets[id].bit);
} else if (monbit >= 0) {
- u32 monbitmask = BIT(monbit);
-
- return !!(readl(priv->base + CPG_RST_MON) & monbitmask);
+ reg = CPG_RST_MON;
+ bitmask = BIT(monbit);
+ } else {
+ return -ENOTSUPP;
}
- return -ENOTSUPP;
+
+ return !!(readl(priv->base + reg) & bitmask);
}
static const struct reset_control_ops rzg2l_cpg_reset_ops = {