Message ID | 1516468460-4908-5-git-send-email-david@lechnology.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Saturday 20 January 2018 10:43 PM, David Lechner wrote: > This adds platform-specific declarations for the PLL clocks on TI DA850/ > OMAP-L138/AM18XX SoCs. > > Signed-off-by: David Lechner <david@lechnology.com> > +static const struct davinci_pll_clk_info da850_pll1_info __initconst = { > + .name = "pll1", > + .unlock_reg = CFGCHIP(3), > + .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, I guess this will change with the cfgchip handling discussion last week. > + .pllm_mask = GENMASK(4, 0), > + .pllm_min = 4, > + .pllm_max = 32, > + .pllout_min_rate = 300000000, > + .pllout_max_rate = 600000000, > + .flags = PLL_HAS_POSTDIV, > +}; > + [...] > +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) > +{ > + const struct davinci_pll_sysclk_info *info; > + > + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); > + > + davinci_pll_auxclk_register("pll0_auxclk", pll0); > + > + for (info = da850_pll0_sysclk_info; info->name; info++) > + davinci_pll_sysclk_register(info, pll0); > + > + davinci_pll_obsclk_register(&da850_pll0_obsclk_info, pll0); > + > + davinci_pll_clk_register(&da850_pll1_info, "oscin", pll1); Both PLL0 and PLL1 use the same reference clock. So this should be "ref_clk". I dont think we ever need to register a clock called oscin along with "ref_clk". There is only one reference clock. It can either be obtained using internal oscillator or external oscillator. Thanks, Sekhar
On 02/01/2018 02:58 AM, Sekhar Nori wrote: > On Saturday 20 January 2018 10:43 PM, David Lechner wrote: >> This adds platform-specific declarations for the PLL clocks on TI DA850/ >> OMAP-L138/AM18XX SoCs. >> >> Signed-off-by: David Lechner <david@lechnology.com> > >> +static const struct davinci_pll_clk_info da850_pll1_info __initconst = { >> + .name = "pll1", >> + .unlock_reg = CFGCHIP(3), >> + .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, > > I guess this will change with the cfgchip handling discussion last week. Actually no, there really weren't any changes to the clock drivers because of this change. Only a small change in mach-davinci. > >> + .pllm_mask = GENMASK(4, 0), >> + .pllm_min = 4, >> + .pllm_max = 32, >> + .pllout_min_rate = 300000000, >> + .pllout_max_rate = 600000000, >> + .flags = PLL_HAS_POSTDIV, >> +}; >> + > > [...] > >> +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) >> +{ >> + const struct davinci_pll_sysclk_info *info; >> + >> + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); >> + >> + davinci_pll_auxclk_register("pll0_auxclk", pll0); >> + >> + for (info = da850_pll0_sysclk_info; info->name; info++) >> + davinci_pll_sysclk_register(info, pll0); >> + >> + davinci_pll_obsclk_register(&da850_pll0_obsclk_info, pll0); >> + >> + davinci_pll_clk_register(&da850_pll1_info, "oscin", pll1); > > Both PLL0 and PLL1 use the same reference clock. So this should be > "ref_clk". I dont think we ever need to register a clock called oscin > along with "ref_clk". There is only one reference clock. It can either > be obtained using internal oscillator or external oscillator. > As per my response to the previous path, this depends on which both which SoC and which diagram in the TRM for that SoC you are looking at. It works either way.
On 01/20/2018 11:13 AM, David Lechner wrote: > This adds platform-specific declarations for the PLL clocks on TI DA850/ > OMAP-L138/AM18XX SoCs. > > Signed-off-by: David Lechner <david@lechnology.com> > --- > > v6 changes: > - Added da850_pll{0,1}_info with controller-specific information > - Added OBSCLK data > - Add empty lines between function calls > > drivers/clk/davinci/Makefile | 1 + > drivers/clk/davinci/pll-da850.c | 163 ++++++++++++++++++++++++++++++++++++++++ > include/linux/clk/davinci.h | 1 + > 3 files changed, 165 insertions(+) > create mode 100644 drivers/clk/davinci/pll-da850.c > > diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile > index 9061e19..13049d4 100644 > --- a/drivers/clk/davinci/Makefile > +++ b/drivers/clk/davinci/Makefile > @@ -3,4 +3,5 @@ > ifeq ($(CONFIG_COMMON_CLK), y) > obj-y += pll.o > obj-$(CONFIG_ARCH_DAVINCI_DA830) += pll-da830.o > +obj-$(CONFIG_ARCH_DAVINCI_DA850) += pll-da850.o > endif > diff --git a/drivers/clk/davinci/pll-da850.c b/drivers/clk/davinci/pll-da850.c > new file mode 100644 > index 0000000..a94e1a6 > --- /dev/null > +++ b/drivers/clk/davinci/pll-da850.c > @@ -0,0 +1,163 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * PLL clock descriptions for TI DA850/OMAP-L138/AM18XX > + * > + * Copyright (C) 2018 David Lechner <david@lechnology.com> > + */ > + > +#include <linux/bitops.h> > +#include <linux/clk-provider.h> > +#include <linux/clkdev.h> > +#include <linux/init.h> > +#include <linux/kernel.h> > +#include <linux/mfd/da8xx-cfgchip.h> > +#include <linux/of.h> > +#include <linux/types.h> > + > +#include "pll.h" > + > +#define OCSEL_OCSRC_OSCIN 0x14 > +#define OCSEL_OCSRC_PLL0_SYSCLK(n) (0x16 + (n)) > +#define OCSEL_OCSRC_PLL1_OBSCLK 0x1e > +#define OCSEL_OCSRC_PLL1_SYSCLK(n) (0x16 + (n)) > + > +static const struct davinci_pll_clk_info da850_pll0_info __initconst = { > + .name = "pll0", > + .unlock_reg = CFGCHIP(0), > + .unlock_mask = CFGCHIP0_PLL_MASTER_LOCK, > + .pllm_mask = GENMASK(4, 0), > + .pllm_min = 4, > + .pllm_max = 32, > + .pllout_min_rate = 300000000, > + .pllout_max_rate = 600000000, > + .flags = PLL_HAS_OSCIN | PLL_HAS_PREDIV | PLL_HAS_POSTDIV | > + PLL_HAS_EXTCLKSRC, > +}; > + > +/* > + * NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio", > + * meaning that we could change the divider as long as we keep the correct > + * ratio between all of the clocks, but we don't support that because there is > + * currently not a need for it. > + */ > + > +static const struct davinci_pll_sysclk_info da850_pll0_sysclk_info[] __initconst = { > + SYSCLK(1, pll0_sysclk1, pll0_pllen, 5, SYSCLK_FIXED_DIV), > + SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV), > + SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0), > + SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV), > + SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0), > + SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_ARM_RATE | SYSCLK_FIXED_DIV), > + SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0), > + { } > +}; > + > +static const char * const da850_pll0_obsclk_parent_names[] __initconst = { > + "oscin", > + "pll0_sysclk1", > + "pll0_sysclk2", > + "pll0_sysclk3", > + "pll0_sysclk4", > + "pll0_sysclk5", > + "pll0_sysclk6", > + "pll0_sysclk7", > + "pll1_obsclk", > +}; > + > +static u32 da850_pll0_obsclk_table[] = { > + OCSEL_OCSRC_OSCIN, > + OCSEL_OCSRC_PLL0_SYSCLK(1), > + OCSEL_OCSRC_PLL0_SYSCLK(2), > + OCSEL_OCSRC_PLL0_SYSCLK(3), > + OCSEL_OCSRC_PLL0_SYSCLK(4), > + OCSEL_OCSRC_PLL0_SYSCLK(5), > + OCSEL_OCSRC_PLL0_SYSCLK(6), > + OCSEL_OCSRC_PLL0_SYSCLK(7), > + OCSEL_OCSRC_PLL1_OBSCLK, > +}; > + > +static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info __initconst = { > + .name = "pll0_obsclk", > + .parent_names = da850_pll0_obsclk_parent_names, > + .num_parents = ARRAY_SIZE(da850_pll0_obsclk_parent_names), > + .table = da850_pll0_obsclk_table, > + .ocsrc_mask = GENMASK(4, 0), > +}; > + > +static const struct davinci_pll_clk_info da850_pll1_info __initconst = { > + .name = "pll1", > + .unlock_reg = CFGCHIP(3), > + .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, > + .pllm_mask = GENMASK(4, 0), > + .pllm_min = 4, > + .pllm_max = 32, > + .pllout_min_rate = 300000000, > + .pllout_max_rate = 600000000, > + .flags = PLL_HAS_POSTDIV, > +}; > + > +static const struct davinci_pll_sysclk_info da850_pll1_sysclk_info[] __initconst = { > + SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED), > + SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, 0), > + SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, 0), > + { } > +}; > + > +static const char * const da850_pll1_obsclk_parent_names[] __initconst = { > + "oscin", Re: the issue of "ref_clk" vs. "oscin"... This is one of the places where having the otherwise unnecessary "oscin" clock really helps out. The PLL driver doesn't control "ref_clk" - it comes from somewhere else. And in the case of DT, it may not even be named "ref_clk", so we really don't want to hard-code the name "ref_clk" here. If we have to allow a variable name here, it just makes more work in the driver shuffling names around. And the name "oscin" totally makes sense here because the TRM lists this input to the mux as "OSCIN". > + "pll1_sysclk1", > + "pll1_sysclk2", > + "pll1_sysclk3", > +}; > + > +static u32 da850_pll1_obsclk_table[] = { > + OCSEL_OCSRC_OSCIN, > + OCSEL_OCSRC_PLL1_SYSCLK(1), > + OCSEL_OCSRC_PLL1_SYSCLK(2), > + OCSEL_OCSRC_PLL1_SYSCLK(3), > +}; > + > +static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info __initconst = { > + .name = "pll1_obsclk", > + .parent_names = da850_pll1_obsclk_parent_names, > + .num_parents = ARRAY_SIZE(da850_pll1_obsclk_parent_names), > + .table = da850_pll1_obsclk_table, > + .ocsrc_mask = GENMASK(4, 0), > +}; > + > +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) > +{ > + const struct davinci_pll_sysclk_info *info; > + > + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); And really, we probably shouldn't be hard-coding "ref_clk" here either. Basically, we are making the assumption that the board file has registered a clock named "ref_clk". It would probably be better to pass the name as a parameter. > + > + davinci_pll_auxclk_register("pll0_auxclk", pll0); > + > + for (info = da850_pll0_sysclk_info; info->name; info++) > + davinci_pll_sysclk_register(info, pll0); > + > + davinci_pll_obsclk_register(&da850_pll0_obsclk_info, pll0); > + > + davinci_pll_clk_register(&da850_pll1_info, "oscin", pll1); > + > + for (info = da850_pll1_sysclk_info; info->name; info++) > + davinci_pll_sysclk_register(info, pll1); > + > + davinci_pll_obsclk_register(&da850_pll1_obsclk_info, pll1); > +} > + > +#ifdef CONFIG_OF > +static void __init of_da850_pll0_auxclk_init(struct device_node *node) > +{ > + of_davinci_pll_init(node, &da850_pll0_info, &da850_pll0_obsclk_info, > + da850_pll0_sysclk_info, 7); > +} > +CLK_OF_DECLARE(da850_pll0_auxclk, "ti,da850-pll0", of_da850_pll0_auxclk_init); > + > +static void __init of_da850_pll1_auxclk_init(struct device_node *node) > +{ > + of_davinci_pll_init(node, &da850_pll1_info, &da850_pll1_obsclk_info, > + da850_pll1_sysclk_info, 3); > +} > +CLK_OF_DECLARE(da850_pll1_auxclk, "ti,da850-pll1", of_da850_pll1_auxclk_init); > +#endif > diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h > index 4f4d60d..7b08fe0 100644 > --- a/include/linux/clk/davinci.h > +++ b/include/linux/clk/davinci.h > @@ -10,5 +10,6 @@ > #include <linux/types.h> > > void da830_pll_clk_init(void __iomem *pll); > +void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1); > > #endif /* __LINUX_CLK_DAVINCI_H__ */ >
On Friday 02 February 2018 12:34 AM, David Lechner wrote: > On 02/01/2018 02:58 AM, Sekhar Nori wrote: >> On Saturday 20 January 2018 10:43 PM, David Lechner wrote: >>> This adds platform-specific declarations for the PLL clocks on TI DA850/ >>> OMAP-L138/AM18XX SoCs. >>> >>> Signed-off-by: David Lechner <david@lechnology.com> >> >>> +static const struct davinci_pll_clk_info da850_pll1_info __initconst >>> = { >>> + .name = "pll1", >>> + .unlock_reg = CFGCHIP(3), >>> + .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, >> >> I guess this will change with the cfgchip handling discussion last week. > > Actually no, there really weren't any changes to the clock drivers because > of this change. Only a small change in mach-davinci. > >> >>> + .pllm_mask = GENMASK(4, 0), >>> + .pllm_min = 4, >>> + .pllm_max = 32, >>> + .pllout_min_rate = 300000000, >>> + .pllout_max_rate = 600000000, >>> + .flags = PLL_HAS_POSTDIV, >>> +}; >>> + >> >> [...] >> >>> +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) >>> +{ >>> + const struct davinci_pll_sysclk_info *info; >>> + >>> + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); >>> + >>> + davinci_pll_auxclk_register("pll0_auxclk", pll0); >>> + >>> + for (info = da850_pll0_sysclk_info; info->name; info++) >>> + davinci_pll_sysclk_register(info, pll0); >>> + >>> + davinci_pll_obsclk_register(&da850_pll0_obsclk_info, pll0); >>> + >>> + davinci_pll_clk_register(&da850_pll1_info, "oscin", pll1); >> >> Both PLL0 and PLL1 use the same reference clock. So this should be >> "ref_clk". I dont think we ever need to register a clock called oscin >> along with "ref_clk". There is only one reference clock. It can either >> be obtained using internal oscillator or external oscillator. >> > > As per my response to the previous path, this depends on which both > which SoC and which diagram in the TRM for that SoC you are looking at. > It works either way. I see the distinction you are making between clock inputs to the two PLLs now. A comment somewhere (probably in pll.c) should do it. Thanks, Sekhar
On Friday 02 February 2018 12:52 AM, David Lechner wrote: >> +static const char * const da850_pll1_obsclk_parent_names[] >> __initconst = { >> + "oscin", > > Re: the issue of "ref_clk" vs. "oscin"... > > This is one of the places where having the otherwise unnecessary "oscin" > clock > really helps out. The PLL driver doesn't control "ref_clk" - it comes > from somewhere > else. And in the case of DT, it may not even be named "ref_clk", so we > really > don't want to hard-code the name "ref_clk" here. TBH, I don't really see what is wrong with mandating the name "ref_clk" as the reference clock name to be provided. And for all board-files and DTs to supply the same name. > If we have to allow a variable name here, it just makes more work in the > driver > shuffling names around. > > And the name "oscin" totally makes sense here because the TRM lists this > input to the > mux as "OSCIN". Fine with me if you feel it simplifies implementation for you (and also because of the distinction you want to make between the external "before CLKMODE" clock and internal "after CLKMODE" clock). What I do care about though is: a) In the DT case, ability for different boards to provide different ref_clk frequencies. We never really had this in the legacy board file way (except some rudimentary support on DM6467T). And its fine to continue with status quo for board files. b) In the DT case, ability for board to specify whether it uses the on-chip oscillator or has an external clean clock provider. >> +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) >> +{ >> + const struct davinci_pll_sysclk_info *info; >> + >> + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); > > And really, we probably shouldn't be hard-coding "ref_clk" here either. > Basically, we are making the assumption that the board file has registered > a clock named "ref_clk". It would probably be better to pass the name > as a parameter. As I noted before, I am not sure if this level of naming flexibility is needed. Every board needs to have one anyway. They might as well call it by the same name. That said, I wont oppose it either if you decide to have that flexibility. Thanks, Sekhar
On 02/02/2018 02:37 AM, Sekhar Nori wrote: > On Friday 02 February 2018 12:52 AM, David Lechner wrote: > >>> +static const char * const da850_pll1_obsclk_parent_names[] >>> __initconst = { >>> + "oscin", >> >> Re: the issue of "ref_clk" vs. "oscin"... >> >> This is one of the places where having the otherwise unnecessary "oscin" >> clock >> really helps out. The PLL driver doesn't control "ref_clk" - it comes >> from somewhere >> else. And in the case of DT, it may not even be named "ref_clk", so we >> really >> don't want to hard-code the name "ref_clk" here. > > TBH, I don't really see what is wrong with mandating the name "ref_clk" > as the reference clock name to be provided. And for all board-files and > DTs to supply the same name. > >> If we have to allow a variable name here, it just makes more work in the >> driver >> shuffling names around. >> >> And the name "oscin" totally makes sense here because the TRM lists this >> input to the >> mux as "OSCIN". > > Fine with me if you feel it simplifies implementation for you (and also > because of the distinction you want to make between the external "before > CLKMODE" clock and internal "after CLKMODE" clock). What I do care about > though is: > > a) In the DT case, ability for different boards to provide different > ref_clk frequencies. We never really had this in the legacy board > file way (except some rudimentary support on DM6467T). And its fine > to continue with status quo for board files. You can do this now. You would just add something like this to the board's .dts file: & ref_clk { clock-frequency = <30000000>; /* 30 MHz */ }; > > b) In the DT case, ability for board to specify whether it uses the > on-chip oscillator or has an external clean clock provider. Boards with an oscillator don't need to do anything since that is the default. Boards with clock will need to do this: &pll0 { ti,clkmode-square-wave; }; > >>> +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) >>> +{ >>> + const struct davinci_pll_sysclk_info *info; >>> + >>> + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); >> >> And really, we probably shouldn't be hard-coding "ref_clk" here either. >> Basically, we are making the assumption that the board file has registered >> a clock named "ref_clk". It would probably be better to pass the name >> as a parameter. > > As I noted before, I am not sure if this level of naming flexibility is > needed. Every board needs to have one anyway. They might as well call it > by the same name. > > That said, I wont oppose it either if you decide to have that flexibility. > I'll sleep on it. Like you, I could go either way. I'm temped to just leave it as-is though (with some added comments for clarification, of course).
diff --git a/drivers/clk/davinci/Makefile b/drivers/clk/davinci/Makefile index 9061e19..13049d4 100644 --- a/drivers/clk/davinci/Makefile +++ b/drivers/clk/davinci/Makefile @@ -3,4 +3,5 @@ ifeq ($(CONFIG_COMMON_CLK), y) obj-y += pll.o obj-$(CONFIG_ARCH_DAVINCI_DA830) += pll-da830.o +obj-$(CONFIG_ARCH_DAVINCI_DA850) += pll-da850.o endif diff --git a/drivers/clk/davinci/pll-da850.c b/drivers/clk/davinci/pll-da850.c new file mode 100644 index 0000000..a94e1a6 --- /dev/null +++ b/drivers/clk/davinci/pll-da850.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PLL clock descriptions for TI DA850/OMAP-L138/AM18XX + * + * Copyright (C) 2018 David Lechner <david@lechnology.com> + */ + +#include <linux/bitops.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mfd/da8xx-cfgchip.h> +#include <linux/of.h> +#include <linux/types.h> + +#include "pll.h" + +#define OCSEL_OCSRC_OSCIN 0x14 +#define OCSEL_OCSRC_PLL0_SYSCLK(n) (0x16 + (n)) +#define OCSEL_OCSRC_PLL1_OBSCLK 0x1e +#define OCSEL_OCSRC_PLL1_SYSCLK(n) (0x16 + (n)) + +static const struct davinci_pll_clk_info da850_pll0_info __initconst = { + .name = "pll0", + .unlock_reg = CFGCHIP(0), + .unlock_mask = CFGCHIP0_PLL_MASTER_LOCK, + .pllm_mask = GENMASK(4, 0), + .pllm_min = 4, + .pllm_max = 32, + .pllout_min_rate = 300000000, + .pllout_max_rate = 600000000, + .flags = PLL_HAS_OSCIN | PLL_HAS_PREDIV | PLL_HAS_POSTDIV | + PLL_HAS_EXTCLKSRC, +}; + +/* + * NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio", + * meaning that we could change the divider as long as we keep the correct + * ratio between all of the clocks, but we don't support that because there is + * currently not a need for it. + */ + +static const struct davinci_pll_sysclk_info da850_pll0_sysclk_info[] __initconst = { + SYSCLK(1, pll0_sysclk1, pll0_pllen, 5, SYSCLK_FIXED_DIV), + SYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV), + SYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0), + SYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV), + SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0), + SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_ARM_RATE | SYSCLK_FIXED_DIV), + SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0), + { } +}; + +static const char * const da850_pll0_obsclk_parent_names[] __initconst = { + "oscin", + "pll0_sysclk1", + "pll0_sysclk2", + "pll0_sysclk3", + "pll0_sysclk4", + "pll0_sysclk5", + "pll0_sysclk6", + "pll0_sysclk7", + "pll1_obsclk", +}; + +static u32 da850_pll0_obsclk_table[] = { + OCSEL_OCSRC_OSCIN, + OCSEL_OCSRC_PLL0_SYSCLK(1), + OCSEL_OCSRC_PLL0_SYSCLK(2), + OCSEL_OCSRC_PLL0_SYSCLK(3), + OCSEL_OCSRC_PLL0_SYSCLK(4), + OCSEL_OCSRC_PLL0_SYSCLK(5), + OCSEL_OCSRC_PLL0_SYSCLK(6), + OCSEL_OCSRC_PLL0_SYSCLK(7), + OCSEL_OCSRC_PLL1_OBSCLK, +}; + +static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info __initconst = { + .name = "pll0_obsclk", + .parent_names = da850_pll0_obsclk_parent_names, + .num_parents = ARRAY_SIZE(da850_pll0_obsclk_parent_names), + .table = da850_pll0_obsclk_table, + .ocsrc_mask = GENMASK(4, 0), +}; + +static const struct davinci_pll_clk_info da850_pll1_info __initconst = { + .name = "pll1", + .unlock_reg = CFGCHIP(3), + .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, + .pllm_mask = GENMASK(4, 0), + .pllm_min = 4, + .pllm_max = 32, + .pllout_min_rate = 300000000, + .pllout_max_rate = 600000000, + .flags = PLL_HAS_POSTDIV, +}; + +static const struct davinci_pll_sysclk_info da850_pll1_sysclk_info[] __initconst = { + SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED), + SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, 0), + SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, 0), + { } +}; + +static const char * const da850_pll1_obsclk_parent_names[] __initconst = { + "oscin", + "pll1_sysclk1", + "pll1_sysclk2", + "pll1_sysclk3", +}; + +static u32 da850_pll1_obsclk_table[] = { + OCSEL_OCSRC_OSCIN, + OCSEL_OCSRC_PLL1_SYSCLK(1), + OCSEL_OCSRC_PLL1_SYSCLK(2), + OCSEL_OCSRC_PLL1_SYSCLK(3), +}; + +static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info __initconst = { + .name = "pll1_obsclk", + .parent_names = da850_pll1_obsclk_parent_names, + .num_parents = ARRAY_SIZE(da850_pll1_obsclk_parent_names), + .table = da850_pll1_obsclk_table, + .ocsrc_mask = GENMASK(4, 0), +}; + +void __init da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1) +{ + const struct davinci_pll_sysclk_info *info; + + davinci_pll_clk_register(&da850_pll0_info, "ref_clk", pll0); + + davinci_pll_auxclk_register("pll0_auxclk", pll0); + + for (info = da850_pll0_sysclk_info; info->name; info++) + davinci_pll_sysclk_register(info, pll0); + + davinci_pll_obsclk_register(&da850_pll0_obsclk_info, pll0); + + davinci_pll_clk_register(&da850_pll1_info, "oscin", pll1); + + for (info = da850_pll1_sysclk_info; info->name; info++) + davinci_pll_sysclk_register(info, pll1); + + davinci_pll_obsclk_register(&da850_pll1_obsclk_info, pll1); +} + +#ifdef CONFIG_OF +static void __init of_da850_pll0_auxclk_init(struct device_node *node) +{ + of_davinci_pll_init(node, &da850_pll0_info, &da850_pll0_obsclk_info, + da850_pll0_sysclk_info, 7); +} +CLK_OF_DECLARE(da850_pll0_auxclk, "ti,da850-pll0", of_da850_pll0_auxclk_init); + +static void __init of_da850_pll1_auxclk_init(struct device_node *node) +{ + of_davinci_pll_init(node, &da850_pll1_info, &da850_pll1_obsclk_info, + da850_pll1_sysclk_info, 3); +} +CLK_OF_DECLARE(da850_pll1_auxclk, "ti,da850-pll1", of_da850_pll1_auxclk_init); +#endif diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h index 4f4d60d..7b08fe0 100644 --- a/include/linux/clk/davinci.h +++ b/include/linux/clk/davinci.h @@ -10,5 +10,6 @@ #include <linux/types.h> void da830_pll_clk_init(void __iomem *pll); +void da850_pll_clk_init(void __iomem *pll0, void __iomem *pll1); #endif /* __LINUX_CLK_DAVINCI_H__ */
This adds platform-specific declarations for the PLL clocks on TI DA850/ OMAP-L138/AM18XX SoCs. Signed-off-by: David Lechner <david@lechnology.com> --- v6 changes: - Added da850_pll{0,1}_info with controller-specific information - Added OBSCLK data - Add empty lines between function calls drivers/clk/davinci/Makefile | 1 + drivers/clk/davinci/pll-da850.c | 163 ++++++++++++++++++++++++++++++++++++++++ include/linux/clk/davinci.h | 1 + 3 files changed, 165 insertions(+) create mode 100644 drivers/clk/davinci/pll-da850.c