clk: renesas: Updates for v5.16 (take two)
- Add SPI Multi I/O Bus and SDHI clocks and resets on RZ/G2L, - Add SPI Multi I/O Bus (RPC) clocks on R-Car V3U, - Add MediaLB clocks on R-Car H3, M3-W/W+, and M3-N. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQQ9qaHoIs/1I4cXmEiKwlD9ZEnxcAUCYWln3QAKCRCKwlD9ZEnx cBVCAP9WgdRq0SWdQqGRwUAo9RTmPxy4YmlU9EWifI6qrVc8xgD/cZ2Luew7N6JF n3jFh9gn8kKfV+gFRTgSGNVgGdOi8Ak= =7pBq -----END PGP SIGNATURE----- Merge tag 'renesas-clk-for-v5.16-tag2' 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 SPI Multi I/O Bus and SDHI clocks and resets on RZ/G2L - Add SPI Multi I/O Bus (RPC) clocks on R-Car V3U - Add MediaLB clocks on R-Car H3, M3-W/W+, and M3-N * tag 'renesas-clk-for-v5.16-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers: clk: renesas: r8a779[56]x: Add MLP clocks clk: renesas: r9a07g044: Add SDHI clock and reset entries clk: renesas: rzg2l: Add SDHI clk mux support clk: renesas: r8a779a0: Add RPC support clk: renesas: cpg-lib: Move RPC clock registration to the library clk: renesas: r9a07g044: Add clock and reset entries for SPI Multi I/O Bus Controller
This commit is contained in:
commit
bada0389c2
@ -229,6 +229,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
|
||||
DEF_MOD("lvds", 727, R8A7795_CLK_S0D4),
|
||||
DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI),
|
||||
DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI),
|
||||
DEF_MOD("mlp", 802, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vin7", 804, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin6", 805, R8A7795_CLK_S0D2),
|
||||
DEF_MOD("vin5", 806, R8A7795_CLK_S0D2),
|
||||
|
@ -207,6 +207,7 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = {
|
||||
DEF_MOD("du0", 724, R8A7796_CLK_S2D1),
|
||||
DEF_MOD("lvds", 727, R8A7796_CLK_S2D1),
|
||||
DEF_MOD("hdmi0", 729, R8A7796_CLK_HDMI),
|
||||
DEF_MOD("mlp", 802, R8A7796_CLK_S2D1),
|
||||
DEF_MOD("vin7", 804, R8A7796_CLK_S0D2),
|
||||
DEF_MOD("vin6", 805, R8A7796_CLK_S0D2),
|
||||
DEF_MOD("vin5", 806, R8A7796_CLK_S0D2),
|
||||
|
@ -205,6 +205,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = {
|
||||
DEF_MOD("lvds", 727, R8A77965_CLK_S2D1),
|
||||
DEF_MOD("hdmi0", 729, R8A77965_CLK_HDMI),
|
||||
|
||||
DEF_MOD("mlp", 802, R8A77965_CLK_S2D1),
|
||||
DEF_MOD("vin7", 804, R8A77965_CLK_S0D2),
|
||||
DEF_MOD("vin6", 805, R8A77965_CLK_S0D2),
|
||||
DEF_MOD("vin5", 806, R8A77965_CLK_S0D2),
|
||||
|
@ -37,6 +37,9 @@ enum rcar_r8a779a0_clk_types {
|
||||
CLK_TYPE_R8A779A0_SD,
|
||||
CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */
|
||||
CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */
|
||||
CLK_TYPE_R8A779A0_RPCSRC,
|
||||
CLK_TYPE_R8A779A0_RPC,
|
||||
CLK_TYPE_R8A779A0_RPCD2,
|
||||
};
|
||||
|
||||
struct rcar_r8a779a0_cpg_pll_config {
|
||||
@ -125,6 +128,10 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1),
|
||||
DEF_RATE(".oco", CLK_OCO, 32768),
|
||||
DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_R8A779A0_RPCSRC, CLK_PLL5),
|
||||
DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_R8A779A0_RPC, CLK_RPCSRC),
|
||||
DEF_BASE("rpcd2", R8A779A0_CLK_RPCD2, CLK_TYPE_R8A779A0_RPCD2,
|
||||
R8A779A0_CLK_RPC),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
DEF_Z("z0", R8A779A0_CLK_Z0, CLK_PLL20, 2, 0),
|
||||
@ -200,6 +207,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
|
||||
DEF_MOD("msi3", 621, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi4", 622, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("msi5", 623, R8A779A0_CLK_MSO),
|
||||
DEF_MOD("rpc-if", 629, R8A779A0_CLK_RPCD2),
|
||||
DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8),
|
||||
DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8),
|
||||
@ -414,6 +422,15 @@ static struct clk * __init cpg_z_clk_register(const char *name,
|
||||
return clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* RPC Clocks
|
||||
*/
|
||||
#define CPG_RPCCKCR 0x874
|
||||
|
||||
static const struct clk_div_table cpg_rpcsrc_div_table[] = {
|
||||
{ 0, 4 }, { 1, 6 }, { 2, 5 }, { 3, 6 }, { 0, 0 },
|
||||
};
|
||||
|
||||
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,
|
||||
@ -481,6 +498,21 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev,
|
||||
div = cpg_pll_config->osc_prediv * core->div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_R8A779A0_RPCSRC:
|
||||
return clk_register_divider_table(NULL, core->name,
|
||||
__clk_get_name(parent), 0,
|
||||
base + CPG_RPCCKCR, 3, 2, 0,
|
||||
cpg_rpcsrc_div_table,
|
||||
&cpg_lock);
|
||||
|
||||
case CLK_TYPE_R8A779A0_RPC:
|
||||
return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent), notifiers);
|
||||
|
||||
case CLK_TYPE_R8A779A0_RPCD2:
|
||||
return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent));
|
||||
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
@ -29,10 +29,14 @@ enum clk_ids {
|
||||
CLK_PLL2_DIV16,
|
||||
CLK_PLL2_DIV20,
|
||||
CLK_PLL3,
|
||||
CLK_PLL3_400,
|
||||
CLK_PLL3_533,
|
||||
CLK_PLL3_DIV2,
|
||||
CLK_PLL3_DIV2_4,
|
||||
CLK_PLL3_DIV2_4_2,
|
||||
CLK_PLL3_DIV4,
|
||||
CLK_SEL_PLL3_3,
|
||||
CLK_DIV_PLL3_C,
|
||||
CLK_PLL4,
|
||||
CLK_PLL5,
|
||||
CLK_PLL5_FOUT3,
|
||||
@ -40,6 +44,12 @@ enum clk_ids {
|
||||
CLK_PLL6,
|
||||
CLK_PLL6_250,
|
||||
CLK_P1_DIV2,
|
||||
CLK_PLL2_800,
|
||||
CLK_PLL2_SDHI_533,
|
||||
CLK_PLL2_SDHI_400,
|
||||
CLK_PLL2_SDHI_266,
|
||||
CLK_SD0_DIV4,
|
||||
CLK_SD1_DIV4,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE,
|
||||
@ -56,7 +66,9 @@ static const struct clk_div_table dtable_1_32[] = {
|
||||
};
|
||||
|
||||
/* Mux clock tables */
|
||||
static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
|
||||
static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
|
||||
static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
|
||||
|
||||
static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
@ -68,6 +80,8 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)),
|
||||
DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 133, 2),
|
||||
DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 133, 2),
|
||||
DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4),
|
||||
DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3),
|
||||
|
||||
DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1),
|
||||
DEF_FIXED(".pll5_fout3", CLK_PLL5_FOUT3, CLK_PLL5, 1, 6),
|
||||
@ -75,6 +89,11 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6),
|
||||
|
||||
DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2),
|
||||
DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2),
|
||||
DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3),
|
||||
DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2),
|
||||
DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2),
|
||||
|
||||
DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16),
|
||||
DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20),
|
||||
|
||||
@ -82,6 +101,10 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4),
|
||||
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_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3,
|
||||
sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY),
|
||||
DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3,
|
||||
DIVPL3C, dtable_1_32, CLK_DIVIDER_HIWORD_MASK),
|
||||
|
||||
DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2),
|
||||
DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2),
|
||||
@ -101,6 +124,14 @@ static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = {
|
||||
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),
|
||||
DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
|
||||
DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
|
||||
DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0,
|
||||
sel_shdi, ARRAY_SIZE(sel_shdi)),
|
||||
DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1,
|
||||
sel_shdi, ARRAY_SIZE(sel_shdi)),
|
||||
DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
|
||||
DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
|
||||
};
|
||||
|
||||
static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
@ -114,6 +145,26 @@ static struct rzg2l_mod_clk r9a07g044_mod_clks[] = {
|
||||
0x52c, 0),
|
||||
DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2,
|
||||
0x52c, 1),
|
||||
DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
|
||||
0x550, 0),
|
||||
DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
|
||||
0x550, 1),
|
||||
DEF_MOD("sdhi0_imclk", R9A07G044_SDHI0_IMCLK, CLK_SD0_DIV4,
|
||||
0x554, 0),
|
||||
DEF_MOD("sdhi0_imclk2", R9A07G044_SDHI0_IMCLK2, CLK_SD0_DIV4,
|
||||
0x554, 1),
|
||||
DEF_MOD("sdhi0_clk_hs", R9A07G044_SDHI0_CLK_HS, R9A07G044_CLK_SD0,
|
||||
0x554, 2),
|
||||
DEF_MOD("sdhi0_aclk", R9A07G044_SDHI0_ACLK, R9A07G044_CLK_P1,
|
||||
0x554, 3),
|
||||
DEF_MOD("sdhi1_imclk", R9A07G044_SDHI1_IMCLK, CLK_SD1_DIV4,
|
||||
0x554, 4),
|
||||
DEF_MOD("sdhi1_imclk2", R9A07G044_SDHI1_IMCLK2, CLK_SD1_DIV4,
|
||||
0x554, 5),
|
||||
DEF_MOD("sdhi1_clk_hs", R9A07G044_SDHI1_CLK_HS, R9A07G044_CLK_SD1,
|
||||
0x554, 6),
|
||||
DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1,
|
||||
0x554, 7),
|
||||
DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0,
|
||||
0x570, 0),
|
||||
DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0,
|
||||
@ -182,6 +233,9 @@ static struct rzg2l_reset r9a07g044_resets[] = {
|
||||
DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0),
|
||||
DEF_RST(R9A07G044_DMAC_ARESETN, 0x82c, 0),
|
||||
DEF_RST(R9A07G044_DMAC_RST_ASYNC, 0x82c, 1),
|
||||
DEF_RST(R9A07G044_SPI_RST, 0x850, 0),
|
||||
DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0),
|
||||
DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1),
|
||||
DEF_RST(R9A07G044_SSI0_RST_M2_REG, 0x870, 0),
|
||||
DEF_RST(R9A07G044_SSI1_RST_M2_REG, 0x870, 1),
|
||||
DEF_RST(R9A07G044_SSI2_RST_M2_REG, 0x870, 2),
|
||||
|
@ -267,4 +267,87 @@ free_clock:
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct rpc_clock {
|
||||
struct clk_divider div;
|
||||
struct clk_gate gate;
|
||||
/*
|
||||
* One notifier covers both RPC and RPCD2 clocks as they are both
|
||||
* controlled by the same RPCCKCR register...
|
||||
*/
|
||||
struct cpg_simple_notifier csn;
|
||||
};
|
||||
|
||||
static const struct clk_div_table cpg_rpc_div_table[] = {
|
||||
{ 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
|
||||
};
|
||||
|
||||
struct clk * __init cpg_rpc_clk_register(const char *name,
|
||||
void __iomem *rpcckcr, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
struct rpc_clock *rpc;
|
||||
struct clk *clk;
|
||||
|
||||
rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
|
||||
if (!rpc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rpc->div.reg = rpcckcr;
|
||||
rpc->div.width = 3;
|
||||
rpc->div.table = cpg_rpc_div_table;
|
||||
rpc->div.lock = &cpg_lock;
|
||||
|
||||
rpc->gate.reg = rpcckcr;
|
||||
rpc->gate.bit_idx = 8;
|
||||
rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
|
||||
rpc->gate.lock = &cpg_lock;
|
||||
|
||||
rpc->csn.reg = rpcckcr;
|
||||
|
||||
clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
|
||||
&rpc->div.hw, &clk_divider_ops,
|
||||
&rpc->gate.hw, &clk_gate_ops,
|
||||
CLK_SET_RATE_PARENT);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(rpc);
|
||||
return clk;
|
||||
}
|
||||
|
||||
cpg_simple_notifier_register(notifiers, &rpc->csn);
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct rpcd2_clock {
|
||||
struct clk_fixed_factor fixed;
|
||||
struct clk_gate gate;
|
||||
};
|
||||
|
||||
struct clk * __init cpg_rpcd2_clk_register(const char *name,
|
||||
void __iomem *rpcckcr,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct rpcd2_clock *rpcd2;
|
||||
struct clk *clk;
|
||||
|
||||
rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL);
|
||||
if (!rpcd2)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rpcd2->fixed.mult = 1;
|
||||
rpcd2->fixed.div = 2;
|
||||
|
||||
rpcd2->gate.reg = rpcckcr;
|
||||
rpcd2->gate.bit_idx = 9;
|
||||
rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE;
|
||||
rpcd2->gate.lock = &cpg_lock;
|
||||
|
||||
clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
|
||||
&rpcd2->fixed.hw, &clk_fixed_factor_ops,
|
||||
&rpcd2->gate.hw, &clk_gate_ops,
|
||||
CLK_SET_RATE_PARENT);
|
||||
if (IS_ERR(clk))
|
||||
kfree(rpcd2);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
|
@ -30,4 +30,11 @@ struct clk * __init cpg_sd_clk_register(const char *name,
|
||||
void __iomem *base, unsigned int offset, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers, bool skip_first);
|
||||
|
||||
struct clk * __init cpg_rpc_clk_register(const char *name,
|
||||
void __iomem *rpcckcr, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers);
|
||||
|
||||
struct clk * __init cpg_rpcd2_clk_register(const char *name,
|
||||
void __iomem *rpcckcr,
|
||||
const char *parent_name);
|
||||
#endif
|
||||
|
@ -301,95 +301,10 @@ static struct clk * __init cpg_z_clk_register(const char *name,
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct rpc_clock {
|
||||
struct clk_divider div;
|
||||
struct clk_gate gate;
|
||||
/*
|
||||
* One notifier covers both RPC and RPCD2 clocks as they are both
|
||||
* controlled by the same RPCCKCR register...
|
||||
*/
|
||||
struct cpg_simple_notifier csn;
|
||||
};
|
||||
|
||||
static const struct clk_div_table cpg_rpcsrc_div_table[] = {
|
||||
{ 2, 5 }, { 3, 6 }, { 0, 0 },
|
||||
};
|
||||
|
||||
static const struct clk_div_table cpg_rpc_div_table[] = {
|
||||
{ 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
|
||||
};
|
||||
|
||||
static struct clk * __init cpg_rpc_clk_register(const char *name,
|
||||
void __iomem *base, const char *parent_name,
|
||||
struct raw_notifier_head *notifiers)
|
||||
{
|
||||
struct rpc_clock *rpc;
|
||||
struct clk *clk;
|
||||
|
||||
rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
|
||||
if (!rpc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rpc->div.reg = base + CPG_RPCCKCR;
|
||||
rpc->div.width = 3;
|
||||
rpc->div.table = cpg_rpc_div_table;
|
||||
rpc->div.lock = &cpg_lock;
|
||||
|
||||
rpc->gate.reg = base + CPG_RPCCKCR;
|
||||
rpc->gate.bit_idx = 8;
|
||||
rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
|
||||
rpc->gate.lock = &cpg_lock;
|
||||
|
||||
rpc->csn.reg = base + CPG_RPCCKCR;
|
||||
|
||||
clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
|
||||
&rpc->div.hw, &clk_divider_ops,
|
||||
&rpc->gate.hw, &clk_gate_ops,
|
||||
CLK_SET_RATE_PARENT);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(rpc);
|
||||
return clk;
|
||||
}
|
||||
|
||||
cpg_simple_notifier_register(notifiers, &rpc->csn);
|
||||
return clk;
|
||||
}
|
||||
|
||||
struct rpcd2_clock {
|
||||
struct clk_fixed_factor fixed;
|
||||
struct clk_gate gate;
|
||||
};
|
||||
|
||||
static struct clk * __init cpg_rpcd2_clk_register(const char *name,
|
||||
void __iomem *base,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct rpcd2_clock *rpcd2;
|
||||
struct clk *clk;
|
||||
|
||||
rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL);
|
||||
if (!rpcd2)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
rpcd2->fixed.mult = 1;
|
||||
rpcd2->fixed.div = 2;
|
||||
|
||||
rpcd2->gate.reg = base + CPG_RPCCKCR;
|
||||
rpcd2->gate.bit_idx = 9;
|
||||
rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE;
|
||||
rpcd2->gate.lock = &cpg_lock;
|
||||
|
||||
clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
|
||||
&rpcd2->fixed.hw, &clk_fixed_factor_ops,
|
||||
&rpcd2->gate.hw, &clk_gate_ops,
|
||||
CLK_SET_RATE_PARENT);
|
||||
if (IS_ERR(clk))
|
||||
kfree(rpcd2);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
|
||||
static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
|
||||
static unsigned int cpg_clk_extalr __initdata;
|
||||
static u32 cpg_mode __initdata;
|
||||
@ -600,11 +515,11 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_RPC:
|
||||
return cpg_rpc_clk_register(core->name, base,
|
||||
return cpg_rpc_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent), notifiers);
|
||||
|
||||
case CLK_TYPE_GEN3_RPCD2:
|
||||
return cpg_rpcd2_clk_register(core->name, base,
|
||||
return cpg_rpcd2_clk_register(core->name, base + CPG_RPCCKCR,
|
||||
__clk_get_name(parent));
|
||||
|
||||
default:
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
@ -55,6 +56,14 @@
|
||||
#define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff)
|
||||
#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff)
|
||||
|
||||
struct sd_hw_data {
|
||||
struct clk_hw hw;
|
||||
u32 conf;
|
||||
struct rzg2l_cpg_priv *priv;
|
||||
};
|
||||
|
||||
#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw)
|
||||
|
||||
/**
|
||||
* struct rzg2l_cpg_priv - Clock Pulse Generator Private Data
|
||||
*
|
||||
@ -150,6 +159,112 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
|
||||
return clk_hw->clk;
|
||||
}
|
||||
|
||||
static int rzg2l_cpg_sd_clk_mux_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
return clk_mux_determine_rate_flags(hw, req, 0);
|
||||
}
|
||||
|
||||
static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct sd_hw_data *hwdata = to_sd_hw_data(hw);
|
||||
struct rzg2l_cpg_priv *priv = hwdata->priv;
|
||||
u32 off = GET_REG_OFFSET(hwdata->conf);
|
||||
u32 shift = GET_SHIFT(hwdata->conf);
|
||||
const u32 clk_src_266 = 2;
|
||||
u32 bitmask;
|
||||
|
||||
/*
|
||||
* As per the HW manual, we should not directly switch from 533 MHz to
|
||||
* 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
|
||||
* to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
|
||||
* and then switch to the target setting (2’b01 (533 MHz) or 2’b10
|
||||
* (400 MHz)).
|
||||
* Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
|
||||
* switching register is prohibited.
|
||||
* The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
|
||||
* the index to value mapping is done by adding 1 to the index.
|
||||
*/
|
||||
bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
|
||||
if (index != clk_src_266) {
|
||||
u32 msk, val;
|
||||
int ret;
|
||||
|
||||
writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
|
||||
|
||||
msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
|
||||
|
||||
ret = readl_poll_timeout(priv->base + CPG_CLKSTATUS, val,
|
||||
!(val & msk), 100,
|
||||
CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed to switch clk source\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
writel(bitmask | ((index + 1) << shift), priv->base + off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct sd_hw_data *hwdata = to_sd_hw_data(hw);
|
||||
struct rzg2l_cpg_priv *priv = hwdata->priv;
|
||||
u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf));
|
||||
|
||||
val >>= GET_SHIFT(hwdata->conf);
|
||||
val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0);
|
||||
if (val) {
|
||||
val--;
|
||||
} else {
|
||||
/* Prohibited clk source, change it to 533 MHz(reset value) */
|
||||
rzg2l_cpg_sd_clk_mux_set_parent(hw, 0);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
|
||||
.determine_rate = rzg2l_cpg_sd_clk_mux_determine_rate,
|
||||
.set_parent = rzg2l_cpg_sd_clk_mux_set_parent,
|
||||
.get_parent = rzg2l_cpg_sd_clk_mux_get_parent,
|
||||
};
|
||||
|
||||
static struct clk * __init
|
||||
rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
|
||||
void __iomem *base,
|
||||
struct rzg2l_cpg_priv *priv)
|
||||
{
|
||||
struct sd_hw_data *clk_hw_data;
|
||||
struct clk_init_data init;
|
||||
struct clk_hw *clk_hw;
|
||||
int ret;
|
||||
|
||||
clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
|
||||
if (!clk_hw_data)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clk_hw_data->priv = priv;
|
||||
clk_hw_data->conf = core->conf;
|
||||
|
||||
init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0";
|
||||
init.ops = &rzg2l_cpg_sd_clk_mux_ops;
|
||||
init.flags = 0;
|
||||
init.num_parents = core->num_parents;
|
||||
init.parent_names = core->parent_names;
|
||||
|
||||
clk_hw = &clk_hw_data->hw;
|
||||
clk_hw->init = &init;
|
||||
|
||||
ret = devm_clk_hw_register(priv->dev, clk_hw);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return clk_hw->clk;
|
||||
}
|
||||
|
||||
struct pll_clk {
|
||||
struct clk_hw hw;
|
||||
unsigned int conf;
|
||||
@ -311,6 +426,9 @@ rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core,
|
||||
case CLK_TYPE_MUX:
|
||||
clk = rzg2l_cpg_mux_clk_register(core, priv->base, priv);
|
||||
break;
|
||||
case CLK_TYPE_SD_MUX:
|
||||
clk = rzg2l_cpg_sd_mux_clk_register(core, priv->base, priv);
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
@ -11,8 +11,16 @@
|
||||
|
||||
#define CPG_PL2_DDIV (0x204)
|
||||
#define CPG_PL3A_DDIV (0x208)
|
||||
#define CPG_PL2SDHI_DSEL (0x218)
|
||||
#define CPG_CLKSTATUS (0x280)
|
||||
#define CPG_PL3_SSEL (0x408)
|
||||
#define CPG_PL6_ETH_SSEL (0x418)
|
||||
|
||||
#define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
|
||||
#define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
|
||||
|
||||
#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 20000
|
||||
|
||||
/* n = 0/1/2 for PLL1/4/6 */
|
||||
#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
|
||||
#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
|
||||
@ -24,12 +32,17 @@
|
||||
#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3)
|
||||
#define DIVPL3A DDIV_PACK(CPG_PL3A_DDIV, 0, 3)
|
||||
#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3)
|
||||
#define DIVPL3C DDIV_PACK(CPG_PL3A_DDIV, 8, 3)
|
||||
|
||||
#define SEL_PLL_PACK(offset, bitpos, size) \
|
||||
(((offset) << 20) | ((bitpos) << 12) | ((size) << 8))
|
||||
|
||||
#define SEL_PLL3_3 SEL_PLL_PACK(CPG_PL3_SSEL, 8, 1)
|
||||
#define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
|
||||
|
||||
#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
|
||||
#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
|
||||
|
||||
/**
|
||||
* Definitions of CPG Core Clocks
|
||||
*
|
||||
@ -64,6 +77,9 @@ enum clk_types {
|
||||
|
||||
/* Clock with clock source selector */
|
||||
CLK_TYPE_MUX,
|
||||
|
||||
/* Clock with SD clock source selector */
|
||||
CLK_TYPE_SD_MUX,
|
||||
};
|
||||
|
||||
#define DEF_TYPE(_name, _id, _type...) \
|
||||
@ -84,6 +100,9 @@ enum clk_types {
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_MUX, .conf = _conf, \
|
||||
.parent_names = _parent_names, .num_parents = _num_parents, \
|
||||
.flag = _flag, .mux_flags = _mux_flags)
|
||||
#define DEF_SD_MUX(_name, _id, _conf, _parent_names, _num_parents) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
|
||||
.parent_names = _parent_names, .num_parents = _num_parents)
|
||||
|
||||
/**
|
||||
* struct rzg2l_mod_clk - Module Clocks definitions
|
||||
|
Loading…
Reference in New Issue
Block a user