Re: [linux-sunxi] Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU

2020-12-05 Thread Icenowy Zheng
在 2020-12-02星期三的 23:06 +,André Przywara写道:
> On 02/12/2020 21:03, Jernej Škrabec wrote:
> > Dne sreda, 02. december 2020 ob 14:54:06 CET je Andre Przywara
> > napisal(a):
> > > While the clocks are fairly similar to the H6, many differ in
> > > tiny
> > > details, so a separate clock driver seems indicated.
> > > 
> > > Derived from the H6 clock driver, and adjusted according to the
> > > manual.
> > > 
> > > Signed-off-by: Andre Przywara 
> > > ---
> > >  drivers/clk/sunxi-ng/Kconfig|7 +-
> > >  drivers/clk/sunxi-ng/Makefile   |1 +
> > >  drivers/clk/sunxi-ng/ccu-sun50i-h616.c  | 1134
> > > +++
> > >  drivers/clk/sunxi-ng/ccu-sun50i-h616.h  |   58 +
> > >  include/dt-bindings/clock/sun50i-h616-ccu.h |  110 ++
> > >  include/dt-bindings/reset/sun50i-h616-ccu.h |   67 ++
> > >  6 files changed, 1376 insertions(+), 1 deletion(-)
> > >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> > >  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
> > >  create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
> > >  create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h
> > > 
> > > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> > > ng/Kconfig
> > > index ce5f5847d5d3..cd46d8853876 100644
> > > --- a/drivers/clk/sunxi-ng/Kconfig
> > > +++ b/drivers/clk/sunxi-ng/Kconfig
> 
> 
> 
> > > +static int sun50i_h616_ccu_probe(struct platform_device *pdev)
> > > +{
> > > + struct resource *res;
> > > + void __iomem *reg;
> > > + u32 val;
> > > + int i;
> > > +
> > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > + reg = devm_ioremap_resource(>dev, res);
> > > + if (IS_ERR(reg))
> > > + return PTR_ERR(reg);
> > > +
> > > + /* Enable the lock bits on all PLLs */
> > > + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> > > + val = readl(reg + pll_regs[i]);
> > > + val |= BIT(29);
> > 
> > You should also add BIT(27) here. It enables PLL output (new
> > functionality in 
> > H616). Without this only clocks which are child of PLL_CPUX and
> > PLL_PERIPH0 
> > would work (set up by U-Boot). I'm pretty sure that's not intended
> > usage but 
> > until we know better, it's ok imo.
> 
> Ah right, the output enable bit. I was wondering if the A100 solution
> would better here: use bit 27 as the .enable value, and actually
> enable

Why not .enable = BIT(27) | BIT(31) ?

> (bit31) all PLLs here.
> Or we add another field, maybe a flag, to allow the kernel to decide
> which bit to use. Clement suggested something like that on IRC.
> But for now I can surely just set bit 27 here as well.
> 
> > > + writel(val, reg + pll_regs[i]);
> > > + }
> > > +
> > > + /*
> > > +  * Force the output divider of video PLLs to 0.
> > > +  *
> > > +  * See the comment before pll-video0 definition for the reason.
> > > +  */
> > > + for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
> > > + val = readl(reg + pll_video_regs[i]);
> > > + val &= ~BIT(0);
> > > + writel(val, reg + pll_video_regs[i]);
> > > + }
> > > +
> > > + /*
> > > +  * Force OHCI 12M clock sources to 00 (12MHz divided from
> > > 48MHz)
> > > +  *
> > > +  * This clock mux is still mysterious, and the code just
> > > enforces
> > > +  * it to have a valid clock parent.
> > > +  */
> > > + for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
> > > + val = readl(reg + usb2_clk_regs[i]);
> > > + val &= ~GENMASK(25, 24);
> > > + writel (val, reg + usb2_clk_regs[i]);
> > > + }
> > > +
> > > + /*
> > > +  * Force the post-divider of pll-audio to 12 and the output
> > > divider
> > > +  * of it to 2, so 24576000 and 22579200 rates can be set
> > > exactly.
> > > +  */
> > > + val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
> > > + val &= ~(GENMASK(21, 16) | BIT(0));
> > > + writel(val | (11 << 16) | BIT(0), reg +
> > > SUN50I_H616_PLL_AUDIO_REG);
> > > +
> > > + /*
> > > +  * First clock parent (osc32K) is unusable for CEC. But since
> > > there
> > > +  * is no good way to force parent switch (both run with same
> > > frequency),
> > > +  * just set second clock parent here.
> > > +  */
> > > + val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG);
> > > + val |= BIT(24);
> > > + writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
> > > +
> > > + return sunxi_ccu_probe(pdev->dev.of_node, reg,
> > > _h616_ccu_desc);
> > > +}
> > > +
> > > +static const struct of_device_id sun50i_h616_ccu_ids[] = {
> > > + { .compatible = "allwinner,sun50i-h616-ccu",
> > > + .data = _h616_ccu_desc },
> > > + { }
> > > +};
> > > +
> > > +static struct platform_driver sun50i_h616_ccu_driver = {
> > > + .probe  = sun50i_h616_ccu_probe,
> > > + .driver = {
> > > + .name   = "sun50i-h616-ccu",
> > > + .of_match_table = sun50i_h616_ccu_ids,
> > > + },
> > > +};
> > > +builtin_platform_driver(sun50i_h616_ccu_driver);
> > 
> > Please use CLK_OF_DECLARE() instead. That way clocks will be
> > initialized 
> 

