Hi Andrew,

On 11/15/2012 10:28 PM, Andrew Lunn wrote:
> From: Sebastian Hesselbarth <[email protected]>
> 
> This driver allows to provide DT clocks for core clocks found on
> Marvell Kirkwood, Dove & 370/XP SoCs. The core clock frequencies and
> ratios are determined by decoding the Sample-At-Reset registers.
> 
> Although technically correct, using a divider of 0 will lead to
> div_by_zero panic. Let's use a ratio of 0/1 instead to fail later
> with a zero clock.
> 
> Signed-off-by: Gregory CLEMENT <[email protected]>
> Signed-off-by: Sebastian Hesselbarth <[email protected]>
> Signed-off-by: Andrew Lunn <[email protected]>
> ---
>  .../devicetree/bindings/clock/mvebu-core-clock.txt |   47 ++
>  drivers/clk/Kconfig                                |    2 +
>  drivers/clk/Makefile                               |    1 +
>  drivers/clk/mvebu/Kconfig                          |    3 +
>  drivers/clk/mvebu/Makefile                         |    1 +
>  drivers/clk/mvebu/clk-core.c                       |  675 
> ++++++++++++++++++++
>  drivers/clk/mvebu/clk-core.h                       |   18 +
>  drivers/clk/mvebu/clk.c                            |   23 +
>  include/linux/clk/mvebu.h                          |   22 +
>  9 files changed, 792 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
>  create mode 100644 drivers/clk/mvebu/Kconfig
>  create mode 100644 drivers/clk/mvebu/Makefile
>  create mode 100644 drivers/clk/mvebu/clk-core.c
>  create mode 100644 drivers/clk/mvebu/clk-core.h
>  create mode 100644 drivers/clk/mvebu/clk.c
>  create mode 100644 include/linux/clk/mvebu.h
> 
> diff --git a/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt 
> b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
> new file mode 100644
> index 0000000..84cfae7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
> @@ -0,0 +1,47 @@
> +* Core Clock bindings for Marvell MVEBU SoCs
> +
> +Marvell MVEBU SoCs usually allow to determine core clock frequencies by
> +reading the Sample-At-Reset (SAR) register. The core clock consumer should
> +specify the desired clock by having the clock ID in its "clocks" phandle 
> cell.
> +
> +The following is a list of provided IDs and clock names on Kirkwood and Dove:
> + 0 = tclk   (Internal Bus clock)
> + 1 = cpuclk (CPU0 clock)
> + 2 = l2clk  (L2 Cache clock derived from CPU0 clock)
> + 3 = ddrclk (DDR controller clock derived from CPU0 clock)
> +
> +The following is a list of provided IDs and clock names on 370/XP:

You should call them Aramda 370 and Aramda XP. You do this modification
in the 2nd patch but it should be squashed in this patch.

> + 0 = tclk    (Internal Bus clock)
> + 1 = cpuclk  (CPU clock)
> + 2 = nbclk   (L2 Cache clock)
> + 3 = hclk    (DRAM control clock)
> + 4 = dramclk (DDR clock)
> +
> +Required properties:
> +- compatible : shall be one of the following:
> +     "marvell,dove-core-clocks" - for Dove SoC core clocks
> +     "marvell,kirkwood-core-clocks" - for Kirkwood SoC (except mv88f6180)
> +     "marvell,mv88f6180-core-clocks" - for Kirkwood MV88f6180 SoC
> +     "marvell,370-core-clocks" - For 370 SoC core clocks
> +     "marvell,xp-core-clocks" - For XP SoC core clocks

Same here.

