clk: renesas: cpg-mssr: Add register pointers into struct cpg_mssr_priv

To support other register layouts in the future, add register pointers
of {control,status,reset,reset_clear}_regs into struct cpg_mssr_priv.
After that, we can remove unused macros like MSTPSR().  No behavioral
changes.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/1599810232-29035-3-git-send-email-yoshihiro.shimoda.uh@renesas.com
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
Yoshihiro Shimoda 2020-09-11 16:43:50 +09:00 committed by Geert Uytterhoeven
parent ffbf9cf3f9
commit 8b652aa8a1
1 changed files with 47 additions and 35 deletions

View File

@ -57,9 +57,6 @@ static const u16 mstpsr[] = {
0x9A0, 0x9A4, 0x9A8, 0x9AC, 0x9A0, 0x9A4, 0x9A8, 0x9AC,
}; };
#define MSTPSR(i) mstpsr[i]
/* /*
* System Module Stop Control Register offsets * System Module Stop Control Register offsets
*/ */
@ -69,8 +66,6 @@ static const u16 smstpcr[] = {
0x990, 0x994, 0x998, 0x99C, 0x990, 0x994, 0x998, 0x99C,
}; };
#define SMSTPCR(i) smstpcr[i]
/* /*
* Standby Control Register offsets (RZ/A) * Standby Control Register offsets (RZ/A)
* Base address is FRQCR register * Base address is FRQCR register
@ -81,8 +76,6 @@ static const u16 stbcr[] = {
0x424, 0x428, 0x42C, 0x424, 0x428, 0x42C,
}; };
#define STBCR(i) stbcr[i]
/* /*
* Software Reset Register offsets * Software Reset Register offsets
*/ */
@ -92,9 +85,6 @@ static const u16 srcr[] = {
0x920, 0x924, 0x928, 0x92C, 0x920, 0x924, 0x928, 0x92C,
}; };
#define SRCR(i) srcr[i]
/* Realtime Module Stop Control Register offsets */ /* Realtime Module Stop Control Register offsets */
#define RMSTPCR(i) (smstpcr[i] - 0x20) #define RMSTPCR(i) (smstpcr[i] - 0x20)
@ -102,8 +92,11 @@ static const u16 srcr[] = {
#define MMSTPCR(i) (smstpcr[i] + 0x20) #define MMSTPCR(i) (smstpcr[i] + 0x20)
/* Software Reset Clearing Register offsets */ /* Software Reset Clearing Register offsets */
#define SRSTCLR(i) (0x940 + (i) * 4)
static const u16 srstclr[] = {
0x940, 0x944, 0x948, 0x94C, 0x950, 0x954, 0x958, 0x95C,
0x960, 0x964, 0x968, 0x96C,
};
/** /**
* Clock Pulse Generator / Module Standby and Software Reset Private Data * Clock Pulse Generator / Module Standby and Software Reset Private Data
@ -118,6 +111,10 @@ static const u16 srcr[] = {
* @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
* @notifiers: Notifier chain to save/restore clock state for system resume * @notifiers: Notifier chain to save/restore clock state for system resume
* @status_regs: Pointer to status registers array
* @control_regs: Pointer to control registers array
* @reset_regs: Pointer to reset registers array
* @reset_clear_regs: Pointer to reset clearing registers array
* @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
* @smstpcr_saved[].val: Saved values of SMSTPCR[] * @smstpcr_saved[].val: Saved values of SMSTPCR[]
* @clks: Array containing all Core and Module Clocks * @clks: Array containing all Core and Module Clocks
@ -137,6 +134,10 @@ struct cpg_mssr_priv {
unsigned int last_dt_core_clk; unsigned int last_dt_core_clk;
struct raw_notifier_head notifiers; struct raw_notifier_head notifiers;
const u16 *status_regs;
const u16 *control_regs;
const u16 *reset_regs;
const u16 *reset_clear_regs;
struct { struct {
u32 mask; u32 mask;
u32 val; u32 val;
@ -178,23 +179,23 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
spin_lock_irqsave(&priv->rmw_lock, flags); spin_lock_irqsave(&priv->rmw_lock, flags);
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) { if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
value = readb(priv->base + STBCR(reg)); value = readb(priv->base + priv->control_regs[reg]);
if (enable) if (enable)
value &= ~bitmask; value &= ~bitmask;
else else
value |= bitmask; value |= bitmask;
writeb(value, priv->base + STBCR(reg)); writeb(value, priv->base + priv->control_regs[reg]);
/* dummy read to ensure write has completed */ /* dummy read to ensure write has completed */
readb(priv->base + STBCR(reg)); readb(priv->base + priv->control_regs[reg]);
barrier_data(priv->base + STBCR(reg)); barrier_data(priv->base + priv->control_regs[reg]);
} else { } else {
value = readl(priv->base + SMSTPCR(reg)); value = readl(priv->base + priv->control_regs[reg]);
if (enable) if (enable)
value &= ~bitmask; value &= ~bitmask;
else else
value |= bitmask; value |= bitmask;
writel(value, priv->base + SMSTPCR(reg)); writel(value, priv->base + priv->control_regs[reg]);
} }
spin_unlock_irqrestore(&priv->rmw_lock, flags); spin_unlock_irqrestore(&priv->rmw_lock, flags);
@ -203,14 +204,14 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
return 0; return 0;
for (i = 1000; i > 0; --i) { for (i = 1000; i > 0; --i) {
if (!(readl(priv->base + MSTPSR(reg)) & bitmask)) if (!(readl(priv->base + priv->status_regs[reg]) & bitmask))
break; break;
cpu_relax(); cpu_relax();
} }
if (!i) { if (!i) {
dev_err(dev, "Failed to enable SMSTP %p[%d]\n", dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
priv->base + SMSTPCR(reg), bit); priv->base + priv->control_regs[reg], bit);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -234,9 +235,9 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
u32 value; u32 value;
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
value = readb(priv->base + STBCR(clock->index / 32)); value = readb(priv->base + priv->control_regs[clock->index / 32]);
else else
value = readl(priv->base + MSTPSR(clock->index / 32)); value = readl(priv->base + priv->status_regs[clock->index / 32]);
return !(value & BIT(clock->index % 32)); return !(value & BIT(clock->index % 32));
} }
@ -578,13 +579,13 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev,
dev_dbg(priv->dev, "reset %u%02u\n", reg, bit); dev_dbg(priv->dev, "reset %u%02u\n", reg, bit);
/* Reset module */ /* Reset module */
writel(bitmask, priv->base + SRCR(reg)); writel(bitmask, priv->base + priv->reset_regs[reg]);
/* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */
udelay(35); udelay(35);
/* Release module from reset state */ /* Release module from reset state */
writel(bitmask, priv->base + SRSTCLR(reg)); writel(bitmask, priv->base + priv->reset_clear_regs[reg]);
return 0; return 0;
} }
@ -598,7 +599,7 @@ static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id)
dev_dbg(priv->dev, "assert %u%02u\n", reg, bit); dev_dbg(priv->dev, "assert %u%02u\n", reg, bit);
writel(bitmask, priv->base + SRCR(reg)); writel(bitmask, priv->base + priv->reset_regs[reg]);
return 0; return 0;
} }
@ -612,7 +613,7 @@ static int cpg_mssr_deassert(struct reset_controller_dev *rcdev,
dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit); dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit);
writel(bitmask, priv->base + SRSTCLR(reg)); writel(bitmask, priv->base + priv->reset_clear_regs[reg]);
return 0; return 0;
} }
@ -624,7 +625,7 @@ static int cpg_mssr_status(struct reset_controller_dev *rcdev,
unsigned int bit = id % 32; unsigned int bit = id % 32;
u32 bitmask = BIT(bit); u32 bitmask = BIT(bit);
return !!(readl(priv->base + SRCR(reg)) & bitmask); return !!(readl(priv->base + priv->reset_regs[reg]) & bitmask);
} }
static const struct reset_control_ops cpg_mssr_reset_ops = { static const struct reset_control_ops cpg_mssr_reset_ops = {
@ -827,8 +828,8 @@ static int cpg_mssr_suspend_noirq(struct device *dev)
if (priv->smstpcr_saved[reg].mask) if (priv->smstpcr_saved[reg].mask)
priv->smstpcr_saved[reg].val = priv->smstpcr_saved[reg].val =
priv->reg_layout == CLK_REG_LAYOUT_RZ_A ? priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
readb(priv->base + STBCR(reg)) : readb(priv->base + priv->control_regs[reg]) :
readl(priv->base + SMSTPCR(reg)); readl(priv->base + priv->control_regs[reg]);
} }
/* Save core clocks */ /* Save core clocks */
@ -857,22 +858,22 @@ static int cpg_mssr_resume_noirq(struct device *dev)
continue; continue;
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
oldval = readb(priv->base + STBCR(reg)); oldval = readb(priv->base + priv->control_regs[reg]);
else else
oldval = readl(priv->base + SMSTPCR(reg)); oldval = readl(priv->base + priv->control_regs[reg]);
newval = oldval & ~mask; newval = oldval & ~mask;
newval |= priv->smstpcr_saved[reg].val & mask; newval |= priv->smstpcr_saved[reg].val & mask;
if (newval == oldval) if (newval == oldval)
continue; continue;
if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) { if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
writeb(newval, priv->base + STBCR(reg)); writeb(newval, priv->base + priv->control_regs[reg]);
/* dummy read to ensure write has completed */ /* dummy read to ensure write has completed */
readb(priv->base + STBCR(reg)); readb(priv->base + priv->control_regs[reg]);
barrier_data(priv->base + STBCR(reg)); barrier_data(priv->base + priv->control_regs[reg]);
continue; continue;
} else } else
writel(newval, priv->base + SMSTPCR(reg)); writel(newval, priv->base + priv->control_regs[reg]);
/* Wait until enabled clocks are really enabled */ /* Wait until enabled clocks are really enabled */
mask &= ~priv->smstpcr_saved[reg].val; mask &= ~priv->smstpcr_saved[reg].val;
@ -880,7 +881,7 @@ static int cpg_mssr_resume_noirq(struct device *dev)
continue; continue;
for (i = 1000; i > 0; --i) { for (i = 1000; i > 0; --i) {
oldval = readl(priv->base + MSTPSR(reg)); oldval = readl(priv->base + priv->status_regs[reg]);
if (!(oldval & mask)) if (!(oldval & mask))
break; break;
cpu_relax(); cpu_relax();
@ -939,6 +940,17 @@ static int __init cpg_mssr_common_init(struct device *dev,
priv->last_dt_core_clk = info->last_dt_core_clk; priv->last_dt_core_clk = info->last_dt_core_clk;
RAW_INIT_NOTIFIER_HEAD(&priv->notifiers); RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);
priv->reg_layout = info->reg_layout; priv->reg_layout = info->reg_layout;
if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) {
priv->status_regs = mstpsr;
priv->control_regs = smstpcr;
priv->reset_regs = srcr;
priv->reset_clear_regs = srstclr;
} else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
priv->control_regs = stbcr;
} else {
error = -EINVAL;
goto out_err;
}
for (i = 0; i < nclks; i++) for (i = 0; i < nclks; i++)
priv->clks[i] = ERR_PTR(-ENOENT); priv->clks[i] = ERR_PTR(-ENOENT);