[linux-sunxi] Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU

2020-12-02 Thread André Przywara
On 02/12/2020 21:03, Jernej Škrabec wrote:
> Dne sreda, 02. december 2020 ob 14:54:06 CET je Andre Przywara napisal(a):
>> While the clocks are fairly similar to the H6, many differ in tiny
>> details, so a separate clock driver seems indicated.
>>
>> Derived from the H6 clock driver, and adjusted according to the manual.
>>
>> Signed-off-by: Andre Przywara 
>> ---
>>  drivers/clk/sunxi-ng/Kconfig|7 +-
>>  drivers/clk/sunxi-ng/Makefile   |1 +
>>  drivers/clk/sunxi-ng/ccu-sun50i-h616.c  | 1134 +++
>>  drivers/clk/sunxi-ng/ccu-sun50i-h616.h  |   58 +
>>  include/dt-bindings/clock/sun50i-h616-ccu.h |  110 ++
>>  include/dt-bindings/reset/sun50i-h616-ccu.h |   67 ++
>>  6 files changed, 1376 insertions(+), 1 deletion(-)
>>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
>>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
>>  create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
>>  create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h
>>
>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
>> index ce5f5847d5d3..cd46d8853876 100644
>> --- a/drivers/clk/sunxi-ng/Kconfig
>> +++ b/drivers/clk/sunxi-ng/Kconfig