> +- reg : shall be the register address of the Sample-At-Reset (SAR) register
> +- #clock-cells : from common clock binding; shall be set to 1
> +
> +Optional properties:
> +- clock-output-names : from common clock binding; allows overwrite default 
> clock
> +     output names ("tclk", "cpuclk", "l2clk", "ddrclk")
> +
> +Example:
> +
> +core_clk: core-clocks@d0214 {
> +     compatible = "marvell,dove-core-clocks";
> +     reg = <0xd0214 0x4>;
> +     #clock-cells = <1>;
> +};
> +
> +spi0: spi@10600 {
> +     compatible = "marvell,orion-spi";
> +     /* ... */
> +     /* get tclk from core clock provider */
> +     clocks = <&core_clk 0>;
> +};
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index bace9e9..60427c0 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -54,3 +54,5 @@ config COMMON_CLK_MAX77686
>         This driver supports Maxim 77686 crystal oscillator clock. 
>  
>  endmenu
> +
> +source "drivers/clk/mvebu/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 71a25b9..d0a14ae 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_PLAT_SPEAR)    += spear/
>  obj-$(CONFIG_ARCH_U300)              += clk-u300.o
>  obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
>  obj-$(CONFIG_ARCH_PRIMA2)    += clk-prima2.o
> +obj-$(CONFIG_PLAT_ORION)     += mvebu/
>  ifeq ($(CONFIG_COMMON_CLK), y)
>  obj-$(CONFIG_ARCH_MMP)               += mmp/
>  endif
> diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig
> new file mode 100644
> index 0000000..fd7bf97
> --- /dev/null
> +++ b/drivers/clk/mvebu/Kconfig
> @@ -0,0 +1,3 @@
> +config MVEBU_CLK_CORE
> +       bool
> +
> diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile
> new file mode 100644
> index 0000000..de1d961
> --- /dev/null
> +++ b/drivers/clk/mvebu/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_MVEBU_CLK_CORE)         += clk.o clk-core.o
> diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c
> new file mode 100644
> index 0000000..26ba835
> --- /dev/null
> +++ b/drivers/clk/mvebu/clk-core.c
> @@ -0,0 +1,675 @@
> +/*
> + * Marvell EBU clock core handling defined at reset
> + *
> + * Copyright (C) 2012 Marvell
> + *
> + * Gregory CLEMENT <[email protected]>
> + * Sebastian Hesselbarth <[email protected]>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2.  This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +#include <linux/kernel.h>
> +#include <linux/clk.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/of_address.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include "clk-core.h"
> +
> +struct core_ratio {
> +     int id;
> +     const char *name;
> +};
> +
> +struct core_clocks {
> +     u32 (*get_tclk_freq)(void __iomem *sar);
> +     u32 (*get_cpu_freq)(void __iomem *sar);
> +     void (*get_clk_ratio)(void __iomem *sar, int id, int *mult, int *div);
> +     const struct core_ratio *ratios;
> +     int num_ratios;
> +};
> +
> +static struct clk_onecell_data clk_data;
> +
> +static void __init mvebu_clk_core_setup(struct device_node *np,
> +                              struct core_clocks *coreclk)
> +{
> +     const char *tclk_name = "tclk";
> +     const char *cpuclk_name = "cpuclk";
> +     void __iomem *base;
> +     unsigned long rate;
> +     int n;
> +
> +     base = of_iomap(np, 0);
> +     if (WARN_ON(!base))
> +             return;
> +
> +     /*
> +      * Allocate struct for TCLK, cpu clk, and core ratio clocks
> +      */
> +     clk_data.clk_num = 2 + coreclk->num_ratios;
> +     clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
> +                             GFP_KERNEL);
> +     if (WARN_ON(!clk_data.clks))
> +             return;
> +
> +     /*
> +      * Register TCLK
> +      */
> +     of_property_read_string_index(np, "clock-output-names", 0,
> +                                   &tclk_name);
> +     rate = coreclk->get_tclk_freq(base);
> +     clk_data.clks[0] = clk_register_fixed_rate(NULL, tclk_name, NULL,
> +                                                CLK_IS_ROOT, rate);
> +     WARN_ON(IS_ERR(clk_data.clks[0]));
> +
> +     /*
> +      * Register CPU clock
> +      */
> +     of_property_read_string_index(np, "clock-output-names", 1,
> +                                   &cpuclk_name);
> +     rate = coreclk->get_cpu_freq(base);
> +     clk_data.clks[1] = clk_register_fixed_rate(NULL, cpuclk_name, NULL,
> +                                                CLK_IS_ROOT, rate);
> +     WARN_ON(IS_ERR(clk_data.clks[1]));
> +
> +     /*
> +      * Register fixed-factor clocks derived from CPU clock
> +      */
> +     for (n = 0; n < coreclk->num_ratios; n++) {
> +             const char *rclk_name = coreclk->ratios[n].name;
> +             int mult, div;
> +
> +             of_property_read_string_index(np, "clock-output-names",
> +                                           2+n, &rclk_name);
> +             coreclk->get_clk_ratio(base, coreclk->ratios[n].id,
> +                                    &mult, &div);
> +             clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
> +                                    cpuclk_name, 0, mult, div);
> +             WARN_ON(IS_ERR(clk_data.clks[2+n]));
> +     };
> +
> +     /*
> +      * SAR register isn't needed anymore
> +      */
> +     iounmap(base);
> +
> +     of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +}
> +
> +#ifdef CONFIG_MACH_ARMADA_370_XP
> +/*
> + * 370/XP Sample At Reset is a 64 bit bitfiled split in two register

Add "Armada" in front of 370/XP please.

> + * of 32 bits
> + */
> +
> +#define SARL                             0   /* Low part [0:31] */
> +#define          SARL_AXP_PCLK_FREQ_OPT          21
> +#define          SARL_AXP_PCLK_FREQ_OPT_MASK     0x7
> +#define          SARL_A370_PCLK_FREQ_OPT         11
> +#define          SARL_A370_PCLK_FREQ_OPT_MASK    0xF
> +#define          SARL_AXP_FAB_FREQ_OPT           24
> +#define          SARL_AXP_FAB_FREQ_OPT_MASK      0xF
> +#define          SARL_A370_FAB_FREQ_OPT          15
> +#define          SARL_A370_FAB_FREQ_OPT_MASK     0x1F
> +#define          SARL_A370_TCLK_FREQ_OPT         20
> +#define          SARL_A370_TCLK_FREQ_OPT_MASK    0x1
> +#define SARH                             4   /* High part [32:63] */
> +#define          SARH_AXP_PCLK_FREQ_OPT          (52-32)
> +#define          SARH_AXP_PCLK_FREQ_OPT_MASK     0x1
> +#define          SARH_AXP_PCLK_FREQ_OPT_SHIFT    3
> +#define          SARH_AXP_FAB_FREQ_OPT           (51-32)
> +#define          SARH_AXP_FAB_FREQ_OPT_MASK      0x1
> +#define          SARH_AXP_FAB_FREQ_OPT_SHIFT     4
> +
> +static const u32 __initconst a370_tclk_frequencies[] = {

In all other part in the kernel the relatives functions to
Armada 370 or Armada XP are suffixed by armada_370 or armada_xp.
Could we do the same here for being consistent?
It will help when one wants to grep code relative to the armada
370 or the armada XP.


> +     16600000,
> +     20000000,
> +};
> +
> +static u32 __init a370_get_tclk_freq(void __iomem *sar)
Same here.

