clk: renesas: Updates for v5.16
- Add TPU (PWM), and Z (Cortex-A76) clocks on R-Car V3U, - Add Ethernet clocks on RZ/G2L. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCYVbWUgAKCRCKwlD9ZEnx cOkVAP97PDGWxcrTdrtWVQnWDTIgRAgARrCgzGKjrVbrD/qNLgD7Bmqna9sYgQJR zGWoXMTi/4Ou7+3l+gIHBn5u3svIiQ8= =GnKU -----END PGP SIGNATURE----- Merge tag 'renesas-clk-for-v5.16-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into clk-renesas Pull Renesas clk driver updates from Geert Uytterhoeven: - Add TPU (PWM), and Z (Cortex-A76) clocks on Renesas R-Car V3U - Add Ethernet clocks on Renesas RZ/G2L * tag 'renesas-clk-for-v5.16-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers: clk: renesas: r8a779a0: Add Z0 and Z1 clock support clk: renesas: r9a07g044: Add GbEthernet clock/reset clk: renesas: rzg2l: Add support to handle coupled clocks clk: renesas: r9a07g044: Add ethernet clock sources clk: renesas: rzg2l: Add support to handle MUX clocks clk: renesas: r8a779a0: Add TPU clock clk: renesas: rzg2l: Fix clk status function clk: renesas: r9a07g044: Mark IA55_CLK and DMAC_ACLK critical
This commit is contained in:
commit
e974872eb3
@ -33,6 +33,7 @@ enum rcar_r8a779a0_clk_types {
|
||||
CLK_TYPE_R8A779A0_PLL1,
|
||||
CLK_TYPE_R8A779A0_PLL2X_3X, /* PLL[23][01] */
|
||||
CLK_TYPE_R8A779A0_PLL5,
|
||||
CLK_TYPE_R8A779A0_Z,
|
||||
CLK_TYPE_R8A779A0_SD,
|
||||
CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */
|
||||
CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */
|
||||
@ -84,6 +85,10 @@ enum clk_ids {
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \
|
||||
.offset = _offset)
|
||||
|
||||
#define DEF_Z(_name, _id, _parent, _div, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_Z, _parent, .div = _div, \
|
||||
.offset = _offset)
|
||||
|
||||
#define DEF_SD(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset)
|
||||
|
||||
@ -122,6 +127,8 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
||||
DEF_RATE(".oco", CLK_OCO, 32768),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
DEF_Z("z0", R8A779A0_CLK_Z0, CLK_PLL20, 2, 0),
|
||||
DEF_Z("z1", R8A779A0_CLK_Z1, CLK_PLL21, 2, 8),
|
||||
DEF_FIXED("zx", R8A779A0_CLK_ZX, CLK_PLL20_DIV2, 2, 1),
|
||||
DEF_FIXED("s1d1", R8A779A0_CLK_S1D1, CLK_S1, 1, 1),
|
||||
DEF_FIXED("s1d2", R8A779A0_CLK_S1D2, CLK_S1, 2, 1),
|
||||
@ -205,6 +212,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
|
||||
DEF_MOD("tmu2", 715, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("tmu3", 716, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("tmu4", 717, R8A779A0_CLK_S1D4),
|
||||
DEF_MOD("tpu0", 718, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1),
|
||||
DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1),
|
||||
@ -259,6 +267,153 @@ static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
|
||||
/*
|
||||
* Z0 Clock & Z1 Clock
|
||||
*/
|
||||
#define CPG_FRQCRB 0x00000804
|
||||
#define CPG_FRQCRB_KICK BIT(31)
|
||||
#define CPG_FRQCRC 0x00000808
|
||||
|
||||
struct cpg_z_clk {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
void __iomem *kick_reg;
|
||||
unsigned long max_rate; /* Maximum rate for normal mode */
|
||||
unsigned int fixed_div;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
#define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw)
|
||||
|
||||
static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int mult;
|
||||
u32 val;
|
||||
|
||||
val = readl(zclk->reg) & zclk->mask;
|
||||
mult = 32 - (val >> __ffs(zclk->mask));
|
||||
|
||||
return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult,
|
||||
32 * zclk->fixed_div);
|
||||
}
|
||||
|
||||
static int cpg_z_clk_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int min_mult, max_mult, mult;
|
||||
unsigned long rate, prate;
|
||||
|
||||
rate = min(req->rate, req->max_rate);
|
||||
if (rate <= zclk->max_rate) {
|
||||
/* Set parent rate to initial value for normal modes */
|
||||
prate = zclk->max_rate;
|
||||
} else {
|
||||
/* Set increased parent rate for boost modes */
|
||||
prate = rate;
|
||||
}
|
||||
req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||
prate * zclk->fixed_div);
|
||||
|
||||
prate = req->best_parent_rate / zclk->fixed_div;
|
||||
min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL);
|
||||
max_mult = min(div64_ul(req->max_rate * 32ULL, prate), 32ULL);
|
||||
if (max_mult < min_mult)
|
||||
return -EINVAL;
|
||||
|
||||
mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate);
|
||||
mult = clamp(mult, min_mult, max_mult);
|
||||
|
||||
req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cpg_z_clk *zclk = to_z_clk(hw);
|
||||
unsigned int mult;
|
||||
unsigned int i;
|
||||
|
||||
mult = DIV64_U64_ROUND_CLOSEST(rate * 32ULL * zclk->fixed_div,
|
||||
parent_rate);
|
||||
mult = clamp(mult, 1U, 32U);
|
||||
|
||||
if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
|
||||
return -EBUSY;
|
||||
|
||||
cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask));
|
||||
|
||||
/*
|
||||
* Set KICK bit in FRQCRB to update hardware setting and wait for
|
||||
* clock change completion.
|
||||
*/
|
||||
cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
|
||||
|
||||
/*
|
||||
* Note: There is no HW information about the worst case latency.
|
||||
*
|
||||
* Using experimental measurements, it seems that no more than
|
||||
* ~10 iterations are needed, independently of the CPU rate.
|
||||
* Since this value might be dependent on external xtal rate, pll1
|
||||
* rate or even the other emulation clocks rate, use 1000 as a
|
||||
* "super" safe value.
|
||||
*/
|
||||
for (i = 1000; i; i--) {
|
||||
if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
|
||||
return 0;
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_z_clk_ops = {
|
||||
.recalc_rate = cpg_z_clk_recalc_rate,
|
||||
.determine_rate = cpg_z_clk_determine_rate,
|
||||
.set_rate = cpg_z_clk_set_rate,
|
||||
};
|
||||
|
||||
static struct clk * __init cpg_z_clk_register(const char *name,
|
||||
const char *parent_name,
|
||||
void __iomem *reg,
|
||||
unsigned int div,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct clk_init_data init = {};
|
||||
struct cpg_z_clk *zclk;
|
||||
struct clk *clk;
|
||||
|
||||
zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
|
||||
if (!zclk)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cpg_z_clk_ops;
|
||||
init.flags = CLK_SET_RATE_PARENT;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
zclk->reg = reg + CPG_FRQCRC;
|
||||
zclk->kick_reg = reg + CPG_FRQCRB;
|
||||
zclk->hw.init = &init;
|
||||
zclk->mask = GENMASK(offset + 4, offset);
|
||||
zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */
|
||||
|
||||
clk = clk_register(NULL, &zclk->hw);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(zclk);
|
||||
return clk;
|
||||
}
|
||||
|
||||
zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) /
|
||||
zclk->fixed_div;
|
||||
return clk;
|
||||
}
|
||||
|
||||
static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base,
|
||||
@ -293,6 +448,10 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
|
||||
div = cpg_pll_config->pll5_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_Z:
|
||||
return cpg_z_clk_register(core->name, __clk_get_name(parent),
|
||||
base, core->div, core->offset);
|
||||
|
||||
case CLK_TYPE_R8A779A0_SD:
|
||||
return cpg_sd_clk_register(core->name, base, core->offset,
|
||||
__clk_get_name(parent), notifiers,
|
||||
|
@ -35,8 +35,10 @@ enum clk_ids {
|
||||
CLK_PLL3_DIV4,
|
||||
CLK_PLL4,
|
||||
CLK_PLL5,
|
||||
CLK_PLL5_DIV2,
|
||||
CLK_PLL5_FOUT3,
|
||||
CLK_PLL5_250,
|
||||
CLK_PLL6,
|
||||
CLK_PLL6_250,
|
||||
CLK_P1_DIV2,
|
||||
|
||||
/* Module Clocks */
|
||||
@ -53,6 +55,9 @@ static const struct clk_div_table dtable_1_32[] = {
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
/* Mux clock tables */
|
||||
static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
|
||||
|
||||
static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
@ -64,6 +69,11 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 133, 2),
|
||||
DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 133, 2),
|
||||
|
||||
DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1),
|
||||
DEF_FIXED(".pll5_fout3", CLK_PLL5_FOUT3, CLK_PLL5, 1, 6),
|
||||
|
||||
DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6),
|
||||
|
||||
DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
|
||||
DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16),
|
||||
DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20),
|
||||
@ -73,6 +83,9 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2),
|
||||
DEF_FIXED(".pll3_div4", CLK_PLL3_DIV4, CLK_PLL3, 1, 4),
|
||||
|
||||
DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2),
|
||||
DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
|
||||
|
||||
/* Core output clk */
|
||||
DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1),
|
||||
DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A,
|
||||
@ -84,6 +97,10 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2),
|
||||
DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2,
|
||||
DIVPL3A, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
|
||||
DEF_FIXED("M0", R9A07G044_CLK_M0, CLK_PLL3_DIV2_4, 1, 1),
|
||||
DEF_FIXED("ZT", R9A07G044_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1),
|
||||
DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2,
|
||||
sel_pll6_2, ARRAY_SIZE(sel_pll6_2), 0, CLK_MUX_HIWORD_MASK),
|
||||
};
|
||||
|
||||
static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
@ -121,6 +138,14 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
0x578, 2),
|
||||
DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1,
|
||||
0x578, 3),
|
||||
DEF_COUPLED("eth0_axi", R9A07G044_ETH0_CLK_AXI, R9A07G044_CLK_M0,
|
||||
0x57c, 0),
|
||||
DEF_COUPLED("eth0_chi", R9A07G044_ETH0_CLK_CHI, R9A07G044_CLK_ZT,
|
||||
0x57c, 0),
|
||||
DEF_COUPLED("eth1_axi", R9A07G044_ETH1_CLK_AXI, R9A07G044_CLK_M0,
|
||||
0x57c, 1),
|
||||
DEF_COUPLED("eth1_chi", R9A07G044_ETH1_CLK_CHI, R9A07G044_CLK_ZT,
|
||||
0x57c, 1),
|
||||
DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0,
|
||||
0x580, 0),
|
||||
DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0,
|
||||
@ -165,6 +190,8 @@ static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
DEF_RST(R9A07G044_USB_U2H1_HRESETN, 0x878, 1),
|
||||
DEF_RST(R9A07G044_USB_U2P_EXL_SYSRST, 0x878, 2),
|
||||
DEF_RST(R9A07G044_USB_PRESETN, 0x878, 3),
|
||||
DEF_RST(R9A07G044_ETH0_RST_HW_N, 0x87c, 0),
|
||||
DEF_RST(R9A07G044_ETH1_RST_HW_N, 0x87c, 1),
|
||||
DEF_RST(R9A07G044_I2C0_MRST, 0x880, 0),
|
||||
DEF_RST(R9A07G044_I2C1_MRST, 0x880, 1),
|
||||
DEF_RST(R9A07G044_I2C2_MRST, 0x880, 2),
|
||||
@ -186,6 +213,8 @@ static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
|
||||
static const unsigned int r9a07g044_crit_mod_clks[] __initconst = {
|
||||
MOD_CLK_BASE + R9A07G044_GIC600_GICCLK,
|
||||
MOD_CLK_BASE + R9A07G044_IA55_CLK,
|
||||
MOD_CLK_BASE + R9A07G044_DMAC_ACLK,
|
||||
};
|
||||
|
||||
const struct rzg2l_cpg_info r9a07g044_cpg_info = {
|
||||
|
@ -130,6 +130,26 @@ rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
|
||||
return clk_hw->clk;
|
||||
}
|
||||
|
||||
static struct clk * __init
|
||||
rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
|
||||
void __iomem *base,
|
||||
struct rzg2l_cpg_priv *priv)
|
||||
{
|
||||
const struct clk_hw *clk_hw;
|
||||
|
||||
clk_hw = devm_clk_hw_register_mux(priv->dev, core->name,
|
||||
core->parent_names, core->num_parents,
|
||||
core->flag,
|
||||
base + GET_REG_OFFSET(core->conf),
|
||||
GET_SHIFT(core->conf),
|
||||
GET_WIDTH(core->conf),
|
||||
core->mux_flags, &priv->rmw_lock);
|
||||
if (IS_ERR(clk_hw))
|
||||
return ERR_CAST(clk_hw);
|
||||
|
||||
return clk_hw->clk;
|
||||
}
|
||||
|
||||
struct pll_clk {
|
||||
struct clk_hw hw;
|
||||
unsigned int conf;
|
||||
@ -288,6 +308,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
|
||||
clk = rzg2l_cpg_div_clk_register(core, priv->clks,
|
||||
priv->base, priv);
|
||||
break;
|
||||
case CLK_TYPE_MUX:
|
||||
clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv);
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
@ -310,13 +333,17 @@ fail:
|
||||
* @hw: handle between common and hardware-specific interfaces
|
||||
* @off: register offset
|
||||
* @bit: ON/MON bit
|
||||
* @enabled: soft state of the clock, if it is coupled with another clock
|
||||
* @priv: CPG/MSTP private data
|
||||
* @sibling: pointer to the other coupled clock
|
||||
*/
|
||||
struct mstp_clock {
|
||||
struct clk_hw hw;
|
||||
u16 off;
|
||||
u8 bit;
|
||||
bool enabled;
|
||||
struct rzg2l_cpg_priv *priv;
|
||||
struct mstp_clock *sibling;
|
||||
};
|
||||
|
||||
#define to_mod_clock(_hw) container_of(_hw, struct mstp_clock, hw)
|
||||
@ -369,11 +396,41 @@ static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable)
|
||||
|
||||
static int rzg2l_mod_clock_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct mstp_clock *clock = to_mod_clock(hw);
|
||||
|
||||
if (clock->sibling) {
|
||||
struct rzg2l_cpg_priv *priv = clock->priv;
|
||||
unsigned long flags;
|
||||
bool enabled;
|
||||
|
||||
spin_lock_irqsave(&priv->rmw_lock, flags);
|
||||
enabled = clock->sibling->enabled;
|
||||
clock->enabled = true;
|
||||
spin_unlock_irqrestore(&priv->rmw_lock, flags);
|
||||
if (enabled)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rzg2l_mod_clock_endisable(hw, true);
|
||||
}
|
||||
|
||||
static void rzg2l_mod_clock_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct mstp_clock *clock = to_mod_clock(hw);
|
||||
|
||||
if (clock->sibling) {
|
||||
struct rzg2l_cpg_priv *priv = clock->priv;
|
||||
unsigned long flags;
|
||||
bool enabled;
|
||||
|
||||
spin_lock_irqsave(&priv->rmw_lock, flags);
|
||||
enabled = clock->sibling->enabled;
|
||||
clock->enabled = false;
|
||||
spin_unlock_irqrestore(&priv->rmw_lock, flags);
|
||||
if (enabled)
|
||||
return;
|
||||
}
|
||||
|
||||
rzg2l_mod_clock_endisable(hw, false);
|
||||
}
|
||||
|
||||
@ -389,9 +446,12 @@ static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (clock->sibling)
|
||||
return clock->enabled;
|
||||
|
||||
value = readl(priv->base + CLK_MON_R(clock->off));
|
||||
|
||||
return !(value & bitmask);
|
||||
return value & bitmask;
|
||||
}
|
||||
|
||||
static const struct clk_ops rzg2l_mod_clock_ops = {
|
||||
@ -400,6 +460,28 @@ static const struct clk_ops rzg2l_mod_clock_ops = {
|
||||
.is_enabled = rzg2l_mod_clock_is_enabled,
|
||||
};
|
||||
|
||||
static struct mstp_clock
|
||||
*rzg2l_mod_clock__get_sibling(struct mstp_clock *clock,
|
||||
struct rzg2l_cpg_priv *priv)
|
||||
{
|
||||
struct clk_hw *hw;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < priv->num_mod_clks; i++) {
|
||||
struct mstp_clock *clk;
|
||||
|
||||
if (priv->clks[priv->num_core_clks + i] == ERR_PTR(-ENOENT))
|
||||
continue;
|
||||
|
||||
hw = __clk_get_hw(priv->clks[priv->num_core_clks + i]);
|
||||
clk = to_mod_clock(hw);
|
||||
if (clock->off == clk->off && clock->bit == clk->bit)
|
||||
return clk;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __init
|
||||
rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
|
||||
const struct rzg2l_cpg_info *info,
|
||||
@ -461,6 +543,18 @@ rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
|
||||
|
||||
dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk));
|
||||
priv->clks[id] = clk;
|
||||
|
||||
if (mod->is_coupled) {
|
||||
struct mstp_clock *sibling;
|
||||
|
||||
clock->enabled = rzg2l_mod_clock_is_enabled(&clock->hw);
|
||||
sibling = rzg2l_mod_clock__get_sibling(clock, priv);
|
||||
if (sibling) {
|
||||
clock->sibling = sibling;
|
||||
sibling->sibling = clock;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#define CPG_PL2_DDIV (0x204)
|
||||
#define CPG_PL3A_DDIV (0x208)
|
||||
#define CPG_PL6_ETH_SSEL (0x418)
|
||||
|
||||
/* n = 0/1/2 for PLL1/4/6 */
|
||||
#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
|
||||
@ -24,6 +25,11 @@
|
||||
#define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3)
|
||||
#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3)
|
||||
|
||||
#define SEL_PLL_PACK(offset, bitpos, size) \
|
||||
(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
|
||||
|
||||
#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
|
||||
|
||||
/**
|
||||
* Definitions of CPG Core Clocks
|
||||
*
|
||||
@ -43,6 +49,7 @@ struct cpg_core_clk {
|
||||
const struct clk_div_table *dtable;
|
||||
const char * const *parent_names;
|
||||
int flag;
|
||||
int mux_flags;
|
||||
int num_parents;
|
||||
};
|
||||
|
||||
@ -54,6 +61,9 @@ enum clk_types {
|
||||
|
||||
/* Clock with divider */
|
||||
CLK_TYPE_DIV,
|
||||
|
||||
/* Clock with clock source selector */
|
||||
CLK_TYPE_MUX,
|
||||
};
|
||||
|
||||
#define DEF_TYPE(_name, _id, _type...) \
|
||||
@ -69,6 +79,11 @@ enum clk_types {
|
||||
#define DEF_DIV(_name, _id, _parent, _conf, _dtable, _flag) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \
|
||||
.parent = _parent, .dtable = _dtable, .flag = _flag)
|
||||
#define DEF_MUX(_name, _id, _conf, _parent_names, _num_parents, _flag, \
|
||||
_mux_flags) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
|
||||
.parent_names = _parent_names, .num_parents = _num_parents, \
|
||||
.flag = _flag, .mux_flags = _mux_flags)
|
||||
|
||||
/**
|
||||
* struct rzg2l_mod_clk - Module Clocks definitions
|
||||
@ -78,6 +93,7 @@ enum clk_types {
|
||||
* @parent: id of parent clock
|
||||
* @off: register offset
|
||||
* @bit: ON/MON bit
|
||||
* @is_coupled: flag to indicate coupled clock
|
||||
*/
|
||||
struct rzg2l_mod_clk {
|
||||
const char *name;
|
||||
@ -85,17 +101,25 @@ struct rzg2l_mod_clk {
|
||||
unsigned int parent;
|
||||
u16 off;
|
||||
u8 bit;
|
||||
bool is_coupled;
|
||||
};
|
||||
|
||||
#define DEF_MOD(_name, _id, _parent, _off, _bit) \
|
||||
#define DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _is_coupled) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.id = MOD_CLK_BASE + (_id), \
|
||||
.parent = (_parent), \
|
||||
.off = (_off), \
|
||||
.bit = (_bit), \
|
||||
.is_coupled = (_is_coupled), \
|
||||
}
|
||||
|
||||
#define DEF_MOD(_name, _id, _parent, _off, _bit) \
|
||||
DEF_MOD_BASE(_name, _id, _parent, _off, _bit, false)
|
||||
|
||||
#define DEF_COUPLED(_name, _id, _parent, _off, _bit) \
|
||||
DEF_MOD_BASE(_name, _id, _parent, _off, _bit, true)
|
||||
|
||||
/**
|
||||
* struct rzg2l_reset - Reset definitions
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user