>> +static int sun50i_h616_ccu_probe(struct platform_device *pdev)
>> +{
>> +struct resource *res;
>> +void __iomem *reg;
>> +u32 val;
>> +int i;
>> +
>> +res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +reg = devm_ioremap_resource(>dev, res);
>> +if (IS_ERR(reg))
>> +return PTR_ERR(reg);
>> +
>> +/* Enable the lock bits on all PLLs */
>> +for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
>> +val = readl(reg + pll_regs[i]);
>> +val |= BIT(29);
> 
> You should also add BIT(27) here. It enables PLL output (new functionality in 
> H616). Without this only clocks which are child of PLL_CPUX and PLL_PERIPH0 
> would work (set up by U-Boot). I'm pretty sure that's not intended usage but 
> until we know better, it's ok imo.

Ah right, the output enable bit. I was wondering if the A100 solution
would better here: use bit 27 as the .enable value, and actually enable
(bit31) all PLLs here.
Or we add another field, maybe a flag, to allow the kernel to decide
which bit to use. Clement suggested something like that on IRC.
But for now I can surely just set bit 27 here as well.

>> +writel(val, reg + pll_regs[i]);
>> +}
>> +
>> +/*
>> + * Force the output divider of video PLLs to 0.
>> + *
>> + * See the comment before pll-video0 definition for the reason.
>> + */
>> +for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
>> +val = readl(reg + pll_video_regs[i]);
>> +val &= ~BIT(0);
>> +writel(val, reg + pll_video_regs[i]);
>> +}
>> +
>> +/*
>> + * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
>> + *
>> + * This clock mux is still mysterious, and the code just enforces
>> + * it to have a valid clock parent.
>> + */
>> +for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
>> +val = readl(reg + usb2_clk_regs[i]);
>> +val &= ~GENMASK(25, 24);
>> +writel (val, reg + usb2_clk_regs[i]);
>> +}
>> +
>> +/*
>> + * Force the post-divider of pll-audio to 12 and the output divider
>> + * of it to 2, so 24576000 and 22579200 rates can be set exactly.
>> + */
>> +val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
>> +val &= ~(GENMASK(21, 16) | BIT(0));
>> +writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
>> +
>> +/*
>> + * First clock parent (osc32K) is unusable for CEC. But since there
>> + * is no good way to force parent switch (both run with same frequency),
>> + * just set second clock parent here.
>> + */
>> +val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG);
>> +val |= BIT(24);
>> +writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
>> +
>> +return sunxi_ccu_probe(pdev->dev.of_node, reg, _h616_ccu_desc);
>> +}
>> +
>> +static const struct of_device_id sun50i_h616_ccu_ids[] = {
>> +{ .compatible = "allwinner,sun50i-h616-ccu",
>> +.data = _h616_ccu_desc },
>> +{ }
>> +};
>> +
>> +static struct platform_driver sun50i_h616_ccu_driver = {
>> +.probe  = sun50i_h616_ccu_probe,
>> +.driver = {
>> +.name   = "sun50i-h616-ccu",
>> +.of_match_table = sun50i_h616_ccu_ids,
>> +},
>> +};
>> +builtin_platform_driver(sun50i_h616_ccu_driver);
> 
> Please use CLK_OF_DECLARE() instead. That way clocks will be initialized 
> earlier and it will be actually possible to register both timer peripherals 
> (once DT nodes are added). If pdev or dev is ever needed, two stage 
> initialization can be made later.

Sure, will do.

Thanks for having a look!

Andre

> 
> Best regards,
> Jernej
> 
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h 
>> 

[linux-sunxi] Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU

