Message ID | 20201110125609.30246-1-prabhakar.mahadev-lad.rj@bp.renesas.com (mailing list archive) |
---|---|
State | Awaiting Upstream, archived |
Headers | show |
Series | [v3] clk: renesas: r8a774c0: Add RPC clocks | expand |
Hi Prabhakar, On Tue, Nov 10, 2020 at 1:56 PM Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> wrote: > Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, > as well as the RPC-IF module clock, in the RZ/G2E (R8A774C0) CPG/MSSR > driver. > > Add new clk type CLK_TYPE_GEN3E3_RPCSRC to register rpcsrc as a fixed > clock on R-Car Gen3 E3 (and also RZ/G2E which is identical to E3 SoC), > parent and the divider is set based on the register value CPG_RPCCKCR[4:3] > (parent is cross verified against MD[4:1] pins) which has been set prior > to booting the kernel. > > MD[4] MD[3] MD[2] MD[1] > 0 0 0 1 -> RPCSRC CLK source is PLL1 > 0 0 1 1 -> RPCSRC CLK source is PLL1 > 0 1 0 0 -> RPCSRC CLK source is PLL1 > 1 0 1 1 -> RPCSRC CLK source is PLL1 > x x x x -> For any other values RPCSRC CLK source is PLL0 > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> Thanks for your patch! > --- > v2->v3 > * Implemented as a fixed clock Sounds fine to me. If we ever need to configure this clock from Linux, the driver can be changed. > --- a/drivers/clk/renesas/rcar-gen3-cpg.c > +++ b/drivers/clk/renesas/rcar-gen3-cpg.c > @@ -427,6 +427,19 @@ static struct clk * __init cpg_sd_clk_register(const char *name, > return clk; > } > > +static bool __init cpg_rpcsrc_e3_parent_is_pll0(u32 mode) > +{ > + unsigned int e3_rpcsrc = (mode & GENMASK(4, 1)) >> 1; > + unsigned int pll1[] = { 0x1, 0x3, 0x4, 0xb, }; > + int i; > + > + for (i = 0; i < ARRAY_SIZE(pll1); i++) > + if (e3_rpcsrc == pll1[i]) > + return false; Did you know gcc (version 9.3.0) generates smaller code for: switch (e3_rpcsrc) { case 0x1: case 0x3: case 0x4: case 0xb: return false; default: return true; } ? > @@ -696,6 +709,42 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, > cpg_rpcsrc_div_table, > &cpg_lock); > > + case CLK_TYPE_GEN3E3_RPCSRC: > + /* > + * Register RPCSRC as fixed factor clock based on the > + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for > + * which has been set prior to booting the kernel. > + */ > + > + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3; > + if (cpg_rpcsrc_e3_parent_is_pll0(cpg_mode)) { > + if (value != 2) > + return ERR_PTR(-EINVAL); > + } else { > + if (value == 2) > + return ERR_PTR(-EINVAL); > + } IMHO this cross-verification is not needed, and harmful: it prevents the boot loader from changing the configuration, which I think is a valid use case. > + > + switch (value) { > + case 0: > + div = 5; > + break; > + case 1: > + div = 3; > + break; > + case 2: > + parent = clks[core->parent >> 16]; > + if (IS_ERR(parent)) > + return ERR_CAST(parent); > + div = 8; R-Car D3 is very similar, but uses div = 5 instead of 8. Perhaps this value can be retrieved from cpg_core_clk.div? Of course, we can do that later, when D3 support is added. > + break; > + case 3: > + default: > + div = 2; > + break; > + } > + break; > + > case CLK_TYPE_GEN3_RPC: > return cpg_rpc_clk_register(core->name, base, > __clk_get_name(parent), notifiers); The rest looks good to me. Gr{oetje,eeting}s, Geert
Hi Geert, Thank you for the review. On Mon, Nov 16, 2020 at 8:34 AM Geert Uytterhoeven <geert@linux-m68k.org> wrote: > > Hi Prabhakar, > > On Tue, Nov 10, 2020 at 1:56 PM Lad Prabhakar > <prabhakar.mahadev-lad.rj@bp.renesas.com> wrote: > > Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, > > as well as the RPC-IF module clock, in the RZ/G2E (R8A774C0) CPG/MSSR > > driver. > > > > Add new clk type CLK_TYPE_GEN3E3_RPCSRC to register rpcsrc as a fixed > > clock on R-Car Gen3 E3 (and also RZ/G2E which is identical to E3 SoC), > > parent and the divider is set based on the register value CPG_RPCCKCR[4:3] > > (parent is cross verified against MD[4:1] pins) which has been set prior > > to booting the kernel. > > > > MD[4] MD[3] MD[2] MD[1] > > 0 0 0 1 -> RPCSRC CLK source is PLL1 > > 0 0 1 1 -> RPCSRC CLK source is PLL1 > > 0 1 0 0 -> RPCSRC CLK source is PLL1 > > 1 0 1 1 -> RPCSRC CLK source is PLL1 > > x x x x -> For any other values RPCSRC CLK source is PLL0 > > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> > > Thanks for your patch! > > > --- > > v2->v3 > > * Implemented as a fixed clock > > Sounds fine to me. If we ever need to configure this clock from Linux, > the driver can be changed. > > > --- a/drivers/clk/renesas/rcar-gen3-cpg.c > > +++ b/drivers/clk/renesas/rcar-gen3-cpg.c > > @@ -427,6 +427,19 @@ static struct clk * __init cpg_sd_clk_register(const char *name, > > return clk; > > } > > > > +static bool __init cpg_rpcsrc_e3_parent_is_pll0(u32 mode) > > +{ > > + unsigned int e3_rpcsrc = (mode & GENMASK(4, 1)) >> 1; > > + unsigned int pll1[] = { 0x1, 0x3, 0x4, 0xb, }; > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(pll1); i++) > > + if (e3_rpcsrc == pll1[i]) > > + return false; > > Did you know gcc (version 9.3.0) generates smaller code for: > > switch (e3_rpcsrc) { > case 0x1: > case 0x3: > case 0x4: > case 0xb: > return false; > > default: > return true; > } > > ? > That's insightful thank you for the pointer. > > @@ -696,6 +709,42 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, > > cpg_rpcsrc_div_table, > > &cpg_lock); > > > > + case CLK_TYPE_GEN3E3_RPCSRC: > > + /* > > + * Register RPCSRC as fixed factor clock based on the > > + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for > > + * which has been set prior to booting the kernel. > > + */ > > + > > + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3; > > + if (cpg_rpcsrc_e3_parent_is_pll0(cpg_mode)) { > > + if (value != 2) > > + return ERR_PTR(-EINVAL); > > + } else { > > + if (value == 2) > > + return ERR_PTR(-EINVAL); > > + } > > IMHO this cross-verification is not needed, and harmful: it prevents the > boot loader from changing the configuration, which I think is a valid > use case. > Agreed will drop this check (and also cpg_rpcsrc_e3_parent_is_pll0()) > > + > > + switch (value) { > > + case 0: > > + div = 5; > > + break; > > + case 1: > > + div = 3; > > + break; > > + case 2: > > + parent = clks[core->parent >> 16]; > > + if (IS_ERR(parent)) > > + return ERR_CAST(parent); > > + div = 8; > > R-Car D3 is very similar, but uses div = 5 instead of 8. > Perhaps this value can be retrieved from cpg_core_clk.div? > Of course, we can do that later, when D3 support is added. > Agreed, should the below be OK ? #define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1, _div) Cheers, Prabhakar > > + break; > > + case 3: > > + default: > > + div = 2; > > + break; > > + } > > + break; > > + > > case CLK_TYPE_GEN3_RPC: > > return cpg_rpc_clk_register(core->name, base, > > __clk_get_name(parent), notifiers); > > The rest looks good to me. > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org > > In personal conversations with technical people, I call myself a hacker. But > when I'm talking to journalists I just say "programmer" or something like that. > -- Linus Torvalds
Hi Prabhakar, On Mon, Nov 16, 2020 at 9:54 AM Lad, Prabhakar <prabhakar.csengg@gmail.com> wrote: > On Mon, Nov 16, 2020 at 8:34 AM Geert Uytterhoeven <geert@linux-m68k.org> wrote: > > On Tue, Nov 10, 2020 at 1:56 PM Lad Prabhakar > > <prabhakar.mahadev-lad.rj@bp.renesas.com> wrote: > > > Describe the RPCSRC internal clock and the RPC[D2] clocks derived from it, > > > as well as the RPC-IF module clock, in the RZ/G2E (R8A774C0) CPG/MSSR > > > driver. > > > > > > Add new clk type CLK_TYPE_GEN3E3_RPCSRC to register rpcsrc as a fixed > > > clock on R-Car Gen3 E3 (and also RZ/G2E which is identical to E3 SoC), > > > parent and the divider is set based on the register value CPG_RPCCKCR[4:3] > > > (parent is cross verified against MD[4:1] pins) which has been set prior > > > to booting the kernel. > > > > > > MD[4] MD[3] MD[2] MD[1] > > > 0 0 0 1 -> RPCSRC CLK source is PLL1 > > > 0 0 1 1 -> RPCSRC CLK source is PLL1 > > > 0 1 0 0 -> RPCSRC CLK source is PLL1 > > > 1 0 1 1 -> RPCSRC CLK source is PLL1 > > > x x x x -> For any other values RPCSRC CLK source is PLL0 > > > > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > > > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> > > > + switch (value) { > > > + case 0: > > > + div = 5; > > > + break; > > > + case 1: > > > + div = 3; > > > + break; > > > + case 2: > > > + parent = clks[core->parent >> 16]; > > > + if (IS_ERR(parent)) > > > + return ERR_CAST(parent); > > > + div = 8; > > > > R-Car D3 is very similar, but uses div = 5 instead of 8. > > Perhaps this value can be retrieved from cpg_core_clk.div? > > Of course, we can do that later, when D3 support is added. > > > Agreed, should the below be OK ? > > #define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1, _div) Fine, but then I would drop the _E3 suffix ;-) Alternatively, you can just hide the fixed 8 inside the macro, and add a seperate macro for D3 later. Up to you. Gr{oetje,eeting}s, Geert
Hi Geert, > Subject: Re: [PATCH v3] clk: renesas: r8a774c0: Add RPC clocks > > Hi Prabhakar, > > On Tue, Nov 10, 2020 at 1:56 PM Lad Prabhakar <prabhakar.mahadev- > lad.rj@bp.renesas.com> wrote: > > Describe the RPCSRC internal clock and the RPC[D2] clocks derived from > > it, as well as the RPC-IF module clock, in the RZ/G2E (R8A774C0) > > CPG/MSSR driver. > > > > Add new clk type CLK_TYPE_GEN3E3_RPCSRC to register rpcsrc as a fixed > > clock on R-Car Gen3 E3 (and also RZ/G2E which is identical to E3 SoC), > > parent and the divider is set based on the register value > > CPG_RPCCKCR[4:3] (parent is cross verified against MD[4:1] pins) which > > has been set prior to booting the kernel. > > > > MD[4] MD[3] MD[2] MD[1] > > 0 0 0 1 -> RPCSRC CLK source is PLL1 > > 0 0 1 1 -> RPCSRC CLK source is PLL1 > > 0 1 0 0 -> RPCSRC CLK source is PLL1 > > 1 0 1 1 -> RPCSRC CLK source is PLL1 > > x x x x -> For any other values RPCSRC CLK source is > PLL0 > > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> > > Thanks for your patch! > > > --- > > v2->v3 > > * Implemented as a fixed clock > > Sounds fine to me. If we ever need to configure this clock from Linux, > the driver can be changed. > > > --- a/drivers/clk/renesas/rcar-gen3-cpg.c > > +++ b/drivers/clk/renesas/rcar-gen3-cpg.c > > @@ -427,6 +427,19 @@ static struct clk * __init > cpg_sd_clk_register(const char *name, > > return clk; > > } > > > > +static bool __init cpg_rpcsrc_e3_parent_is_pll0(u32 mode) { > > + unsigned int e3_rpcsrc = (mode & GENMASK(4, 1)) >> 1; > > + unsigned int pll1[] = { 0x1, 0x3, 0x4, 0xb, }; > > + int i; > > + > > + for (i = 0; i < ARRAY_SIZE(pll1); i++) > > + if (e3_rpcsrc == pll1[i]) > > + return false; > > Did you know gcc (version 9.3.0) generates smaller code for: > > switch (e3_rpcsrc) { > case 0x1: > case 0x3: > case 0x4: > case 0xb: > return false; > > default: > return true; > } > > ? > > > @@ -696,6 +709,42 @@ struct clk * __init > rcar_gen3_cpg_clk_register(struct device *dev, > > cpg_rpcsrc_div_table, > > &cpg_lock); > > > > + case CLK_TYPE_GEN3E3_RPCSRC: > > + /* > > + * Register RPCSRC as fixed factor clock based on the > > + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for > > + * which has been set prior to booting the kernel. > > + */ > > + > > + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> > 3; > > + if (cpg_rpcsrc_e3_parent_is_pll0(cpg_mode)) { > > + if (value != 2) > > + return ERR_PTR(-EINVAL); > > + } else { > > + if (value == 2) > > + return ERR_PTR(-EINVAL); > > + } > > IMHO this cross-verification is not needed, and harmful: it prevents the > boot loader from changing the configuration, which I think is a valid use > case. But this check validates, whether bootloader done wrong configuration or not? For eg:- PLL1 and setting wrong divider value in RPCCKCR. It allows bootloader for changing right configurations. I may be wrong. Please correct me if I am wrong. Regards, Biju > > + > > + switch (value) { > > + case 0: > > + div = 5; > > + break; > > + case 1: > > + div = 3; > > + break; > > + case 2: > > + parent = clks[core->parent >> 16]; > > + if (IS_ERR(parent)) > > + return ERR_CAST(parent); > > + div = 8; > > R-Car D3 is very similar, but uses div = 5 instead of 8. > Perhaps this value can be retrieved from cpg_core_clk.div? > Of course, we can do that later, when D3 support is added. > > > + break; > > + case 3: > > + default: > > + div = 2; > > + break; > > + } > > + break; > > + > > case CLK_TYPE_GEN3_RPC: > > return cpg_rpc_clk_register(core->name, base, > > __clk_get_name(parent), > > notifiers); > > The rest looks good to me. > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux- > m68k.org > > In personal conversations with technical people, I call myself a hacker. > But when I'm talking to journalists I just say "programmer" or something > like that. > -- Linus Torvalds
Hi Biju, On Mon, Nov 16, 2020 at 10:03 AM Biju Das <biju.das.jz@bp.renesas.com> wrote: > > Subject: Re: [PATCH v3] clk: renesas: r8a774c0: Add RPC clocks > > On Tue, Nov 10, 2020 at 1:56 PM Lad Prabhakar <prabhakar.mahadev- > > lad.rj@bp.renesas.com> wrote: > > > Describe the RPCSRC internal clock and the RPC[D2] clocks derived from > > > it, as well as the RPC-IF module clock, in the RZ/G2E (R8A774C0) > > > CPG/MSSR driver. > > > > > > Add new clk type CLK_TYPE_GEN3E3_RPCSRC to register rpcsrc as a fixed > > > clock on R-Car Gen3 E3 (and also RZ/G2E which is identical to E3 SoC), > > > parent and the divider is set based on the register value > > > CPG_RPCCKCR[4:3] (parent is cross verified against MD[4:1] pins) which > > > has been set prior to booting the kernel. > > > > > > MD[4] MD[3] MD[2] MD[1] > > > 0 0 0 1 -> RPCSRC CLK source is PLL1 > > > 0 0 1 1 -> RPCSRC CLK source is PLL1 > > > 0 1 0 0 -> RPCSRC CLK source is PLL1 > > > 1 0 1 1 -> RPCSRC CLK source is PLL1 > > > x x x x -> For any other values RPCSRC CLK source is > > PLL0 > > > > > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> > > > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> > > > > Thanks for your patch! > > > > > --- > > > v2->v3 > > > * Implemented as a fixed clock > > > > Sounds fine to me. If we ever need to configure this clock from Linux, > > the driver can be changed. > > > > > --- a/drivers/clk/renesas/rcar-gen3-cpg.c > > > +++ b/drivers/clk/renesas/rcar-gen3-cpg.c > > > @@ -696,6 +709,42 @@ struct clk * __init > > rcar_gen3_cpg_clk_register(struct device *dev, > > > cpg_rpcsrc_div_table, > > > &cpg_lock); > > > > > > + case CLK_TYPE_GEN3E3_RPCSRC: > > > + /* > > > + * Register RPCSRC as fixed factor clock based on the > > > + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for > > > + * which has been set prior to booting the kernel. > > > + */ > > > + > > > + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> > > 3; > > > + if (cpg_rpcsrc_e3_parent_is_pll0(cpg_mode)) { > > > + if (value != 2) > > > + return ERR_PTR(-EINVAL); > > > + } else { > > > + if (value == 2) > > > + return ERR_PTR(-EINVAL); > > > + } > > > > IMHO this cross-verification is not needed, and harmful: it prevents the > > boot loader from changing the configuration, which I think is a valid use > > case. > > But this check validates, whether bootloader done wrong configuration or not? > For eg:- PLL1 and setting wrong divider value in RPCCKCR. > > It allows bootloader for changing right configurations. I may be wrong. Please correct me if I am wrong. What is a wrong configuration? According to the RPCSRC docs, DIV[4:3] select both the parent clock and the divider. All four possible values are valid. MD[4:1] select the boot device, and determine the _initial values_ of the DIV[4:0] bits. Nothing in the documentation says they cannot be changed later, after which the DIV[4:3] bits no longer match MD[4:1]. If you want to be really sure, you can change the bits, and measure the impact on the RPC clock signal. A long time ago, I did a similar thing for PLL0CR.CKSEL on R-Car D3, and looked at the impact on the serial console (albeit with remote access, i.e. no console output if kernel and hardware didn't agree ;-) Gr{oetje,eeting}s, Geert
Hi Geert, Thanks for the feedback. > kernel@vger.kernel.org>; Prabhakar <prabhakar.csengg@gmail.com> > Subject: Re: [PATCH v3] clk: renesas: r8a774c0: Add RPC clocks > > Hi Biju, > > On Mon, Nov 16, 2020 at 10:03 AM Biju Das <biju.das.jz@bp.renesas.com> > wrote: > > > Subject: Re: [PATCH v3] clk: renesas: r8a774c0: Add RPC clocks On > > > Tue, Nov 10, 2020 at 1:56 PM Lad Prabhakar <prabhakar.mahadev- > > > lad.rj@bp.renesas.com> wrote: > > > > Describe the RPCSRC internal clock and the RPC[D2] clocks derived > > > > from it, as well as the RPC-IF module clock, in the RZ/G2E > > > > (R8A774C0) CPG/MSSR driver. > > > > > > > > Add new clk type CLK_TYPE_GEN3E3_RPCSRC to register rpcsrc as a > > > > fixed clock on R-Car Gen3 E3 (and also RZ/G2E which is identical > > > > to E3 SoC), parent and the divider is set based on the register > > > > value CPG_RPCCKCR[4:3] (parent is cross verified against MD[4:1] > > > > pins) which has been set prior to booting the kernel. > > > > > > > > MD[4] MD[3] MD[2] MD[1] > > > > 0 0 0 1 -> RPCSRC CLK source is PLL1 > > > > 0 0 1 1 -> RPCSRC CLK source is PLL1 > > > > 0 1 0 0 -> RPCSRC CLK source is PLL1 > > > > 1 0 1 1 -> RPCSRC CLK source is PLL1 > > > > x x x x -> For any other values RPCSRC CLK source > is > > > PLL0 > > > > > > > > Signed-off-by: Lad Prabhakar > > > > <prabhakar.mahadev-lad.rj@bp.renesas.com> > > > > Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> > > > > > > Thanks for your patch! > > > > > > > --- > > > > v2->v3 > > > > * Implemented as a fixed clock > > > > > > Sounds fine to me. If we ever need to configure this clock from > > > Linux, the driver can be changed. > > > > > > > --- a/drivers/clk/renesas/rcar-gen3-cpg.c > > > > +++ b/drivers/clk/renesas/rcar-gen3-cpg.c > > > > > @@ -696,6 +709,42 @@ struct clk * __init > > > rcar_gen3_cpg_clk_register(struct device *dev, > > > > > cpg_rpcsrc_div_table, > > > > &cpg_lock); > > > > > > > > + case CLK_TYPE_GEN3E3_RPCSRC: > > > > + /* > > > > + * Register RPCSRC as fixed factor clock based on > the > > > > + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value > for > > > > + * which has been set prior to booting the kernel. > > > > + */ > > > > + > > > > + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, > > > > + 3)) >> > > > 3; > > > > + if (cpg_rpcsrc_e3_parent_is_pll0(cpg_mode)) { > > > > + if (value != 2) > > > > + return ERR_PTR(-EINVAL); > > > > + } else { > > > > + if (value == 2) > > > > + return ERR_PTR(-EINVAL); > > > > + } > > > > > > IMHO this cross-verification is not needed, and harmful: it prevents > > > the boot loader from changing the configuration, which I think is a > > > valid use case. > > > > But this check validates, whether bootloader done wrong configuration or > not? > > For eg:- PLL1 and setting wrong divider value in RPCCKCR. > > > > It allows bootloader for changing right configurations. I may be wrong. > Please correct me if I am wrong. > > What is a wrong configuration? According to the RPCSRC docs, DIV[4:3] > select both the parent clock and the divider. > All four possible values are valid. OK. It is clear now. Regards, Biju > MD[4:1] select the boot device, and determine the _initial values_ of the > DIV[4:0] bits. Nothing in the documentation says they cannot be changed > later, after which the DIV[4:3] bits no longer match MD[4:1]. > > If you want to be really sure, you can change the bits, and measure the > impact on the RPC clock signal. > > A long time ago, I did a similar thing for PLL0CR.CKSEL on R-Car D3, and > looked at the impact on the serial console (albeit with remote access, > i.e. no console output if kernel and hardware didn't agree ;-) > > Gr{oetje,eeting}s, > > Geert > > -- > Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux- > m68k.org > > In personal conversations with technical people, I call myself a hacker. > But when I'm talking to journalists I just say "programmer" or something > like that. > -- Linus Torvalds
diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c index 9fc9fa9e531a..ed3a2cf0e0bb 100644 --- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c @@ -44,6 +44,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, CLK_OCO, @@ -74,6 +75,13 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = { DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), + DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1), + + DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774C0_CLK_RPC), + DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), @@ -199,6 +207,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774C0_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774C0_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774C0_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774C0_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774C0_CLK_S3D2), DEF_MOD("i2c5", 919, R8A774C0_CLK_S3D2), DEF_MOD("i2c-dvfs", 926, R8A774C0_CLK_CP), diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 488f8b3980c5..00c3d5570274 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -427,6 +427,19 @@ static struct clk * __init cpg_sd_clk_register(const char *name, return clk; } +static bool __init cpg_rpcsrc_e3_parent_is_pll0(u32 mode) +{ + unsigned int e3_rpcsrc = (mode & GENMASK(4, 1)) >> 1; + unsigned int pll1[] = { 0x1, 0x3, 0x4, 0xb, }; + int i; + + for (i = 0; i < ARRAY_SIZE(pll1); i++) + if (e3_rpcsrc == pll1[i]) + return false; + + return true; +} + struct rpc_clock { struct clk_divider div; struct clk_gate gate; @@ -696,6 +709,42 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, cpg_rpcsrc_div_table, &cpg_lock); + case CLK_TYPE_GEN3E3_RPCSRC: + /* + * Register RPCSRC as fixed factor clock based on the + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for + * which has been set prior to booting the kernel. + */ + + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3; + if (cpg_rpcsrc_e3_parent_is_pll0(cpg_mode)) { + if (value != 2) + return ERR_PTR(-EINVAL); + } else { + if (value == 2) + return ERR_PTR(-EINVAL); + } + + switch (value) { + case 0: + div = 5; + break; + case 1: + div = 3; + break; + case 2: + parent = clks[core->parent >> 16]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + div = 8; + break; + case 3: + default: + div = 2; + break; + } + break; + case CLK_TYPE_GEN3_RPC: return cpg_rpc_clk_register(core->name, base, __clk_get_name(parent), notifiers); diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index c4ac80cac6a0..4d20b2a8bd9f 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -24,6 +24,7 @@ enum rcar_gen3_clk_types { CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ CLK_TYPE_GEN3_RPCSRC, + CLK_TYPE_GEN3E3_RPCSRC, CLK_TYPE_GEN3_RPC, CLK_TYPE_GEN3_RPCD2, @@ -54,6 +55,9 @@ enum rcar_gen3_clk_types { #define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset) \ DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset) +#define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3E3_RPCSRC, (_parent0) << 16 | (_parent1)) + struct rcar_gen3_cpg_pll_config { u8 extal_div; u8 pll1_mult;