Message ID | 20190402125056.21509-8-alexandre.belloni@bootlin.com (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
Series | clk: at91: add sam9x60 pmc clock support | expand |
Quoting Alexandre Belloni (2019-04-02 05:50:56) > diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c > new file mode 100644 > index 000000000000..22bf51c55bdc > --- /dev/null > +++ b/drivers/clk/at91/sam9x60.c > @@ -0,0 +1,307 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include <linux/clk-provider.h> > +#include <linux/mfd/syscon.h> > +#include <linux/slab.h> > + > +#include <dt-bindings/clock/at91.h> > + > +#include "pmc.h" > + > +DEFINE_SPINLOCK(pmc_pll_lock); > + > +static const struct clk_master_characteristics mck_characteristics = { > + .output = { .min = 140000000, .max = 200000000 }, > + .divisors = { 1, 2, 4, 3 }, > + .have_div3_pres = 1, > +}; > + > +static const struct clk_master_layout sam9x60_master_layout = { > + .mask = 0x373, > + .pres_shift = 4, > + .offset = 0x28, > +}; > + > +static struct clk_range plla_outputs[] = { const? > + { .min = 300000000, .max = 600000000 }, > +}; [...] > + > +} > + > +CLK_OF_DECLARE_DRIVER(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup); > -- Can't be platform device?
On 25/04/2019 12:38:55-0700, Stephen Boyd wrote: > Quoting Alexandre Belloni (2019-04-02 05:50:56) > > diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c > > new file mode 100644 > > index 000000000000..22bf51c55bdc > > --- /dev/null > > +++ b/drivers/clk/at91/sam9x60.c > > @@ -0,0 +1,307 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +#include <linux/clk-provider.h> > > +#include <linux/mfd/syscon.h> > > +#include <linux/slab.h> > > + > > +#include <dt-bindings/clock/at91.h> > > + > > +#include "pmc.h" > > + > > +DEFINE_SPINLOCK(pmc_pll_lock); > > + > > +static const struct clk_master_characteristics mck_characteristics = { > > + .output = { .min = 140000000, .max = 200000000 }, > > + .divisors = { 1, 2, 4, 3 }, > > + .have_div3_pres = 1, > > +}; > > + > > +static const struct clk_master_layout sam9x60_master_layout = { > > + .mask = 0x373, > > + .pres_shift = 4, > > + .offset = 0x28, > > +}; > > + > > +static struct clk_range plla_outputs[] = { > > const? > Right, can you fix that up or should I send a new version? > > + { .min = 300000000, .max = 600000000 }, > > +}; > [...] > > + > > +} > > + > > +CLK_OF_DECLARE_DRIVER(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup); > > -- > > Can't be platform device? > IIRC two clocks are used by the clocksource and having it as a platform device make the clocksource driver fail with -EPROBE_DEFER.
Quoting Alexandre Belloni (2019-04-25 13:31:39) > On 25/04/2019 12:38:55-0700, Stephen Boyd wrote: > > Quoting Alexandre Belloni (2019-04-02 05:50:56) > > > diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c > > > new file mode 100644 > > > index 000000000000..22bf51c55bdc > > > --- /dev/null > > > +++ b/drivers/clk/at91/sam9x60.c > > > @@ -0,0 +1,307 @@ > > > +// SPDX-License-Identifier: GPL-2.0 > > > +#include <linux/clk-provider.h> > > > +#include <linux/mfd/syscon.h> > > > +#include <linux/slab.h> > > > + > > > +#include <dt-bindings/clock/at91.h> > > > + > > > +#include "pmc.h" > > > + > > > +DEFINE_SPINLOCK(pmc_pll_lock); > > > + > > > +static const struct clk_master_characteristics mck_characteristics = { > > > + .output = { .min = 140000000, .max = 200000000 }, > > > + .divisors = { 1, 2, 4, 3 }, > > > + .have_div3_pres = 1, > > > +}; > > > + > > > +static const struct clk_master_layout sam9x60_master_layout = { > > > + .mask = 0x373, > > > + .pres_shift = 4, > > > + .offset = 0x28, > > > +}; > > > + > > > +static struct clk_range plla_outputs[] = { > > > > const? > > > > Right, can you fix that up or should I send a new version? > I can fix it. > > > + { .min = 300000000, .max = 600000000 }, > > > +}; > > [...] > > > + > > > +} > > > + > > > +CLK_OF_DECLARE_DRIVER(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup); > > > -- > > > > Can't be platform device? > > > > IIRC two clocks are used by the clocksource and having it as a platform > device make the clocksource driver fail with -EPROBE_DEFER. > Ok. I'll add a comment in the driver. It needs to be CLK_OF_DECLARE_DRIVER() because it's used somewhere else too? Or it can be CLK_OF_DECLARE() instead?
On 25/04/2019 13:58:10-0700, Stephen Boyd wrote: > > IIRC two clocks are used by the clocksource and having it as a platform > > device make the clocksource driver fail with -EPROBE_DEFER. > > > > Ok. I'll add a comment in the driver. It needs to be > CLK_OF_DECLARE_DRIVER() because it's used somewhere else too? Or it can > be CLK_OF_DECLARE() instead? It is coming from that comment: https://lore.kernel.org/lkml/153573753043.93865.2420370848457480370@swboyd.mtv.corp.google.com/ Maybe I misinterpreted it.
Quoting Stephen Boyd (2019-04-25 13:58:10) > Quoting Alexandre Belloni (2019-04-25 13:31:39) > > On 25/04/2019 12:38:55-0700, Stephen Boyd wrote: > > > > > > const? > > > > > > > Right, can you fix that up or should I send a new version? > > > > I can fix it. It's more complicated. I'll pile this patch on top. Maybe other static data in drivers/clk/at91 can be const, but this at least covers the struct clk_range ones. diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c index b1af5a395423..0aabe49aed09 100644 --- a/drivers/clk/at91/at91sam9260.c +++ b/drivers/clk/at91/at91sam9260.c @@ -41,7 +41,7 @@ static u8 sam9260_plla_out[] = { 0, 2 }; static u16 sam9260_plla_icpll[] = { 1, 1 }; -static struct clk_range sam9260_plla_outputs[] = { +static const struct clk_range sam9260_plla_outputs[] = { { .min = 80000000, .max = 160000000 }, { .min = 150000000, .max = 240000000 }, }; @@ -58,7 +58,7 @@ static u8 sam9260_pllb_out[] = { 1 }; static u16 sam9260_pllb_icpll[] = { 1 }; -static struct clk_range sam9260_pllb_outputs[] = { +static const struct clk_range sam9260_pllb_outputs[] = { { .min = 70000000, .max = 130000000 }, }; @@ -128,7 +128,7 @@ static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; -static struct clk_range sam9g20_plla_outputs[] = { +static const struct clk_range sam9g20_plla_outputs[] = { { .min = 745000000, .max = 800000000 }, { .min = 695000000, .max = 750000000 }, { .min = 645000000, .max = 700000000 }, @@ -151,7 +151,7 @@ static u8 sam9g20_pllb_out[] = { 0 }; static u16 sam9g20_pllb_icpll[] = { 0 }; -static struct clk_range sam9g20_pllb_outputs[] = { +static const struct clk_range sam9g20_pllb_outputs[] = { { .min = 30000000, .max = 100000000 }, }; @@ -182,7 +182,7 @@ static const struct clk_master_characteristics sam9261_mck_characteristics = { .divisors = { 1, 2, 4, 0 }, }; -static struct clk_range sam9261_plla_outputs[] = { +static const struct clk_range sam9261_plla_outputs[] = { { .min = 80000000, .max = 200000000 }, { .min = 190000000, .max = 240000000 }, }; @@ -199,7 +199,7 @@ static u8 sam9261_pllb_out[] = { 1 }; static u16 sam9261_pllb_icpll[] = { 1 }; -static struct clk_range sam9261_pllb_outputs[] = { +static const struct clk_range sam9261_pllb_outputs[] = { { .min = 70000000, .max = 130000000 }, }; @@ -262,7 +262,7 @@ static const struct clk_master_characteristics sam9263_mck_characteristics = { .divisors = { 1, 2, 4, 0 }, }; -static struct clk_range sam9263_pll_outputs[] = { +static const struct clk_range sam9263_pll_outputs[] = { { .min = 80000000, .max = 200000000 }, { .min = 190000000, .max = 240000000 }, }; diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c index 5aeef68b4bdd..0ac34cdaa106 100644 --- a/drivers/clk/at91/at91sam9rl.c +++ b/drivers/clk/at91/at91sam9rl.c @@ -14,7 +14,7 @@ static const struct clk_master_characteristics sam9rl_mck_characteristics = { static u8 sam9rl_plla_out[] = { 0, 2 }; -static struct clk_range sam9rl_plla_outputs[] = { +static const struct clk_range sam9rl_plla_outputs[] = { { .min = 80000000, .max = 200000000 }, { .min = 190000000, .max = 240000000 }, }; diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c index f5cfcbd85f10..0855f3a80cc7 100644 --- a/drivers/clk/at91/at91sam9x5.c +++ b/drivers/clk/at91/at91sam9x5.c @@ -17,7 +17,7 @@ static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; -static struct clk_range plla_outputs[] = { +static const struct clk_range plla_outputs[] = { { .min = 745000000, .max = 800000000 }, { .min = 695000000, .max = 750000000 }, { .min = 645000000, .max = 700000000 }, diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index fb9e9c4cdc8d..775b77a433f5 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -66,7 +66,7 @@ extern const struct clk_pll_layout sama5d3_pll_layout; struct clk_pll_characteristics { struct clk_range input; int num_output; - struct clk_range *output; + const struct clk_range *output; u16 *icpll; u8 *out; u8 upll : 1; diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index 864ac060aed6..6340b1fc1828 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -21,7 +21,7 @@ static const struct clk_master_layout sam9x60_master_layout = { .offset = 0x28, }; -static struct clk_range plla_outputs[] = { +static const struct clk_range plla_outputs[] = { { .min = 300000000, .max = 600000000 }, }; @@ -31,7 +31,7 @@ static const struct clk_pll_characteristics plla_characteristics = { .output = plla_outputs, }; -static struct clk_range upll_outputs[] = { +static const struct clk_range upll_outputs[] = { { .min = 300000000, .max = 500000000 }, }; diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c index 096156850e08..f3d3f6c8e261 100644 --- a/drivers/clk/at91/sama5d2.c +++ b/drivers/clk/at91/sama5d2.c @@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 }; static u16 plla_icpll[] = { 0 }; -static struct clk_range plla_outputs[] = { +static const struct clk_range plla_outputs[] = { { .min = 600000000, .max = 1200000000 }, }; diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c index 840edca77821..25b156d4e645 100644 --- a/drivers/clk/at91/sama5d4.c +++ b/drivers/clk/at91/sama5d4.c @@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 }; static u16 plla_icpll[] = { 0 }; -static struct clk_range plla_outputs[] = { +static const struct clk_range plla_outputs[] = { { .min = 600000000, .max = 1200000000 }, };
Quoting Alexandre Belloni (2019-04-25 14:10:09) > On 25/04/2019 13:58:10-0700, Stephen Boyd wrote: > > > IIRC two clocks are used by the clocksource and having it as a platform > > > device make the clocksource driver fail with -EPROBE_DEFER. > > > > > > > Ok. I'll add a comment in the driver. It needs to be > > CLK_OF_DECLARE_DRIVER() because it's used somewhere else too? Or it can > > be CLK_OF_DECLARE() instead? > > It is coming from that comment: > https://lore.kernel.org/lkml/153573753043.93865.2420370848457480370@swboyd.mtv.corp.google.com/ > > Maybe I misinterpreted it. > Hmm I was just confused it seems. If you don't have two devices probing the same DT node with this compatible string then I think it can just be CLK_OF_DECLARE(). I was thinking that you were running into some sort of issue where the other driver using this same compatible couldn't probe.
On 25/04/2019 14:14:54-0700, Stephen Boyd wrote: > Quoting Stephen Boyd (2019-04-25 13:58:10) > > Quoting Alexandre Belloni (2019-04-25 13:31:39) > > > On 25/04/2019 12:38:55-0700, Stephen Boyd wrote: > > > > > > > > const? > > > > > > > > > > Right, can you fix that up or should I send a new version? > > > > > > > I can fix it. > > It's more complicated. I'll pile this patch on top. Maybe other > static data in drivers/clk/at91 can be const, but this at least covers > the struct clk_range ones. > Seems good to me. > diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c > index b1af5a395423..0aabe49aed09 100644 > --- a/drivers/clk/at91/at91sam9260.c > +++ b/drivers/clk/at91/at91sam9260.c > @@ -41,7 +41,7 @@ static u8 sam9260_plla_out[] = { 0, 2 }; > > static u16 sam9260_plla_icpll[] = { 1, 1 }; > > -static struct clk_range sam9260_plla_outputs[] = { > +static const struct clk_range sam9260_plla_outputs[] = { > { .min = 80000000, .max = 160000000 }, > { .min = 150000000, .max = 240000000 }, > }; > @@ -58,7 +58,7 @@ static u8 sam9260_pllb_out[] = { 1 }; > > static u16 sam9260_pllb_icpll[] = { 1 }; > > -static struct clk_range sam9260_pllb_outputs[] = { > +static const struct clk_range sam9260_pllb_outputs[] = { > { .min = 70000000, .max = 130000000 }, > }; > > @@ -128,7 +128,7 @@ static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; > > static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; > > -static struct clk_range sam9g20_plla_outputs[] = { > +static const struct clk_range sam9g20_plla_outputs[] = { > { .min = 745000000, .max = 800000000 }, > { .min = 695000000, .max = 750000000 }, > { .min = 645000000, .max = 700000000 }, > @@ -151,7 +151,7 @@ static u8 sam9g20_pllb_out[] = { 0 }; > > static u16 sam9g20_pllb_icpll[] = { 0 }; > > -static struct clk_range sam9g20_pllb_outputs[] = { > +static const struct clk_range sam9g20_pllb_outputs[] = { > { .min = 30000000, .max = 100000000 }, > }; > > @@ -182,7 +182,7 @@ static const struct clk_master_characteristics sam9261_mck_characteristics = { > .divisors = { 1, 2, 4, 0 }, > }; > > -static struct clk_range sam9261_plla_outputs[] = { > +static const struct clk_range sam9261_plla_outputs[] = { > { .min = 80000000, .max = 200000000 }, > { .min = 190000000, .max = 240000000 }, > }; > @@ -199,7 +199,7 @@ static u8 sam9261_pllb_out[] = { 1 }; > > static u16 sam9261_pllb_icpll[] = { 1 }; > > -static struct clk_range sam9261_pllb_outputs[] = { > +static const struct clk_range sam9261_pllb_outputs[] = { > { .min = 70000000, .max = 130000000 }, > }; > > @@ -262,7 +262,7 @@ static const struct clk_master_characteristics sam9263_mck_characteristics = { > .divisors = { 1, 2, 4, 0 }, > }; > > -static struct clk_range sam9263_pll_outputs[] = { > +static const struct clk_range sam9263_pll_outputs[] = { > { .min = 80000000, .max = 200000000 }, > { .min = 190000000, .max = 240000000 }, > }; > diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c > index 5aeef68b4bdd..0ac34cdaa106 100644 > --- a/drivers/clk/at91/at91sam9rl.c > +++ b/drivers/clk/at91/at91sam9rl.c > @@ -14,7 +14,7 @@ static const struct clk_master_characteristics sam9rl_mck_characteristics = { > > static u8 sam9rl_plla_out[] = { 0, 2 }; > > -static struct clk_range sam9rl_plla_outputs[] = { > +static const struct clk_range sam9rl_plla_outputs[] = { > { .min = 80000000, .max = 200000000 }, > { .min = 190000000, .max = 240000000 }, > }; > diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c > index f5cfcbd85f10..0855f3a80cc7 100644 > --- a/drivers/clk/at91/at91sam9x5.c > +++ b/drivers/clk/at91/at91sam9x5.c > @@ -17,7 +17,7 @@ static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 }; > > static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 }; > > -static struct clk_range plla_outputs[] = { > +static const struct clk_range plla_outputs[] = { > { .min = 745000000, .max = 800000000 }, > { .min = 695000000, .max = 750000000 }, > { .min = 645000000, .max = 700000000 }, > diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h > index fb9e9c4cdc8d..775b77a433f5 100644 > --- a/drivers/clk/at91/pmc.h > +++ b/drivers/clk/at91/pmc.h > @@ -66,7 +66,7 @@ extern const struct clk_pll_layout sama5d3_pll_layout; > struct clk_pll_characteristics { > struct clk_range input; > int num_output; > - struct clk_range *output; > + const struct clk_range *output; > u16 *icpll; > u8 *out; > u8 upll : 1; > diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c > index 864ac060aed6..6340b1fc1828 100644 > --- a/drivers/clk/at91/sam9x60.c > +++ b/drivers/clk/at91/sam9x60.c > @@ -21,7 +21,7 @@ static const struct clk_master_layout sam9x60_master_layout = { > .offset = 0x28, > }; > > -static struct clk_range plla_outputs[] = { > +static const struct clk_range plla_outputs[] = { > { .min = 300000000, .max = 600000000 }, > }; > > @@ -31,7 +31,7 @@ static const struct clk_pll_characteristics plla_characteristics = { > .output = plla_outputs, > }; > > -static struct clk_range upll_outputs[] = { > +static const struct clk_range upll_outputs[] = { > { .min = 300000000, .max = 500000000 }, > }; > > diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c > index 096156850e08..f3d3f6c8e261 100644 > --- a/drivers/clk/at91/sama5d2.c > +++ b/drivers/clk/at91/sama5d2.c > @@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 }; > > static u16 plla_icpll[] = { 0 }; > > -static struct clk_range plla_outputs[] = { > +static const struct clk_range plla_outputs[] = { > { .min = 600000000, .max = 1200000000 }, > }; > > diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c > index 840edca77821..25b156d4e645 100644 > --- a/drivers/clk/at91/sama5d4.c > +++ b/drivers/clk/at91/sama5d4.c > @@ -16,7 +16,7 @@ static u8 plla_out[] = { 0 }; > > static u16 plla_icpll[] = { 0 }; > > -static struct clk_range plla_outputs[] = { > +static const struct clk_range plla_outputs[] = { > { .min = 600000000, .max = 1200000000 }, > }; >
On 25/04/2019 14:20:41-0700, Stephen Boyd wrote: > Quoting Alexandre Belloni (2019-04-25 14:10:09) > > On 25/04/2019 13:58:10-0700, Stephen Boyd wrote: > > > > IIRC two clocks are used by the clocksource and having it as a platform > > > > device make the clocksource driver fail with -EPROBE_DEFER. > > > > > > > > > > Ok. I'll add a comment in the driver. It needs to be > > > CLK_OF_DECLARE_DRIVER() because it's used somewhere else too? Or it can > > > be CLK_OF_DECLARE() instead? > > > > It is coming from that comment: > > https://lore.kernel.org/lkml/153573753043.93865.2420370848457480370@swboyd.mtv.corp.google.com/ > > > > Maybe I misinterpreted it. > > > > Hmm I was just confused it seems. If you don't have two devices probing > the same DT node with this compatible string then I think it can just be > CLK_OF_DECLARE(). I was thinking that you were running into some sort of > issue where the other driver using this same compatible couldn't probe. > I tried separating it into two initializations and do as much as possible in the platform driver but because the TCB clocks are peripheral clocks that depend on most of the other ones, I didn't find it convenient. This can safely be changed to CLK_OF_DECLARE. I can send v4 if you want. This should probably be changed for the other drivers too.
Quoting Alexandre Belloni (2019-04-26 14:06:51) > On 25/04/2019 14:20:41-0700, Stephen Boyd wrote: > > > > Hmm I was just confused it seems. If you don't have two devices probing > > the same DT node with this compatible string then I think it can just be > > CLK_OF_DECLARE(). I was thinking that you were running into some sort of > > issue where the other driver using this same compatible couldn't probe. > > > > I tried separating it into two initializations and do as much as > possible in the platform driver but because the TCB clocks are > peripheral clocks that depend on most of the other ones, I didn't find > it convenient. This can safely be changed to CLK_OF_DECLARE. I can send > v4 if you want. This should probably be changed for the other drivers > too. I've fixed it locally, just haven't pushed it out. If you have other drivers that should be using CLK_OF_DECLARE then feel free to send a patch for it.
diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 0a30fc8dfcb0..3732241352ce 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -16,5 +16,6 @@ obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o obj-$(CONFIG_HAVE_AT91_SAM9X60_PLL) += clk-sam9x60-pll.o obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o +obj-$(CONFIG_SOC_SAM9X60) += sam9x60.o obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c new file mode 100644 index 000000000000..22bf51c55bdc --- /dev/null +++ b/drivers/clk/at91/sam9x60.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/clk-provider.h> +#include <linux/mfd/syscon.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/at91.h> + +#include "pmc.h" + +DEFINE_SPINLOCK(pmc_pll_lock); + +static const struct clk_master_characteristics mck_characteristics = { + .output = { .min = 140000000, .max = 200000000 }, + .divisors = { 1, 2, 4, 3 }, + .have_div3_pres = 1, +}; + +static const struct clk_master_layout sam9x60_master_layout = { + .mask = 0x373, + .pres_shift = 4, + .offset = 0x28, +}; + +static struct clk_range plla_outputs[] = { + { .min = 300000000, .max = 600000000 }, +}; + +static const struct clk_pll_characteristics plla_characteristics = { + .input = { .min = 12000000, .max = 48000000 }, + .num_output = ARRAY_SIZE(plla_outputs), + .output = plla_outputs, +}; + +static struct clk_range upll_outputs[] = { + { .min = 300000000, .max = 500000000 }, +}; + +static const struct clk_pll_characteristics upll_characteristics = { + .input = { .min = 12000000, .max = 48000000 }, + .num_output = ARRAY_SIZE(upll_outputs), + .output = upll_outputs, + .upll = true, +}; + +static const struct clk_programmable_layout sam9x60_programmable_layout = { + .pres_shift = 8, + .css_mask = 0x1f, + .have_slck_mck = 0, +}; + +static const struct clk_pcr_layout sam9x60_pcr_layout = { + .offset = 0x88, + .cmd = BIT(31), + .gckcss_mask = GENMASK(12, 8), + .pid_mask = GENMASK(6, 0), +}; + +static const struct { + char *n; + char *p; + u8 id; +} sam9x60_systemck[] = { + { .n = "ddrck", .p = "masterck", .id = 2 }, + { .n = "uhpck", .p = "usbck", .id = 6 }, + { .n = "pck0", .p = "prog0", .id = 8 }, + { .n = "pck1", .p = "prog1", .id = 9 }, + { .n = "qspick", .p = "masterck", .id = 19 }, +}; + +static const struct { + char *n; + u8 id; +} sam9x60_periphck[] = { + { .n = "pioA_clk", .id = 2, }, + { .n = "pioB_clk", .id = 3, }, + { .n = "pioC_clk", .id = 4, }, + { .n = "flex0_clk", .id = 5, }, + { .n = "flex1_clk", .id = 6, }, + { .n = "flex2_clk", .id = 7, }, + { .n = "flex3_clk", .id = 8, }, + { .n = "flex6_clk", .id = 9, }, + { .n = "flex7_clk", .id = 10, }, + { .n = "flex8_clk", .id = 11, }, + { .n = "sdmmc0_clk", .id = 12, }, + { .n = "flex4_clk", .id = 13, }, + { .n = "flex5_clk", .id = 14, }, + { .n = "flex9_clk", .id = 15, }, + { .n = "flex10_clk", .id = 16, }, + { .n = "tcb0_clk", .id = 17, }, + { .n = "pwm_clk", .id = 18, }, + { .n = "adc_clk", .id = 19, }, + { .n = "dma0_clk", .id = 20, }, + { .n = "matrix_clk", .id = 21, }, + { .n = "uhphs_clk", .id = 22, }, + { .n = "udphs_clk", .id = 23, }, + { .n = "macb0_clk", .id = 24, }, + { .n = "lcd_clk", .id = 25, }, + { .n = "sdmmc1_clk", .id = 26, }, + { .n = "macb1_clk", .id = 27, }, + { .n = "ssc_clk", .id = 28, }, + { .n = "can0_clk", .id = 29, }, + { .n = "can1_clk", .id = 30, }, + { .n = "flex11_clk", .id = 32, }, + { .n = "flex12_clk", .id = 33, }, + { .n = "i2s_clk", .id = 34, }, + { .n = "qspi_clk", .id = 35, }, + { .n = "gfx2d_clk", .id = 36, }, + { .n = "pit64b_clk", .id = 37, }, + { .n = "trng_clk", .id = 38, }, + { .n = "aes_clk", .id = 39, }, + { .n = "tdes_clk", .id = 40, }, + { .n = "sha_clk", .id = 41, }, + { .n = "classd_clk", .id = 42, }, + { .n = "isi_clk", .id = 43, }, + { .n = "pioD_clk", .id = 44, }, + { .n = "tcb1_clk", .id = 45, }, + { .n = "dbgu_clk", .id = 47, }, + { .n = "mpddr_clk", .id = 49, }, +}; + +static const struct { + char *n; + u8 id; + struct clk_range r; + bool pll; +} sam9x60_gck[] = { + { .n = "flex0_gclk", .id = 5, }, + { .n = "flex1_gclk", .id = 6, }, + { .n = "flex2_gclk", .id = 7, }, + { .n = "flex3_gclk", .id = 8, }, + { .n = "flex6_gclk", .id = 9, }, + { .n = "flex7_gclk", .id = 10, }, + { .n = "flex8_gclk", .id = 11, }, + { .n = "sdmmc0_gclk", .id = 12, .r = { .min = 0, .max = 105000000 }, }, + { .n = "flex4_gclk", .id = 13, }, + { .n = "flex5_gclk", .id = 14, }, + { .n = "flex9_gclk", .id = 15, }, + { .n = "flex10_gclk", .id = 16, }, + { .n = "tcb0_gclk", .id = 17, }, + { .n = "adc_gclk", .id = 19, }, + { .n = "lcd_gclk", .id = 25, .r = { .min = 0, .max = 140000000 }, }, + { .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, }, + { .n = "flex11_gclk", .id = 32, }, + { .n = "flex12_gclk", .id = 33, }, + { .n = "i2s_gclk", .id = 34, .r = { .min = 0, .max = 105000000 }, + .pll = true, }, + { .n = "pit64b_gclk", .id = 37, }, + { .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, + .pll = true, }, + { .n = "tcb1_gclk", .id = 45, }, + { .n = "dbgu_gclk", .id = 47, }, +}; + +static void __init sam9x60_pmc_setup(struct device_node *np) +{ + struct clk_range range = CLK_RANGE(0, 0); + const char *td_slck_name, *md_slck_name, *mainxtal_name; + struct pmc_data *sam9x60_pmc; + const char *parent_names[6]; + struct regmap *regmap; + struct clk_hw *hw; + int i; + bool bypass; + + i = of_property_match_string(np, "clock-names", "td_slck"); + if (i < 0) + return; + + td_slck_name = of_clk_get_parent_name(np, i); + + i = of_property_match_string(np, "clock-names", "md_slck"); + if (i < 0) + return; + + md_slck_name = of_clk_get_parent_name(np, i); + + i = of_property_match_string(np, "clock-names", "main_xtal"); + if (i < 0) + return; + mainxtal_name = of_clk_get_parent_name(np, i); + + regmap = syscon_node_to_regmap(np); + if (IS_ERR(regmap)) + return; + + sam9x60_pmc = pmc_data_allocate(PMC_MAIN + 1, + nck(sam9x60_systemck), + nck(sam9x60_periphck), + nck(sam9x60_gck)); + if (!sam9x60_pmc) + return; + + hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 24000000, + 50000000); + if (IS_ERR(hw)) + goto err_free; + + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + + hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, + bypass); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = "main_rc_osc"; + parent_names[1] = "main_osc"; + hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); + if (IS_ERR(hw)) + goto err_free; + + sam9x60_pmc->chws[PMC_MAIN] = hw; + + hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "pllack", + "mainck", 0, &plla_characteristics); + if (IS_ERR(hw)) + goto err_free; + + hw = sam9x60_clk_register_pll(regmap, &pmc_pll_lock, "upllck", + "main_osc", 1, &upll_characteristics); + if (IS_ERR(hw)) + goto err_free; + + sam9x60_pmc->chws[PMC_UTMI] = hw; + + parent_names[0] = md_slck_name; + parent_names[1] = "mainck"; + parent_names[2] = "pllack"; + hw = at91_clk_register_master(regmap, "masterck", 3, parent_names, + &sam9x60_master_layout, + &mck_characteristics); + if (IS_ERR(hw)) + goto err_free; + + sam9x60_pmc->chws[PMC_MCK] = hw; + + parent_names[0] = "pllack"; + parent_names[1] = "upllck"; + parent_names[2] = "mainck"; + parent_names[3] = "mainck"; + hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 4); + if (IS_ERR(hw)) + goto err_free; + + parent_names[0] = md_slck_name; + parent_names[1] = td_slck_name; + parent_names[2] = "mainck"; + parent_names[3] = "masterck"; + parent_names[4] = "pllack"; + parent_names[5] = "upllck"; + for (i = 0; i < 8; i++) { + char name[6]; + + snprintf(name, sizeof(name), "prog%d", i); + + hw = at91_clk_register_programmable(regmap, name, + parent_names, 6, i, + &sam9x60_programmable_layout); + if (IS_ERR(hw)) + goto err_free; + } + + for (i = 0; i < ARRAY_SIZE(sam9x60_systemck); i++) { + hw = at91_clk_register_system(regmap, sam9x60_systemck[i].n, + sam9x60_systemck[i].p, + sam9x60_systemck[i].id); + if (IS_ERR(hw)) + goto err_free; + + sam9x60_pmc->shws[sam9x60_systemck[i].id] = hw; + } + + for (i = 0; i < ARRAY_SIZE(sam9x60_periphck); i++) { + hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock, + &sam9x60_pcr_layout, + sam9x60_periphck[i].n, + "masterck", + sam9x60_periphck[i].id, + &range); + if (IS_ERR(hw)) + goto err_free; + + sam9x60_pmc->phws[sam9x60_periphck[i].id] = hw; + } + + for (i = 0; i < ARRAY_SIZE(sam9x60_gck); i++) { + hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, + &sam9x60_pcr_layout, + sam9x60_gck[i].n, + parent_names, 6, + sam9x60_gck[i].id, + sam9x60_gck[i].pll, + &sam9x60_gck[i].r); + if (IS_ERR(hw)) + goto err_free; + + sam9x60_pmc->ghws[sam9x60_gck[i].id] = hw; + } + + of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sam9x60_pmc); + + return; + +err_free: + pmc_data_free(sam9x60_pmc); +} + +CLK_OF_DECLARE_DRIVER(sam9x60_pmc, "microchip,sam9x60-pmc", sam9x60_pmc_setup);
Add a driver for the PMC clocks of the sam9c60. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> --- drivers/clk/at91/Makefile | 1 + drivers/clk/at91/sam9x60.c | 307 +++++++++++++++++++++++++++++++++++++ 2 files changed, 308 insertions(+) create mode 100644 drivers/clk/at91/sam9x60.c