2020-12-02 Thread Jernej Škrabec
Dne sreda, 02. december 2020 ob 14:54:06 CET je Andre Przywara napisal(a):
> While the clocks are fairly similar to the H6, many differ in tiny
> details, so a separate clock driver seems indicated.
> 
> Derived from the H6 clock driver, and adjusted according to the manual.
> 
> Signed-off-by: Andre Przywara 
> ---
>  drivers/clk/sunxi-ng/Kconfig|7 +-
>  drivers/clk/sunxi-ng/Makefile   |1 +
>  drivers/clk/sunxi-ng/ccu-sun50i-h616.c  | 1134 +++
>  drivers/clk/sunxi-ng/ccu-sun50i-h616.h  |   58 +
>  include/dt-bindings/clock/sun50i-h616-ccu.h |  110 ++
>  include/dt-bindings/reset/sun50i-h616-ccu.h |   67 ++
>  6 files changed, 1376 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
>  create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
>  create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h
> 
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index ce5f5847d5d3..cd46d8853876 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -32,8 +32,13 @@ config SUN50I_H6_CCU
>   default ARM64 && ARCH_SUNXI
>   depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> +config SUN50I_H616_CCU
> + bool "Support for the Allwinner H616 CCU"
> + default ARM64 && ARCH_SUNXI
> + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
> +
>  config SUN50I_H6_R_CCU
> - bool "Support for the Allwinner H6 PRCM CCU"
> + bool "Support for the Allwinner H6 and H616 PRCM CCU"
>   default ARM64 && ARCH_SUNXI
>   depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>  
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 3eb5cff40eac..96c324306d97 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU)+= ccu-sun50i-a64.o
>  obj-$(CONFIG_SUN50I_A100_CCU)+= ccu-sun50i-a100.o
>  obj-$(CONFIG_SUN50I_A100_R_CCU)  += ccu-sun50i-a100-r.o
>  obj-$(CONFIG_SUN50I_H6_CCU)  += ccu-sun50i-h6.o
> +obj-$(CONFIG_SUN50I_H616_CCU)+= ccu-sun50i-h616.o
>  obj-$(CONFIG_SUN50I_H6_R_CCU)+= ccu-sun50i-h6-r.o
>  obj-$(CONFIG_SUN4I_A10_CCU)  += ccu-sun4i-a10.o
>  obj-$(CONFIG_SUN5I_CCU)  += ccu-sun5i.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/
ccu-sun50i-h616.c
> new file mode 100644
> index ..3fbb258f0354
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> @@ -0,0 +1,1134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Arm Ltd.
> + * Based on the H6 CCU driver, which is:
> + *   Copyright (c) 2017 Icenowy Zheng 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_div.h"
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +#include "ccu_mult.h"
> +#include "ccu_nk.h"
> +#include "ccu_nkm.h"
> +#include "ccu_nkmp.h"
> +#include "ccu_nm.h"
> +
> +#include "ccu-sun50i-h616.h"
> +
> +/*
> + * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
> + * P should only be used for output frequencies lower than 288 MHz.
> + *
> + * For now we can just model it as a multiplier clock, and force P to /1.
> + *
> + * The M factor is present in the register's description, but not in the
> + * frequency formula, and it's documented as "M is only used for backdoor
> + * testing", so it's not modelled and then force to 0.
> + */
> +#define SUN50I_H616_PLL_CPUX_REG 0x000
> +static struct ccu_mult pll_cpux_clk = {
> + .enable = BIT(31),
> + .lock   = BIT(28),
> + .mult   = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> + .common = {
> + .reg= 0x000,
> + .hw.init= CLK_HW_INIT("pll-cpux", "osc24M",
> +   _mult_ops,
> +   
CLK_SET_RATE_UNGATE),
> + },
> +};
> +
> +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
> +#define SUN50I_H616_PLL_DDR0_REG 0x010
> +static struct ccu_nkmp pll_ddr0_clk = {
> + .enable = BIT(31),
> + .lock   = BIT(28),
> + .n  = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> + .m  = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .p  = _SUNXI_CCU_DIV(0, 1), /* output divider */
> + .common = {
> + .reg= 0x010,
> + .hw.init= CLK_HW_INIT("pll-ddr0", "osc24M",
> +   _nkmp_ops,
> +   
CLK_SET_RATE_UNGATE),
> + },
> +};
> +
> +#define SUN50I_H616_PLL_DDR1_REG 0x018
> +static struct ccu_nkmp pll_ddr1_clk = {
> + .enable = BIT(31),
> + .lock   = BIT(28),
> + 

[linux-sunxi] Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU

2020-12-02 Thread Maxime Ripard
Hi

On Wed, Dec 02, 2020 at 01:54:06PM +, Andre Przywara wrote:
> While the clocks are fairly similar to the H6, many differ in tiny
> details, so a separate clock driver seems indicated.
> 
> Derived from the H6 clock driver, and adjusted according to the manual.
> 
> Signed-off-by: Andre Przywara 

The patch itself looks ok, but there's a bunch of checkpatch warning
you'll want to fix.

Maxime

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/linux-sunxi/20201202155651.vgbkrrrxlw55yq7x%40gilmour.


signature.asc
Description: PGP signature