> +{
> +     u8 tclk_freq_select = 0;
> +
> +     tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
> +                         SARL_A370_TCLK_FREQ_OPT_MASK);
> +     return a370_tclk_frequencies[tclk_freq_select];
> +}
> +
> +static const u32 __initconst a370_cpu_frequencies[] = {
> +     400000000,
> +     533000000,
> +     667000000,
> +     800000000,
> +     1000000000,
> +     1067000000,
> +     1200000000,
> +};
> +
> +static u32 __init a370_get_cpu_freq(void __iomem *sar)
> +{
> +     u32 cpu_freq;
> +     u8 cpu_freq_select = 0;
> +
> +     cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
> +                        SARL_A370_PCLK_FREQ_OPT_MASK);
> +     if (cpu_freq_select > ARRAY_SIZE(a370_cpu_frequencies)) {
> +             pr_err("CPU freq select unsuported %d\n", cpu_freq_select);
> +             cpu_freq = 0;
> +     } else
> +             cpu_freq = a370_cpu_frequencies[cpu_freq_select];
> +
> +     return cpu_freq;
> +}
> +
> +enum { A370_XP_NBCLK, A370_XP_HCLK, A370_XP_DRAMCLK };
> +
> +static const struct core_ratio __initconst a370_xp_core_ratios[] = {
> +     { .id = A370_XP_NBCLK,   .name = "nbclk" },
> +     { .id = A370_XP_HCLK,    .name = "hclk" },
> +     { .id = A370_XP_DRAMCLK, .name = "dramclk" },
> +};
> +
> +static const int __initconst a370_xp_nbclk_ratios[32][2] = {
> +     {0, 1}, {1, 2}, {2, 2}, {2, 2},
> +     {1, 2}, {1, 2}, {1, 1}, {2, 3},
> +     {0, 1}, {1, 2}, {2, 4}, {0, 1},
> +     {1, 2}, {0, 1}, {0, 1}, {2, 2},
> +     {0, 1}, {0, 1}, {0, 1}, {1, 1},
> +     {2, 3}, {0, 1}, {0, 1}, {0, 1},
> +     {0, 1}, {0, 1}, {0, 1}, {1, 1},
> +     {0, 1}, {0, 1}, {0, 1}, {0, 1},
> +};
> +
> +static const int __initconst a370_xp_hclk_ratios[32][2] = {
> +     {0, 1}, {1, 2}, {2, 6}, {2, 3},
> +     {1, 3}, {1, 4}, {1, 2}, {2, 6},
> +     {0, 1}, {1, 6}, {2, 10}, {0, 1},
> +     {1, 4}, {0, 1}, {0, 1}, {2, 5},
> +     {0, 1}, {0, 1}, {0, 1}, {1, 2},
> +     {2, 6}, {0, 1}, {0, 1}, {0, 1},
> +     {0, 1}, {0, 1}, {0, 1}, {1, 1},
> +     {0, 1}, {0, 1}, {0, 1}, {0, 1},
> +};
> +
> +static const int __initconst a370_xp_dramclk_ratios[32][2] = {
> +     {0, 1}, {1, 2}, {2, 3}, {2, 3},
> +     {1, 3}, {1, 2}, {1, 2}, {2, 6},
> +     {0, 1}, {1, 3}, {2, 5}, {0, 1},
> +     {1, 4}, {0, 1}, {0, 1}, {2, 5},
> +     {0, 1}, {0, 1}, {0, 1}, {1, 1},
> +     {2, 3}, {0, 1}, {0, 1}, {0, 1},
> +     {0, 1}, {0, 1}, {0, 1}, {1, 1},
> +     {0, 1}, {0, 1}, {0, 1}, {0, 1},
> +};
> +
> +static void __init a370_xp_get_clk_ratio(u32 opt,
> +     void __iomem *sar, int id, int *mult, int *div)
> +{
> +     switch (id) {
> +     case A370_XP_NBCLK:
> +             *mult = a370_xp_nbclk_ratios[opt][0];
> +             *div = a370_xp_nbclk_ratios[opt][1];
> +             break;
> +     case A370_XP_HCLK:
> +             *mult = a370_xp_hclk_ratios[opt][0];
> +             *div = a370_xp_hclk_ratios[opt][1];
> +             break;
> +     case A370_XP_DRAMCLK:
> +             *mult = a370_xp_dramclk_ratios[opt][0];
> +             *div = a370_xp_dramclk_ratios[opt][1];
> +             break;
> +     }
> +}
> +
> +static void __init a370_get_clk_ratio(
> +     void __iomem *sar, int id, int *mult, int *div)
> +{
> +     u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
> +             SARL_A370_FAB_FREQ_OPT_MASK);
> +
> +     a370_xp_get_clk_ratio(opt, sar, id, mult, div);
> +}
> +
> +
> +static const struct core_clocks a370_core_clocks = {
> +     .get_tclk_freq = a370_get_tclk_freq,
> +     .get_cpu_freq = a370_get_cpu_freq,
> +     .get_clk_ratio = a370_get_clk_ratio,
> +     .ratios = a370_xp_core_ratios,
> +     .num_ratios = ARRAY_SIZE(a370_xp_core_ratios),
> +};
> +
> +static const u32 __initconst xp_cpu_frequencies[] = {

And for Armada XP even the 'a' disappeared!

Gregory
_______________________________________________
devicetree-discuss mailing list
[email protected]
https://lists.ozlabs.org/listinfo/devicetree-discuss

Reply via email to