diff mbox

[2/8] clk: keystone: Add gate control clock driver

Message ID 1375719147-7578-3-git-send-email-santosh.shilimkar@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Santosh Shilimkar Aug. 5, 2013, 4:12 p.m. UTC
Add the driver for the clock gate control which uses PSC (Power Sleep
Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
disabling of the clocks for different IPs present in the SoC.

Cc: Mike Turquette <mturquette@linaro.org>

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
 drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
 include/linux/clk/keystone.h                       |    1 +
 3 files changed, 337 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
 create mode 100644 drivers/clk/keystone/gate.c

Comments

Mark Rutland Aug. 13, 2013, 4:13 p.m. UTC | #1
[adding dt maintainers]

On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
> Add the driver for the clock gate control which uses PSC (Power Sleep
> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
> disabling of the clocks for different IPs present in the SoC.
> 
> Cc: Mike Turquette <mturquette@linaro.org>
> 
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
>  include/linux/clk/keystone.h                       |    1 +
>  3 files changed, 337 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
>  create mode 100644 drivers/clk/keystone/gate.c
> 
> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> new file mode 100644
> index 0000000..40afef5
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> @@ -0,0 +1,30 @@
> +Binding for Keystone gate control driver which uses PSC controller IP.
> +
> +This binding uses the common clock binding[1].
> +
> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> +
> +Required properties:
> +- compatible : shall be "keystone,psc-clk".

Similarly to my comments on patch 1, this should probably be something
more like "ti,keystone-psc-clock"

> +- #clock-cells : from common clock binding; shall be set to 0.
> +- clocks : parent clock phandle
> +- reg :        psc address address space
> +
> +Optional properties:
> +- clock-output-names : From common clock binding to override the
> +                       default output clock name
> +- status : "enabled" if clock is always enabled

Huh? This is a standard property, for which ePAPR defines "okay",
"disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
seem to follow the standard meaning judging by the code.

It looks like this could be a boolean property
("clock-always-enabled"?), but that assumes it's necessary.

Why do you need this?

> +- lpsc : lpsc module id, if not set defaults to zero

What's that needed for? Are there multiple clocks sharing a common
register bank?

> +- pd : power domain number, if not set defaults to zero (always ON)

Please don't use abbreviations unnecessarily. "power-domain-id" or
similar would be far better. What exactly does this represent? Does the
clock IP itself handle power domains, or is there some external unit
that controls power domains?

> +- gpsc : gpsc number, if not set defaults to zero

How does that interact with the lpsc property? When are these necessary?

> +
> +Example:
> +       clock {
> +               #clock-cells = <0>;
> +               compatible = "keystone,psc-clk";
> +               clocks = <&chipclk3>;
> +               clock-output-names = "debugss_trc";
> +               reg = <0x02350000 4096>;
> +               lpsc = <5>;
> +               pd = <1>;
> +       };
> diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
> new file mode 100644
> index 0000000..72ac478
> --- /dev/null
> +++ b/drivers/clk/keystone/gate.c
> @@ -0,0 +1,306 @@
> +/*
> + * Clock driver for Keystone 2 based devices
> + *
> + * Copyright (C) 2013 Texas Instruments.
> + *     Murali Karicheri <m-karicheri2@ti.com>
> + *     Santosh Shilimkar <santosh.shilimkar@ti.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/of_address.h>
> +#include <linux/of.h>
> +#include <linux/module.h>
> +
> +/* PSC register offsets */
> +#define PTCMD                  0x120
> +#define PTSTAT                 0x128
> +#define PDSTAT                 0x200
> +#define PDCTL                  0x300
> +#define MDSTAT                 0x800
> +#define MDCTL                  0xa00
> +
> +/* PSC module states */
> +#define PSC_STATE_SWRSTDISABLE 0
> +#define PSC_STATE_SYNCRST      1
> +#define PSC_STATE_DISABLE      2
> +#define PSC_STATE_ENABLE       3
> +
> +#define MDSTAT_STATE_MASK      0x3f
> +#define MDSTAT_MCKOUT          BIT(12)
> +#define PDSTAT_STATE_MASK      0x1f
> +#define MDCTL_FORCE            BIT(31)
> +#define MDCTL_LRESET           BIT(8)
> +#define PDCTL_NEXT             BIT(0)
> +
> +/* PSC flags. Disable state is SwRstDisable */
> +#define PSC_SWRSTDISABLE       BIT(0)
> +/* Force module state transtition */
> +#define PSC_FORCE              BIT(1)
> +/* Keep module in local reset */
> +#define PSC_LRESET             BIT(2)
> +#define NUM_GPSC               2
> +#define REG_OFFSET             4
> +
> +/**
> + * struct clk_psc_data - PSC data
> + * @base: Base address for a PSC
> + * @flags: framework flags
> + * @lpsc: Is it local PSC
> + * @gpsc: Is it global PSC
> + * @domain: PSC domain
> + *
> + */
> +struct clk_psc_data {
> +       void __iomem *base;
> +       u32     flags;
> +       u32     psc_flags;
> +       u8      lpsc;
> +       u8      gpsc;
> +       u8      domain;
> +};
> +
> +/**
> + * struct clk_psc - PSC clock structure
> + * @hw: clk_hw for the psc
> + * @psc_data: PSC driver specific data
> + * @lock: Spinlock used by the driver
> + */
> +struct clk_psc {
> +       struct clk_hw hw;
> +       struct clk_psc_data *psc_data;
> +       spinlock_t *lock;
> +};
> +
> +struct reg_psc {
> +       u32 phy_base;
> +       u32 size;
> +       void __iomem *io_base;
> +};
> +
> +static struct reg_psc psc_addr[NUM_GPSC];
> +static DEFINE_SPINLOCK(psc_lock);
> +
> +#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)
> +
> +static void psc_config(void __iomem *psc_base, unsigned int domain,
> +               unsigned int id, bool enable, u32 flags)
> +{
> +       u32 ptcmd, pdstat, pdctl, mdstat, mdctl, next_state;
> +
> +       if (enable)
> +               next_state = PSC_STATE_ENABLE;
> +       else if (flags & PSC_SWRSTDISABLE)
> +               next_state = PSC_STATE_SWRSTDISABLE;
> +       else
> +               next_state = PSC_STATE_DISABLE;
> +
> +       mdctl = readl(psc_base + MDCTL + REG_OFFSET * id);
> +       mdctl &= ~MDSTAT_STATE_MASK;
> +       mdctl |= next_state;
> +       if (flags & PSC_FORCE)
> +               mdctl |= MDCTL_FORCE;
> +       if (flags & PSC_LRESET)
> +               mdctl &= ~MDCTL_LRESET;
> +       writel(mdctl, psc_base + MDCTL + REG_OFFSET * id);
> +
> +       pdstat = readl(psc_base + PDSTAT + REG_OFFSET * domain);
> +       if (!(pdstat & PDSTAT_STATE_MASK)) {
> +               pdctl = readl(psc_base + PDCTL + REG_OFFSET * domain);
> +               pdctl |= PDCTL_NEXT;
> +               writel(pdctl, psc_base + PDCTL + REG_OFFSET * domain);
> +       }
> +
> +       ptcmd = 1 << domain;
> +       writel(ptcmd, psc_base + PTCMD);
> +       while ((readl(psc_base + PTSTAT) >> domain) & 1)
> +               ;
> +
> +       do {
> +               mdstat = readl(psc_base + MDSTAT + REG_OFFSET * id);
> +       } while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
> +}
> +
> +static int keystone_clk_is_enabled(struct clk_hw *hw)
> +{
> +       struct clk_psc *psc = to_clk_psc(hw);
> +       struct clk_psc_data *data = psc->psc_data;
> +       u32 mdstat = readl(data->base + MDSTAT + REG_OFFSET * data->lpsc);
> +
> +       return (mdstat & MDSTAT_MCKOUT) ? 1 : 0;
> +}
> +
> +static int keystone_clk_enable(struct clk_hw *hw)
> +{
> +       struct clk_psc *psc = to_clk_psc(hw);
> +       struct clk_psc_data *data = psc->psc_data;
> +       unsigned long flags = 0;
> +
> +       if (psc->lock)
> +               spin_lock_irqsave(psc->lock, flags);
> +
> +       psc_config(data->base, data->domain, data->lpsc, 1, data->psc_flags);
> +
> +       if (psc->lock)
> +               spin_unlock_irqrestore(psc->lock, flags);
> +
> +       return 0;
> +}
> +
> +static void keystone_clk_disable(struct clk_hw *hw)
> +{
> +       struct clk_psc *psc = to_clk_psc(hw);
> +       struct clk_psc_data *data = psc->psc_data;
> +       unsigned long flags = 0;
> +
> +       if (psc->lock)
> +               spin_lock_irqsave(psc->lock, flags);
> +
> +       psc_config(data->base, data->domain, data->lpsc, 0, data->psc_flags);
> +
> +       if (psc->lock)
> +               spin_unlock_irqrestore(psc->lock, flags);
> +}
> +
> +static const struct clk_ops clk_psc_ops = {
> +       .enable = keystone_clk_enable,
> +       .disable = keystone_clk_disable,
> +       .is_enabled = keystone_clk_is_enabled,
> +};
> +
> +/**
> + * clk_register_psc - register psc clock
> + * @dev: device that is registering this clock
> + * @name: name of this clock
> + * @parent_name: name of clock's parent
> + * @psc_data: platform data to configure this clock
> + * @lock: spinlock used by this clock
> + */
> +static struct clk *clk_register_psc(struct device *dev,
> +                       const char *name,
> +                       const char *parent_name,
> +                       struct clk_psc_data *psc_data,
> +                       spinlock_t *lock)
> +{
> +       struct clk_init_data init;
> +       struct clk_psc *psc;
> +       struct clk *clk;
> +
> +       psc = kzalloc(sizeof(*psc), GFP_KERNEL);
> +       if (!psc)
> +               return ERR_PTR(-ENOMEM);
> +
> +       init.name = name;
> +       init.ops = &clk_psc_ops;
> +       init.flags = psc_data->flags;
> +       init.parent_names = (parent_name ? &parent_name : NULL);

Is &parent_name not a pointer to a pointer on the stack? Is this only
used once?

> +       init.num_parents = (parent_name ? 1 : 0);
> +
> +       psc->psc_data = psc_data;
> +       psc->lock = lock;
> +       psc->hw.init = &init;

That's definitely a pointer to some data on the stack, and that seems to
be kept around. Is this only used for one-time initialisation, or might
it be used later?

> +
> +       clk = clk_register(NULL, &psc->hw);
> +       if (IS_ERR(clk))
> +               kfree(psc);
> +
> +       return clk;
> +}
> +
> +/**
> + * of_psc_clk_init - initialize psc clock through DT
> + * @node: device tree node for this clock
> + * @lock: spinlock used by this clock
> + */
> +static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock)
> +{
> +       const char *parent_name, *status = NULL, *base_flags = NULL;
> +       struct clk_psc_data *data;
> +       const char *clk_name = node->name;
> +       u32 gpsc = 0, lpsc = 0, pd = 0;
> +       struct resource res;
> +       struct clk *clk;
> +       int rc;
> +
> +       data = kzalloc(sizeof(*data), GFP_KERNEL);
> +       WARN_ON(!data);

Does that not mean things will blow up later? return now?

> +
> +       if (of_address_to_resource(node, 0, &res)) {
> +               pr_err("psc_clk_init - no reg property defined\n");
> +               goto out;
> +       }
> +
> +       of_property_read_u32(node, "gpsc", &gpsc);
> +       of_property_read_u32(node, "lpsc", &lpsc);
> +       of_property_read_u32(node, "pd", &pd);
> +
> +       if (gpsc >= NUM_GPSC) {
> +               pr_err("psc_clk_init - no reg property defined\n");

Wrong error message.

> +               goto out;
> +       }
> +
> +       of_property_read_string(node,
> +                       "clock-output-names", &clk_name);
> +       parent_name = of_clk_get_parent_name(node, 0);
> +       WARN_ON(!parent_name);

Do you require the parent name? If so you need to fail gracefully, if
not you don't need the WARN_ON (perhaps a pr_warn would be better?).

> +
> +       /* Expected that same phy_base is used for all psc clocks of
> +        * a give gpsc. So ioremap is done only once.
> +        */

So these clocks are all components of a larger IP block? It might make
more sense to describe the containing block, with the actual clocks as
sub-nodes (or if the set of clocks for the containing block is known,
just the containing block).

> +       if (psc_addr[gpsc].phy_base) {
> +               if (psc_addr[gpsc].phy_base != res.start) {
> +                       pr_err("Different psc base for same GPSC\n");
> +                       goto out;
> +               }
> +       } else {
> +               psc_addr[gpsc].phy_base = res.start;
> +               psc_addr[gpsc].io_base =
> +                       ioremap(res.start, resource_size(&res));
> +       }
> +
> +       WARN_ON(!psc_addr[gpsc].io_base);

Surely things will blow up later if that's the case? return here instead?

> +       data->base = psc_addr[gpsc].io_base;
> +       data->lpsc = lpsc;
> +       data->gpsc = gpsc;
> +       data->domain = pd;
> +
> +       if (of_property_read_bool(node, "ti,psc-lreset"))
> +               data->psc_flags |= PSC_LRESET;
> +       if (of_property_read_bool(node, "ti,psc-force"))
> +               data->psc_flags |= PSC_FORCE;

Neither of these were defined in the binding, and they don't appear to
have been inherited form another binding. What are they for? Why are
they needed?

> +
> +       clk = clk_register_psc(NULL, clk_name, parent_name,
> +                               data, lock);
> +
> +       if (clk) {
> +               of_clk_add_provider(node, of_clk_src_simple_get, clk);
> +
> +               rc = of_property_read_string(node, "status", &status);
> +               if (status && !strcmp(status, "enabled"))
> +                       clk_prepare_enable(clk);
> +               return;
> +       }

As mentioned above, this abuses the standard status property, and it's
not clear why this is necessary.

Thanks,
Mark.

> +       pr_err("psc_clk_init - error registering psc clk %s\n", node->name);
> +out:
> +       kfree(data);
> +       return;
> +}
> +
> +/**
> + * of_keystone_psc_clk_init - initialize psc clock through DT
> + * @node: device tree node for this clock
> + */
> +void __init of_keystone_psc_clk_init(struct device_node *node)
> +{
> +       of_psc_clk_init(node, &psc_lock);
> +}
> +EXPORT_SYMBOL_GPL(of_keystone_psc_clk_init);
> +CLK_OF_DECLARE(keystone_gate_clk, "keystone,psc-clk", of_keystone_psc_clk_init);
> diff --git a/include/linux/clk/keystone.h b/include/linux/clk/keystone.h
> index 1ade95d..7b3e154 100644
> --- a/include/linux/clk/keystone.h
> +++ b/include/linux/clk/keystone.h
> @@ -14,5 +14,6 @@
>  #define __LINUX_CLK_KEYSTONE_H_
> 
>  extern void of_keystone_pll_clk_init(struct device_node *node);
> +extern void of_keystone_psc_clk_init(struct device_node *node);
> 
>  #endif /* __LINUX_CLK_KEYSTONE_H_ */
> --
> 1.7.9.5
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
Santosh Shilimkar Aug. 13, 2013, 4:36 p.m. UTC | #2
On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
> [adding dt maintainers]
> 
> On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
>> Add the driver for the clock gate control which uses PSC (Power Sleep
>> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
>> disabling of the clocks for different IPs present in the SoC.
>>
>> Cc: Mike Turquette <mturquette@linaro.org>
>>
>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> ---
>>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
>>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
>>  include/linux/clk/keystone.h                       |    1 +
>>  3 files changed, 337 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
>>  create mode 100644 drivers/clk/keystone/gate.c
>>
>> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
>> new file mode 100644
>> index 0000000..40afef5
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
>> @@ -0,0 +1,30 @@
>> +Binding for Keystone gate control driver which uses PSC controller IP.
>> +
>> +This binding uses the common clock binding[1].
>> +
>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>> +
>> +Required properties:
>> +- compatible : shall be "keystone,psc-clk".
> 
> Similarly to my comments on patch 1, this should probably be something
> more like "ti,keystone-psc-clock"
> 
>> +- #clock-cells : from common clock binding; shall be set to 0.
>> +- clocks : parent clock phandle
>> +- reg :        psc address address space
>> +
>> +Optional properties:
>> +- clock-output-names : From common clock binding to override the
>> +                       default output clock name
>> +- status : "enabled" if clock is always enabled
> 
> Huh? This is a standard property, for which ePAPR defines "okay",
> "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
> seem to follow the standard meaning judging by the code.
> 
> It looks like this could be a boolean property
> ("clock-always-enabled"?), but that assumes it's necessary.
> 
> Why do you need this?
> 
I dropped this already. Forgot to update the documentation.

>> +- lpsc : lpsc module id, if not set defaults to zero
> 
> What's that needed for? Are there multiple clocks sharing a common
> register bank?
> 
>> +- pd : power domain number, if not set defaults to zero (always ON)
> 
> Please don't use abbreviations unnecessarily. "power-domain-id" or
> similar would be far better. What exactly does this represent? Does the
> clock IP itself handle power domains, or is there some external unit
> that controls power domains?
> 
pd is commonly used but I can expand it. This represent the power
domain number.

>> +- gpsc : gpsc number, if not set defaults to zero
> 
> How does that interact with the lpsc property? When are these necessary?
> 
lpsc is local clock/module control where as gpsc sits on top of it. 

>> diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
>> new file mode 100644
>> index 0000000..72ac478
>> --- /dev/null
>> +++ b/drivers/clk/keystone/gate.c

[..]

>> +/**
>> + * clk_register_psc - register psc clock
>> + * @dev: device that is registering this clock
>> + * @name: name of this clock
>> + * @parent_name: name of clock's parent
>> + * @psc_data: platform data to configure this clock
>> + * @lock: spinlock used by this clock
>> + */
>> +static struct clk *clk_register_psc(struct device *dev,
>> +                       const char *name,
>> +                       const char *parent_name,
>> +                       struct clk_psc_data *psc_data,
>> +                       spinlock_t *lock)
>> +{
>> +       struct clk_init_data init;
>> +       struct clk_psc *psc;
>> +       struct clk *clk;
>> +
>> +       psc = kzalloc(sizeof(*psc), GFP_KERNEL);
>> +       if (!psc)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       init.name = name;
>> +       init.ops = &clk_psc_ops;
>> +       init.flags = psc_data->flags;
>> +       init.parent_names = (parent_name ? &parent_name : NULL);
> 
> Is &parent_name not a pointer to a pointer on the stack? Is this only
> used once?
> 
>> +       init.num_parents = (parent_name ? 1 : 0);
>> +
>> +       psc->psc_data = psc_data;
>> +       psc->lock = lock;
>> +       psc->hw.init = &init;
> 
> That's definitely a pointer to some data on the stack, and that seems to
> be kept around. Is this only used for one-time initialisation, or might
> it be used later?
> 
Its init only.

>> +       data->base = psc_addr[gpsc].io_base;
>> +       data->lpsc = lpsc;
>> +       data->gpsc = gpsc;
>> +       data->domain = pd;
>> +
>> +       if (of_property_read_bool(node, "ti,psc-lreset"))
>> +               data->psc_flags |= PSC_LRESET;
>> +       if (of_property_read_bool(node, "ti,psc-force"))
>> +               data->psc_flags |= PSC_FORCE;
> 
> Neither of these were defined in the binding, and they don't appear to
> have been inherited form another binding. What are they for? Why are
> they needed?
> 
They represent the hardware support transition method needed to have
proper clock enable/disable sequence to work. Will update the binding
along with other comments which I agree.

>> +
>> +       clk = clk_register_psc(NULL, clk_name, parent_name,
>> +                               data, lock);
>> +
>> +       if (clk) {
>> +               of_clk_add_provider(node, of_clk_src_simple_get, clk);
>> +
>> +               rc = of_property_read_string(node, "status", &status);
>> +               if (status && !strcmp(status, "enabled"))
>> +                       clk_prepare_enable(clk);
>> +               return;
>> +       }
> 
> As mentioned above, this abuses the standard status property, and it's
> not clear why this is necessary.
> 
Actually I have removed this one from dt nodes. Looks like missed
to pick the right patch while posting. Have dropped this change
already.

Regards,
Santosh
Mark Rutland Aug. 13, 2013, 4:53 p.m. UTC | #3
On Tue, Aug 13, 2013 at 05:36:50PM +0100, Santosh Shilimkar wrote:
> On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
> > [adding dt maintainers]
> > 
> > On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
> >> Add the driver for the clock gate control which uses PSC (Power Sleep
> >> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
> >> disabling of the clocks for different IPs present in the SoC.
> >>
> >> Cc: Mike Turquette <mturquette@linaro.org>
> >>
> >> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >> ---
> >>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
> >>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
> >>  include/linux/clk/keystone.h                       |    1 +
> >>  3 files changed, 337 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>  create mode 100644 drivers/clk/keystone/gate.c
> >>
> >> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> >> new file mode 100644
> >> index 0000000..40afef5
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> >> @@ -0,0 +1,30 @@
> >> +Binding for Keystone gate control driver which uses PSC controller IP.
> >> +
> >> +This binding uses the common clock binding[1].
> >> +
> >> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> >> +
> >> +Required properties:
> >> +- compatible : shall be "keystone,psc-clk".
> > 
> > Similarly to my comments on patch 1, this should probably be something
> > more like "ti,keystone-psc-clock"
> > 
> >> +- #clock-cells : from common clock binding; shall be set to 0.
> >> +- clocks : parent clock phandle
> >> +- reg :        psc address address space
> >> +
> >> +Optional properties:
> >> +- clock-output-names : From common clock binding to override the
> >> +                       default output clock name
> >> +- status : "enabled" if clock is always enabled
> > 
> > Huh? This is a standard property, for which ePAPR defines "okay",
> > "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
> > seem to follow the standard meaning judging by the code.
> > 
> > It looks like this could be a boolean property
> > ("clock-always-enabled"?), but that assumes it's necessary.
> > 
> > Why do you need this?
> > 
> I dropped this already. Forgot to update the documentation.

Ok.

> 
> >> +- lpsc : lpsc module id, if not set defaults to zero
> > 
> > What's that needed for? Are there multiple clocks sharing a common
> > register bank?
> > 
> >> +- pd : power domain number, if not set defaults to zero (always ON)
> > 
> > Please don't use abbreviations unnecessarily. "power-domain-id" or
> > similar would be far better. What exactly does this represent? Does the
> > clock IP itself handle power domains, or is there some external unit
> > that controls power domains?
> > 
> pd is commonly used but I can expand it. This represent the power
> domain number.

Does the the clock IP have some internal logic for handling power
domains only covering its clocks, or is there some external power
controller involved (i.e. do we possibly need to describe an external
unit and a linkage to it?).

> 
> >> +- gpsc : gpsc number, if not set defaults to zero
> > 
> > How does that interact with the lpsc property? When are these necessary?
> > 
> lpsc is local clock/module control where as gpsc sits on top of it. 

Ok. I'm not sure haivng these default to zero makes much sense, as that
could easily hide errors in dts. It might make more sense to make them
required and error out if they aren't present.

Unless they're zero far more often?

> 
> >> diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
> >> new file mode 100644
> >> index 0000000..72ac478
> >> --- /dev/null
> >> +++ b/drivers/clk/keystone/gate.c
> 
> [..]
> 
> >> +/**
> >> + * clk_register_psc - register psc clock
> >> + * @dev: device that is registering this clock
> >> + * @name: name of this clock
> >> + * @parent_name: name of clock's parent
> >> + * @psc_data: platform data to configure this clock
> >> + * @lock: spinlock used by this clock
> >> + */
> >> +static struct clk *clk_register_psc(struct device *dev,
> >> +                       const char *name,
> >> +                       const char *parent_name,
> >> +                       struct clk_psc_data *psc_data,
> >> +                       spinlock_t *lock)
> >> +{
> >> +       struct clk_init_data init;
> >> +       struct clk_psc *psc;
> >> +       struct clk *clk;
> >> +
> >> +       psc = kzalloc(sizeof(*psc), GFP_KERNEL);
> >> +       if (!psc)
> >> +               return ERR_PTR(-ENOMEM);
> >> +
> >> +       init.name = name;
> >> +       init.ops = &clk_psc_ops;
> >> +       init.flags = psc_data->flags;
> >> +       init.parent_names = (parent_name ? &parent_name : NULL);
> > 
> > Is &parent_name not a pointer to a pointer on the stack? Is this only
> > used once?
> > 
> >> +       init.num_parents = (parent_name ? 1 : 0);
> >> +
> >> +       psc->psc_data = psc_data;
> >> +       psc->lock = lock;
> >> +       psc->hw.init = &init;
> > 
> > That's definitely a pointer to some data on the stack, and that seems to
> > be kept around. Is this only used for one-time initialisation, or might
> > it be used later?
> > 
> Its init only.

Ok.

> 
> >> +       data->base = psc_addr[gpsc].io_base;
> >> +       data->lpsc = lpsc;
> >> +       data->gpsc = gpsc;
> >> +       data->domain = pd;
> >> +
> >> +       if (of_property_read_bool(node, "ti,psc-lreset"))
> >> +               data->psc_flags |= PSC_LRESET;
> >> +       if (of_property_read_bool(node, "ti,psc-force"))
> >> +               data->psc_flags |= PSC_FORCE;
> > 
> > Neither of these were defined in the binding, and they don't appear to
> > have been inherited form another binding. What are they for? Why are
> > they needed?
> > 
> They represent the hardware support transition method needed to have
> proper clock enable/disable sequence to work. Will update the binding
> along with other comments which I agree.

Ok.

> 
> >> +
> >> +       clk = clk_register_psc(NULL, clk_name, parent_name,
> >> +                               data, lock);
> >> +
> >> +       if (clk) {
> >> +               of_clk_add_provider(node, of_clk_src_simple_get, clk);
> >> +
> >> +               rc = of_property_read_string(node, "status", &status);
> >> +               if (status && !strcmp(status, "enabled"))
> >> +                       clk_prepare_enable(clk);
> >> +               return;
> >> +       }
> > 
> > As mentioned above, this abuses the standard status property, and it's
> > not clear why this is necessary.
> > 
> Actually I have removed this one from dt nodes. Looks like missed
> to pick the right patch while posting. Have dropped this change
> already.

Great!

Thanks,
Mark.
Mike Turquette Aug. 19, 2013, 8:43 p.m. UTC | #4
Quoting Mark Rutland (2013-08-13 09:53:44)
> On Tue, Aug 13, 2013 at 05:36:50PM +0100, Santosh Shilimkar wrote:
> > On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
> > > [adding dt maintainers]
> > > 
> > > On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
> > >> Add the driver for the clock gate control which uses PSC (Power Sleep
> > >> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
> > >> disabling of the clocks for different IPs present in the SoC.
> > >>
> > >> Cc: Mike Turquette <mturquette@linaro.org>
> > >>
> > >> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > >> ---
> > >>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
> > >>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
> > >>  include/linux/clk/keystone.h                       |    1 +
> > >>  3 files changed, 337 insertions(+)
> > >>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
> > >>  create mode 100644 drivers/clk/keystone/gate.c
> > >>
> > >> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> > >> new file mode 100644
> > >> index 0000000..40afef5
> > >> --- /dev/null
> > >> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> > >> @@ -0,0 +1,30 @@
> > >> +Binding for Keystone gate control driver which uses PSC controller IP.
> > >> +
> > >> +This binding uses the common clock binding[1].
> > >> +
> > >> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> > >> +
> > >> +Required properties:
> > >> +- compatible : shall be "keystone,psc-clk".
> > > 
> > > Similarly to my comments on patch 1, this should probably be something
> > > more like "ti,keystone-psc-clock"
> > > 
> > >> +- #clock-cells : from common clock binding; shall be set to 0.
> > >> +- clocks : parent clock phandle
> > >> +- reg :        psc address address space
> > >> +
> > >> +Optional properties:
> > >> +- clock-output-names : From common clock binding to override the
> > >> +                       default output clock name
> > >> +- status : "enabled" if clock is always enabled
> > > 
> > > Huh? This is a standard property, for which ePAPR defines "okay",
> > > "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
> > > seem to follow the standard meaning judging by the code.
> > > 
> > > It looks like this could be a boolean property
> > > ("clock-always-enabled"?), but that assumes it's necessary.
> > > 
> > > Why do you need this?
> > > 
> > I dropped this already. Forgot to update the documentation.
> 
> Ok.
> 
> > 
> > >> +- lpsc : lpsc module id, if not set defaults to zero
> > > 
> > > What's that needed for? Are there multiple clocks sharing a common
> > > register bank?
> > > 
> > >> +- pd : power domain number, if not set defaults to zero (always ON)
> > > 
> > > Please don't use abbreviations unnecessarily. "power-domain-id" or
> > > similar would be far better. What exactly does this represent? Does the
> > > clock IP itself handle power domains, or is there some external unit
> > > that controls power domains?
> > > 
> > pd is commonly used but I can expand it. This represent the power
> > domain number.
> 
> Does the the clock IP have some internal logic for handling power
> domains only covering its clocks, or is there some external power
> controller involved (i.e. do we possibly need to describe an external
> unit and a linkage to it?).

Hmm, does the clock own the power domain or does the power domain own
the clock? As you well know on OMAP the clock resides within the power
domain. So it seems to me that the better way to do this would be for
the power domain to have it's own binding and node, and then reference
the clock:

power-domain {
	...
	clocks = <&chipclk3>, <&chipclk4>;
	clock-names = "perclk", "uartclk";
	...
};

Now maybe things are different on Keystone, but if not then I don't see
why the clock binding should have anything to do with the power domain.

> 
> > 
> > >> +- gpsc : gpsc number, if not set defaults to zero
> > > 
> > > How does that interact with the lpsc property? When are these necessary?
> > > 
> > lpsc is local clock/module control where as gpsc sits on top of it. 

Similar to the above, should the gpsc have it's own binding and node
that contains the lpsc which also have their own bindings/nodes, which
finally contain the clocks? Maybe that is over engineered but I want to
consider this before the binding gets set in stone.

Regards,
Mike

> 
> Ok. I'm not sure haivng these default to zero makes much sense, as that
> could easily hide errors in dts. It might make more sense to make them
> required and error out if they aren't present.
> 
> Unless they're zero far more often?
> 
> > 
> > >> diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
> > >> new file mode 100644
> > >> index 0000000..72ac478
> > >> --- /dev/null
> > >> +++ b/drivers/clk/keystone/gate.c
> > 
> > [..]
> > 
> > >> +/**
> > >> + * clk_register_psc - register psc clock
> > >> + * @dev: device that is registering this clock
> > >> + * @name: name of this clock
> > >> + * @parent_name: name of clock's parent
> > >> + * @psc_data: platform data to configure this clock
> > >> + * @lock: spinlock used by this clock
> > >> + */
> > >> +static struct clk *clk_register_psc(struct device *dev,
> > >> +                       const char *name,
> > >> +                       const char *parent_name,
> > >> +                       struct clk_psc_data *psc_data,
> > >> +                       spinlock_t *lock)
> > >> +{
> > >> +       struct clk_init_data init;
> > >> +       struct clk_psc *psc;
> > >> +       struct clk *clk;
> > >> +
> > >> +       psc = kzalloc(sizeof(*psc), GFP_KERNEL);
> > >> +       if (!psc)
> > >> +               return ERR_PTR(-ENOMEM);
> > >> +
> > >> +       init.name = name;
> > >> +       init.ops = &clk_psc_ops;
> > >> +       init.flags = psc_data->flags;
> > >> +       init.parent_names = (parent_name ? &parent_name : NULL);
> > > 
> > > Is &parent_name not a pointer to a pointer on the stack? Is this only
> > > used once?
> > > 
> > >> +       init.num_parents = (parent_name ? 1 : 0);
> > >> +
> > >> +       psc->psc_data = psc_data;
> > >> +       psc->lock = lock;
> > >> +       psc->hw.init = &init;
> > > 
> > > That's definitely a pointer to some data on the stack, and that seems to
> > > be kept around. Is this only used for one-time initialisation, or might
> > > it be used later?
> > > 
> > Its init only.
> 
> Ok.
> 
> > 
> > >> +       data->base = psc_addr[gpsc].io_base;
> > >> +       data->lpsc = lpsc;
> > >> +       data->gpsc = gpsc;
> > >> +       data->domain = pd;
> > >> +
> > >> +       if (of_property_read_bool(node, "ti,psc-lreset"))
> > >> +               data->psc_flags |= PSC_LRESET;
> > >> +       if (of_property_read_bool(node, "ti,psc-force"))
> > >> +               data->psc_flags |= PSC_FORCE;
> > > 
> > > Neither of these were defined in the binding, and they don't appear to
> > > have been inherited form another binding. What are they for? Why are
> > > they needed?
> > > 
> > They represent the hardware support transition method needed to have
> > proper clock enable/disable sequence to work. Will update the binding
> > along with other comments which I agree.
> 
> Ok.
> 
> > 
> > >> +
> > >> +       clk = clk_register_psc(NULL, clk_name, parent_name,
> > >> +                               data, lock);
> > >> +
> > >> +       if (clk) {
> > >> +               of_clk_add_provider(node, of_clk_src_simple_get, clk);
> > >> +
> > >> +               rc = of_property_read_string(node, "status", &status);
> > >> +               if (status && !strcmp(status, "enabled"))
> > >> +                       clk_prepare_enable(clk);
> > >> +               return;
> > >> +       }
> > > 
> > > As mentioned above, this abuses the standard status property, and it's
> > > not clear why this is necessary.
> > > 
> > Actually I have removed this one from dt nodes. Looks like missed
> > to pick the right patch while posting. Have dropped this change
> > already.
> 
> Great!
> 
> Thanks,
> Mark.
Santosh Shilimkar Aug. 20, 2013, 1:55 p.m. UTC | #5
On Monday 19 August 2013 04:43 PM, Mike Turquette wrote:
> Quoting Mark Rutland (2013-08-13 09:53:44)
>> On Tue, Aug 13, 2013 at 05:36:50PM +0100, Santosh Shilimkar wrote:
>>> On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
>>>> [adding dt maintainers]
>>>>
>>>> On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
>>>>> Add the driver for the clock gate control which uses PSC (Power Sleep
>>>>> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
>>>>> disabling of the clocks for different IPs present in the SoC.
>>>>>
>>>>> Cc: Mike Turquette <mturquette@linaro.org>
>>>>>
>>>>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>> ---
>>>>>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
>>>>>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
>>>>>  include/linux/clk/keystone.h                       |    1 +
>>>>>  3 files changed, 337 insertions(+)
>>>>>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
>>>>>  create mode 100644 drivers/clk/keystone/gate.c
>>>>>
>>>>> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
>>>>> new file mode 100644
>>>>> index 0000000..40afef5
>>>>> --- /dev/null
>>>>> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
>>>>> @@ -0,0 +1,30 @@
>>>>> +Binding for Keystone gate control driver which uses PSC controller IP.
>>>>> +
>>>>> +This binding uses the common clock binding[1].
>>>>> +
>>>>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>>>>> +
>>>>> +Required properties:
>>>>> +- compatible : shall be "keystone,psc-clk".
>>>>
>>>> Similarly to my comments on patch 1, this should probably be something
>>>> more like "ti,keystone-psc-clock"
>>>>
>>>>> +- #clock-cells : from common clock binding; shall be set to 0.
>>>>> +- clocks : parent clock phandle
>>>>> +- reg :        psc address address space
>>>>> +
>>>>> +Optional properties:
>>>>> +- clock-output-names : From common clock binding to override the
>>>>> +                       default output clock name
>>>>> +- status : "enabled" if clock is always enabled
>>>>
>>>> Huh? This is a standard property, for which ePAPR defines "okay",
>>>> "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
>>>> seem to follow the standard meaning judging by the code.
>>>>
>>>> It looks like this could be a boolean property
>>>> ("clock-always-enabled"?), but that assumes it's necessary.
>>>>
>>>> Why do you need this?
>>>>
>>> I dropped this already. Forgot to update the documentation.
>>
>> Ok.
>>
>>>
>>>>> +- lpsc : lpsc module id, if not set defaults to zero
>>>>
>>>> What's that needed for? Are there multiple clocks sharing a common
>>>> register bank?
>>>>
>>>>> +- pd : power domain number, if not set defaults to zero (always ON)
>>>>
>>>> Please don't use abbreviations unnecessarily. "power-domain-id" or
>>>> similar would be far better. What exactly does this represent? Does the
>>>> clock IP itself handle power domains, or is there some external unit
>>>> that controls power domains?
>>>>
>>> pd is commonly used but I can expand it. This represent the power
>>> domain number.
>>
>> Does the the clock IP have some internal logic for handling power
>> domains only covering its clocks, or is there some external power
>> controller involved (i.e. do we possibly need to describe an external
>> unit and a linkage to it?).
> 
> Hmm, does the clock own the power domain or does the power domain own
> the clock? As you well know on OMAP the clock resides within the power
> domain. So it seems to me that the better way to do this would be for
> the power domain to have it's own binding and node, and then reference
> the clock:
> 
> power-domain {
> 	...
> 	clocks = <&chipclk3>, <&chipclk4>;
> 	clock-names = "perclk", "uartclk";
> 	...
> };
> 
> Now maybe things are different on Keystone, but if not then I don't see
> why the clock binding should have anything to do with the power domain.
>
They are bit different w.r.t OMAP. LPSC itself is the clock control of the
IP. The LPSC number in the bindings is actually the specific number which
is used to reach to the address space of the clock control. One can view
that one as clock control register index.

The power domain as such are above the lpsc but the clock enable/disable needs
to follow a recommended sequence which needs the access to those registers.
As such there is no major validation done on dynamically switching off PDs
in current generation devices.

As I mentioned you to on IRC, the PD was the only odd part I have to keep
around to address the sequencing need which is kind of interlinked.
 
>>
>>>
>>>>> +- gpsc : gpsc number, if not set defaults to zero
>>>>
>>>> How does that interact with the lpsc property? When are these necessary?
>>>>
>>> lpsc is local clock/module control where as gpsc sits on top of it. 
> 
> Similar to the above, should the gpsc have it's own binding and node
> that contains the lpsc which also have their own bindings/nodes, which
> finally contain the clocks? Maybe that is over engineered but I want to
> consider this before the binding gets set in stone.
> 
Actually GPSC need not be even mentioned since its one per SOC. Let me 
see if I can drop it to avoid any confusion.

Regards,
Santosh
Mike Turquette Aug. 20, 2013, 9:30 p.m. UTC | #6
Quoting Santosh Shilimkar (2013-08-20 06:55:54)
> On Monday 19 August 2013 04:43 PM, Mike Turquette wrote:
> > Quoting Mark Rutland (2013-08-13 09:53:44)
> >> On Tue, Aug 13, 2013 at 05:36:50PM +0100, Santosh Shilimkar wrote:
> >>> On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
> >>>> [adding dt maintainers]
> >>>>
> >>>> On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
> >>>>> Add the driver for the clock gate control which uses PSC (Power Sleep
> >>>>> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
> >>>>> disabling of the clocks for different IPs present in the SoC.
> >>>>>
> >>>>> Cc: Mike Turquette <mturquette@linaro.org>
> >>>>>
> >>>>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >>>>> ---
> >>>>>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
> >>>>>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
> >>>>>  include/linux/clk/keystone.h                       |    1 +
> >>>>>  3 files changed, 337 insertions(+)
> >>>>>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>>>>  create mode 100644 drivers/clk/keystone/gate.c
> >>>>>
> >>>>> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>>>> new file mode 100644
> >>>>> index 0000000..40afef5
> >>>>> --- /dev/null
> >>>>> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>>>> @@ -0,0 +1,30 @@
> >>>>> +Binding for Keystone gate control driver which uses PSC controller IP.
> >>>>> +
> >>>>> +This binding uses the common clock binding[1].
> >>>>> +
> >>>>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> >>>>> +
> >>>>> +Required properties:
> >>>>> +- compatible : shall be "keystone,psc-clk".
> >>>>
> >>>> Similarly to my comments on patch 1, this should probably be something
> >>>> more like "ti,keystone-psc-clock"
> >>>>
> >>>>> +- #clock-cells : from common clock binding; shall be set to 0.
> >>>>> +- clocks : parent clock phandle
> >>>>> +- reg :        psc address address space
> >>>>> +
> >>>>> +Optional properties:
> >>>>> +- clock-output-names : From common clock binding to override the
> >>>>> +                       default output clock name
> >>>>> +- status : "enabled" if clock is always enabled
> >>>>
> >>>> Huh? This is a standard property, for which ePAPR defines "okay",
> >>>> "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
> >>>> seem to follow the standard meaning judging by the code.
> >>>>
> >>>> It looks like this could be a boolean property
> >>>> ("clock-always-enabled"?), but that assumes it's necessary.
> >>>>
> >>>> Why do you need this?
> >>>>
> >>> I dropped this already. Forgot to update the documentation.
> >>
> >> Ok.
> >>
> >>>
> >>>>> +- lpsc : lpsc module id, if not set defaults to zero
> >>>>
> >>>> What's that needed for? Are there multiple clocks sharing a common
> >>>> register bank?
> >>>>
> >>>>> +- pd : power domain number, if not set defaults to zero (always ON)
> >>>>
> >>>> Please don't use abbreviations unnecessarily. "power-domain-id" or
> >>>> similar would be far better. What exactly does this represent? Does the
> >>>> clock IP itself handle power domains, or is there some external unit
> >>>> that controls power domains?
> >>>>
> >>> pd is commonly used but I can expand it. This represent the power
> >>> domain number.
> >>
> >> Does the the clock IP have some internal logic for handling power
> >> domains only covering its clocks, or is there some external power
> >> controller involved (i.e. do we possibly need to describe an external
> >> unit and a linkage to it?).
> > 
> > Hmm, does the clock own the power domain or does the power domain own
> > the clock? As you well know on OMAP the clock resides within the power
> > domain. So it seems to me that the better way to do this would be for
> > the power domain to have it's own binding and node, and then reference
> > the clock:
> > 
> > power-domain {
> >       ...
> >       clocks = <&chipclk3>, <&chipclk4>;
> >       clock-names = "perclk", "uartclk";
> >       ...
> > };
> > 
> > Now maybe things are different on Keystone, but if not then I don't see
> > why the clock binding should have anything to do with the power domain.
> >
> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
> IP. The LPSC number in the bindings is actually the specific number which
> is used to reach to the address space of the clock control. One can view
> that one as clock control register index.

Thanks for the information. I have a further question about then: are
the LPSC clocks really module clocks that belong to the IP that they are
gating?

If so then they could be defined within the node defining their parent
IP. That might be enough to get rid of the LPSC index value. Again I
might be over-engineering it. Just trying to get an understanding.

> 
> The power domain as such are above the lpsc but the clock enable/disable needs
> to follow a recommended sequence which needs the access to those registers.
> As such there is no major validation done on dynamically switching off PDs
> in current generation devices.
> 
> As I mentioned you to on IRC, the PD was the only odd part I have to keep
> around to address the sequencing need which is kind of interlinked.

Right. Well maybe some day that part can go away but I understand the
need for it now.

Regards,
Mike

>  
> >>
> >>>
> >>>>> +- gpsc : gpsc number, if not set defaults to zero
> >>>>
> >>>> How does that interact with the lpsc property? When are these necessary?
> >>>>
> >>> lpsc is local clock/module control where as gpsc sits on top of it. 
> > 
> > Similar to the above, should the gpsc have it's own binding and node
> > that contains the lpsc which also have their own bindings/nodes, which
> > finally contain the clocks? Maybe that is over engineered but I want to
> > consider this before the binding gets set in stone.
> > 
> Actually GPSC need not be even mentioned since its one per SOC. Let me 
> see if I can drop it to avoid any confusion.
> 
> Regards,
> Santosh
Santosh Shilimkar Aug. 20, 2013, 9:55 p.m. UTC | #7
On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:
> Quoting Santosh Shilimkar (2013-08-20 06:55:54)
>> On Monday 19 August 2013 04:43 PM, Mike Turquette wrote:
>>> Quoting Mark Rutland (2013-08-13 09:53:44)
>>>> On Tue, Aug 13, 2013 at 05:36:50PM +0100, Santosh Shilimkar wrote:
>>>>> On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
>>>>>> [adding dt maintainers]
>>>>>>
>>>>>> On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
>>>>>>> Add the driver for the clock gate control which uses PSC (Power Sleep
>>>>>>> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
>>>>>>> disabling of the clocks for different IPs present in the SoC.
>>>>>>>
>>>>>>> Cc: Mike Turquette <mturquette@linaro.org>
>>>>>>>
>>>>>>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>>> ---
>>>>>>>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
>>>>>>>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
>>>>>>>  include/linux/clk/keystone.h                       |    1 +
>>>>>>>  3 files changed, 337 insertions(+)
>>>>>>>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
>>>>>>>  create mode 100644 drivers/clk/keystone/gate.c
>>>>>>>
>>>>>>> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
>>>>>>> new file mode 100644
>>>>>>> index 0000000..40afef5
>>>>>>> --- /dev/null
>>>>>>> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
>>>>>>> @@ -0,0 +1,30 @@
>>>>>>> +Binding for Keystone gate control driver which uses PSC controller IP.
>>>>>>> +
>>>>>>> +This binding uses the common clock binding[1].
>>>>>>> +
>>>>>>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
>>>>>>> +
>>>>>>> +Required properties:
>>>>>>> +- compatible : shall be "keystone,psc-clk".
>>>>>>
>>>>>> Similarly to my comments on patch 1, this should probably be something
>>>>>> more like "ti,keystone-psc-clock"
>>>>>>
>>>>>>> +- #clock-cells : from common clock binding; shall be set to 0.
>>>>>>> +- clocks : parent clock phandle
>>>>>>> +- reg :        psc address address space
>>>>>>> +
>>>>>>> +Optional properties:
>>>>>>> +- clock-output-names : From common clock binding to override the
>>>>>>> +                       default output clock name
>>>>>>> +- status : "enabled" if clock is always enabled
>>>>>>
>>>>>> Huh? This is a standard property, for which ePAPR defines "okay",
>>>>>> "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
>>>>>> seem to follow the standard meaning judging by the code.
>>>>>>
>>>>>> It looks like this could be a boolean property
>>>>>> ("clock-always-enabled"?), but that assumes it's necessary.
>>>>>>
>>>>>> Why do you need this?
>>>>>>
>>>>> I dropped this already. Forgot to update the documentation.
>>>>
>>>> Ok.
>>>>
>>>>>
>>>>>>> +- lpsc : lpsc module id, if not set defaults to zero
>>>>>>
>>>>>> What's that needed for? Are there multiple clocks sharing a common
>>>>>> register bank?
>>>>>>
>>>>>>> +- pd : power domain number, if not set defaults to zero (always ON)
>>>>>>
>>>>>> Please don't use abbreviations unnecessarily. "power-domain-id" or
>>>>>> similar would be far better. What exactly does this represent? Does the
>>>>>> clock IP itself handle power domains, or is there some external unit
>>>>>> that controls power domains?
>>>>>>
>>>>> pd is commonly used but I can expand it. This represent the power
>>>>> domain number.
>>>>
>>>> Does the the clock IP have some internal logic for handling power
>>>> domains only covering its clocks, or is there some external power
>>>> controller involved (i.e. do we possibly need to describe an external
>>>> unit and a linkage to it?).
>>>
>>> Hmm, does the clock own the power domain or does the power domain own
>>> the clock? As you well know on OMAP the clock resides within the power
>>> domain. So it seems to me that the better way to do this would be for
>>> the power domain to have it's own binding and node, and then reference
>>> the clock:
>>>
>>> power-domain {
>>>       ...
>>>       clocks = <&chipclk3>, <&chipclk4>;
>>>       clock-names = "perclk", "uartclk";
>>>       ...
>>> };
>>>
>>> Now maybe things are different on Keystone, but if not then I don't see
>>> why the clock binding should have anything to do with the power domain.
>>>
>> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
>> IP. The LPSC number in the bindings is actually the specific number which
>> is used to reach to the address space of the clock control. One can view
>> that one as clock control register index.
> 
> Thanks for the information. I have a further question about then: are
> the LPSC clocks really module clocks that belong to the IP that they are
> gating?
> 
LPSC controls the clock enable/disable to the IP/module so answer is yes.
In certain cases LPSC controls clock to more than one IP as well.

> If so then they could be defined within the node defining their parent
> IP. That might be enough to get rid of the LPSC index value. Again I
> might be over-engineering it. Just trying to get an understanding.
> 
Am not sure I follow you here on not having the LPSC index. Sorry. 

>>
>> The power domain as such are above the lpsc but the clock enable/disable needs
>> to follow a recommended sequence which needs the access to those registers.
>> As such there is no major validation done on dynamically switching off PDs
>> in current generation devices.
>>
>> As I mentioned you to on IRC, the PD was the only odd part I have to keep
>> around to address the sequencing need which is kind of interlinked.
> 
> Right. Well maybe some day that part can go away but I understand the
> need for it now.
> 
right. Thanks

regards,
Santosh
Mike Turquette Aug. 20, 2013, 10:41 p.m. UTC | #8
Quoting Santosh Shilimkar (2013-08-20 14:55:56)
> On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:
> > Quoting Santosh Shilimkar (2013-08-20 06:55:54)
> >> On Monday 19 August 2013 04:43 PM, Mike Turquette wrote:
> >>> Quoting Mark Rutland (2013-08-13 09:53:44)
> >>>> On Tue, Aug 13, 2013 at 05:36:50PM +0100, Santosh Shilimkar wrote:
> >>>>> On Tuesday 13 August 2013 12:13 PM, Mark Rutland wrote:
> >>>>>> [adding dt maintainers]
> >>>>>>
> >>>>>> On Mon, Aug 05, 2013 at 05:12:21PM +0100, Santosh Shilimkar wrote:
> >>>>>>> Add the driver for the clock gate control which uses PSC (Power Sleep
> >>>>>>> Controller) IP on Keystone 2 based SOCs. It is responsible for enabling and
> >>>>>>> disabling of the clocks for different IPs present in the SoC.
> >>>>>>>
> >>>>>>> Cc: Mike Turquette <mturquette@linaro.org>
> >>>>>>>
> >>>>>>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >>>>>>> ---
> >>>>>>>  .../devicetree/bindings/clock/keystone-gate.txt    |   30 ++
> >>>>>>>  drivers/clk/keystone/gate.c                        |  306 ++++++++++++++++++++
> >>>>>>>  include/linux/clk/keystone.h                       |    1 +
> >>>>>>>  3 files changed, 337 insertions(+)
> >>>>>>>  create mode 100644 Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>>>>>>  create mode 100644 drivers/clk/keystone/gate.c
> >>>>>>>
> >>>>>>> diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>>>>>> new file mode 100644
> >>>>>>> index 0000000..40afef5
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
> >>>>>>> @@ -0,0 +1,30 @@
> >>>>>>> +Binding for Keystone gate control driver which uses PSC controller IP.
> >>>>>>> +
> >>>>>>> +This binding uses the common clock binding[1].
> >>>>>>> +
> >>>>>>> +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
> >>>>>>> +
> >>>>>>> +Required properties:
> >>>>>>> +- compatible : shall be "keystone,psc-clk".
> >>>>>>
> >>>>>> Similarly to my comments on patch 1, this should probably be something
> >>>>>> more like "ti,keystone-psc-clock"
> >>>>>>
> >>>>>>> +- #clock-cells : from common clock binding; shall be set to 0.
> >>>>>>> +- clocks : parent clock phandle
> >>>>>>> +- reg :        psc address address space
> >>>>>>> +
> >>>>>>> +Optional properties:
> >>>>>>> +- clock-output-names : From common clock binding to override the
> >>>>>>> +                       default output clock name
> >>>>>>> +- status : "enabled" if clock is always enabled
> >>>>>>
> >>>>>> Huh? This is a standard property, for which ePAPR defines "okay",
> >>>>>> "disabled", "fail", and "fail-sss", and not "enabled". This also doesn't
> >>>>>> seem to follow the standard meaning judging by the code.
> >>>>>>
> >>>>>> It looks like this could be a boolean property
> >>>>>> ("clock-always-enabled"?), but that assumes it's necessary.
> >>>>>>
> >>>>>> Why do you need this?
> >>>>>>
> >>>>> I dropped this already. Forgot to update the documentation.
> >>>>
> >>>> Ok.
> >>>>
> >>>>>
> >>>>>>> +- lpsc : lpsc module id, if not set defaults to zero
> >>>>>>
> >>>>>> What's that needed for? Are there multiple clocks sharing a common
> >>>>>> register bank?
> >>>>>>
> >>>>>>> +- pd : power domain number, if not set defaults to zero (always ON)
> >>>>>>
> >>>>>> Please don't use abbreviations unnecessarily. "power-domain-id" or
> >>>>>> similar would be far better. What exactly does this represent? Does the
> >>>>>> clock IP itself handle power domains, or is there some external unit
> >>>>>> that controls power domains?
> >>>>>>
> >>>>> pd is commonly used but I can expand it. This represent the power
> >>>>> domain number.
> >>>>
> >>>> Does the the clock IP have some internal logic for handling power
> >>>> domains only covering its clocks, or is there some external power
> >>>> controller involved (i.e. do we possibly need to describe an external
> >>>> unit and a linkage to it?).
> >>>
> >>> Hmm, does the clock own the power domain or does the power domain own
> >>> the clock? As you well know on OMAP the clock resides within the power
> >>> domain. So it seems to me that the better way to do this would be for
> >>> the power domain to have it's own binding and node, and then reference
> >>> the clock:
> >>>
> >>> power-domain {
> >>>       ...
> >>>       clocks = <&chipclk3>, <&chipclk4>;
> >>>       clock-names = "perclk", "uartclk";
> >>>       ...
> >>> };
> >>>
> >>> Now maybe things are different on Keystone, but if not then I don't see
> >>> why the clock binding should have anything to do with the power domain.
> >>>
> >> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
> >> IP. The LPSC number in the bindings is actually the specific number which
> >> is used to reach to the address space of the clock control. One can view
> >> that one as clock control register index.
> > 
> > Thanks for the information. I have a further question about then: are
> > the LPSC clocks really module clocks that belong to the IP that they are
> > gating?
> > 
> LPSC controls the clock enable/disable to the IP/module so answer is yes.
> In certain cases LPSC controls clock to more than one IP as well.
> 
> > If so then they could be defined within the node defining their parent
> > IP. That might be enough to get rid of the LPSC index value. Again I
> > might be over-engineering it. Just trying to get an understanding.
> > 
> Am not sure I follow you here on not having the LPSC index. Sorry. 

How are the 'reg' property and the 'lpsc' property related? Does the
lpsc property modify the register address used to access the clock
control bits?

Thanks,
Mike

> 
> >>
> >> The power domain as such are above the lpsc but the clock enable/disable needs
> >> to follow a recommended sequence which needs the access to those registers.
> >> As such there is no major validation done on dynamically switching off PDs
> >> in current generation devices.
> >>
> >> As I mentioned you to on IRC, the PD was the only odd part I have to keep
> >> around to address the sequencing need which is kind of interlinked.
> > 
> > Right. Well maybe some day that part can go away but I understand the
> > need for it now.
> > 
> right. Thanks
> 
> regards,
> Santosh
Santosh Shilimkar Aug. 20, 2013, 10:54 p.m. UTC | #9
On Tuesday 20 August 2013 06:41 PM, Mike Turquette wrote:
> Quoting Santosh Shilimkar (2013-08-20 14:55:56)
>> On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:

[...]

>>>> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
>>>> IP. The LPSC number in the bindings is actually the specific number which
>>>> is used to reach to the address space of the clock control. One can view
>>>> that one as clock control register index.
>>>
>>> Thanks for the information. I have a further question about then: are
>>> the LPSC clocks really module clocks that belong to the IP that they are
>>> gating?
>>>
>> LPSC controls the clock enable/disable to the IP/module so answer is yes.
>> In certain cases LPSC controls clock to more than one IP as well.
>>
>>> If so then they could be defined within the node defining their parent
>>> IP. That might be enough to get rid of the LPSC index value. Again I
>>> might be over-engineering it. Just trying to get an understanding.
>>>
>> Am not sure I follow you here on not having the LPSC index. Sorry. 
> 
> How are the 'reg' property and the 'lpsc' property related? Does the
> lpsc property modify the register address used to access the clock
> control bits?
> 
Yes it does. Currently all nodes use fix address and then lpsc is
used as an index. But I think we can do better by just using the
right(offset) address in the reg property. Will have a look at it
and see what I can do here.

Thanks for asking this questions Mike 

regards,
Santosh
Mike Turquette Aug. 21, 2013, 2:22 a.m. UTC | #10
Quoting Santosh Shilimkar (2013-08-20 15:54:15)
> On Tuesday 20 August 2013 06:41 PM, Mike Turquette wrote:
> > Quoting Santosh Shilimkar (2013-08-20 14:55:56)
> >> On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:
> 
> [...]
> 
> >>>> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
> >>>> IP. The LPSC number in the bindings is actually the specific number which
> >>>> is used to reach to the address space of the clock control. One can view
> >>>> that one as clock control register index.
> >>>
> >>> Thanks for the information. I have a further question about then: are
> >>> the LPSC clocks really module clocks that belong to the IP that they are
> >>> gating?
> >>>
> >> LPSC controls the clock enable/disable to the IP/module so answer is yes.
> >> In certain cases LPSC controls clock to more than one IP as well.
> >>
> >>> If so then they could be defined within the node defining their parent
> >>> IP. That might be enough to get rid of the LPSC index value. Again I
> >>> might be over-engineering it. Just trying to get an understanding.
> >>>
> >> Am not sure I follow you here on not having the LPSC index. Sorry. 
> > 
> > How are the 'reg' property and the 'lpsc' property related? Does the
> > lpsc property modify the register address used to access the clock
> > control bits?
> > 
> Yes it does. Currently all nodes use fix address and then lpsc is
> used as an index.

Ok cool. Well the reason I brought that up was because I even had the
idea to define these module clocks within the module nodes that own them
in DT. I am way outside of my DT knowledge at this point but I wonder
if the following type of binding is possible:

module: module@4a308200 {
	#address-cells = <1>;
	#size-cells = <1>;
	reg = <0x4a308200 0x1000>;

	clock {
		#clock-cells = <0>;
		compatible = "keystone,psc-clk";
		clocks = <&chipclk3>;
		clock-output-names = "debugss_trc";
		reg = <0x0256>;
		pd = <1>;
	};
};

Again, my DT knowledge is pretty limited, but could the reg property of
the clock be directly affected by the parent node? That seems like it
could nicely model what the hardware is really doing.

> But I think we can do better by just using the
> right(offset) address in the reg property. Will have a look at it
> and see what I can do here.

This also solves the problem nicely.  Thanks for putting up with my
silly questions ;-)

Regards,
Mike

> 
> Thanks for asking this questions Mike 
> 
> regards,
> Santosh
Santosh Shilimkar Aug. 21, 2013, 1:16 p.m. UTC | #11
On Tuesday 20 August 2013 10:22 PM, Mike Turquette wrote:
> Quoting Santosh Shilimkar (2013-08-20 15:54:15)
>> On Tuesday 20 August 2013 06:41 PM, Mike Turquette wrote:
>>> Quoting Santosh Shilimkar (2013-08-20 14:55:56)
>>>> On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:
>>
>> [...]
>>
>>>>>> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
>>>>>> IP. The LPSC number in the bindings is actually the specific number which
>>>>>> is used to reach to the address space of the clock control. One can view
>>>>>> that one as clock control register index.
>>>>>
>>>>> Thanks for the information. I have a further question about then: are
>>>>> the LPSC clocks really module clocks that belong to the IP that they are
>>>>> gating?
>>>>>
>>>> LPSC controls the clock enable/disable to the IP/module so answer is yes.
>>>> In certain cases LPSC controls clock to more than one IP as well.
>>>>
>>>>> If so then they could be defined within the node defining their parent
>>>>> IP. That might be enough to get rid of the LPSC index value. Again I
>>>>> might be over-engineering it. Just trying to get an understanding.
>>>>>
>>>> Am not sure I follow you here on not having the LPSC index. Sorry. 
>>>
>>> How are the 'reg' property and the 'lpsc' property related? Does the
>>> lpsc property modify the register address used to access the clock
>>> control bits?
>>>
>> Yes it does. Currently all nodes use fix address and then lpsc is
>> used as an index.
> 
> Ok cool. Well the reason I brought that up was because I even had the
> idea to define these module clocks within the module nodes that own them
> in DT. I am way outside of my DT knowledge at this point but I wonder
> if the following type of binding is possible:
> 
> module: module@4a308200 {
> 	#address-cells = <1>;
> 	#size-cells = <1>;
> 	reg = <0x4a308200 0x1000>;
> 
> 	clock {
> 		#clock-cells = <0>;
> 		compatible = "keystone,psc-clk";
> 		clocks = <&chipclk3>;
> 		clock-output-names = "debugss_trc";
> 		reg = <0x0256>;
> 		pd = <1>;
> 	};
> };
> 
> Again, my DT knowledge is pretty limited, but could the reg property of
> the clock be directly affected by the parent node? That seems like it
> could nicely model what the hardware is really doing.
> 
The module(I assume you mean IP here) reg address space is separate than
that used for clock control so that doesn't fit as such. Traditionally
clock controls even though targeted for specific modules sits in different
control as at least seen on OMAP and Keystone. OCP wrappers on OMAP
were bit of exceptions but they were little bit of glue logic without
much control within the address space.

>> But I think we can do better by just using the
>> right(offset) address in the reg property. Will have a look at it
>> and see what I can do here.
> 
> This also solves the problem nicely.  Thanks for putting up with my
> silly questions ;-)
> 
You asked right and good questions.

Regards,
Santosh
Mike Turquette Aug. 22, 2013, 8:12 a.m. UTC | #12
Quoting Santosh Shilimkar (2013-08-21 06:16:33)
> On Tuesday 20 August 2013 10:22 PM, Mike Turquette wrote:
> > Quoting Santosh Shilimkar (2013-08-20 15:54:15)
> >> On Tuesday 20 August 2013 06:41 PM, Mike Turquette wrote:
> >>> Quoting Santosh Shilimkar (2013-08-20 14:55:56)
> >>>> On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:
> >>
> >> [...]
> >>
> >>>>>> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
> >>>>>> IP. The LPSC number in the bindings is actually the specific number which
> >>>>>> is used to reach to the address space of the clock control. One can view
> >>>>>> that one as clock control register index.
> >>>>>
> >>>>> Thanks for the information. I have a further question about then: are
> >>>>> the LPSC clocks really module clocks that belong to the IP that they are
> >>>>> gating?
> >>>>>
> >>>> LPSC controls the clock enable/disable to the IP/module so answer is yes.
> >>>> In certain cases LPSC controls clock to more than one IP as well.
> >>>>
> >>>>> If so then they could be defined within the node defining their parent
> >>>>> IP. That might be enough to get rid of the LPSC index value. Again I
> >>>>> might be over-engineering it. Just trying to get an understanding.
> >>>>>
> >>>> Am not sure I follow you here on not having the LPSC index. Sorry. 
> >>>
> >>> How are the 'reg' property and the 'lpsc' property related? Does the
> >>> lpsc property modify the register address used to access the clock
> >>> control bits?
> >>>
> >> Yes it does. Currently all nodes use fix address and then lpsc is
> >> used as an index.
> > 
> > Ok cool. Well the reason I brought that up was because I even had the
> > idea to define these module clocks within the module nodes that own them
> > in DT. I am way outside of my DT knowledge at this point but I wonder
> > if the following type of binding is possible:
> > 
> > module: module@4a308200 {
> >       #address-cells = <1>;
> >       #size-cells = <1>;
> >       reg = <0x4a308200 0x1000>;
> > 
> >       clock {
> >               #clock-cells = <0>;
> >               compatible = "keystone,psc-clk";
> >               clocks = <&chipclk3>;
> >               clock-output-names = "debugss_trc";
> >               reg = <0x0256>;
> >               pd = <1>;
> >       };
> > };
> > 
> > Again, my DT knowledge is pretty limited, but could the reg property of
> > the clock be directly affected by the parent node? That seems like it
> > could nicely model what the hardware is really doing.
> > 
> The module(I assume you mean IP here) reg address space is separate than
> that used for clock control so that doesn't fit as such. Traditionally
> clock controls even though targeted for specific modules sits in different
> control as at least seen on OMAP and Keystone. OCP wrappers on OMAP
> were bit of exceptions but they were little bit of glue logic without
> much control within the address space.

Great, you perfectly answered my questions. I think that assigning the
"final" address to the 'reg' property is the right way to go (fixed
address + LPSC index).

Regards,
Mike

> 
> >> But I think we can do better by just using the
> >> right(offset) address in the reg property. Will have a look at it
> >> and see what I can do here.
> > 
> > This also solves the problem nicely.  Thanks for putting up with my
> > silly questions ;-)
> > 
> You asked right and good questions.
> 
> Regards,
> Santosh
Santosh Shilimkar Aug. 22, 2013, 2:10 p.m. UTC | #13
On Thursday 22 August 2013 04:12 AM, Mike Turquette wrote:
> Quoting Santosh Shilimkar (2013-08-21 06:16:33)
>> On Tuesday 20 August 2013 10:22 PM, Mike Turquette wrote:
>>> Quoting Santosh Shilimkar (2013-08-20 15:54:15)
>>>> On Tuesday 20 August 2013 06:41 PM, Mike Turquette wrote:
>>>>> Quoting Santosh Shilimkar (2013-08-20 14:55:56)
>>>>>> On Tuesday 20 August 2013 05:30 PM, Mike Turquette wrote:
>>>>
>>>> [...]
>>>>
>>>>>>>> They are bit different w.r.t OMAP. LPSC itself is the clock control of the
>>>>>>>> IP. The LPSC number in the bindings is actually the specific number which
>>>>>>>> is used to reach to the address space of the clock control. One can view
>>>>>>>> that one as clock control register index.
>>>>>>>
>>>>>>> Thanks for the information. I have a further question about then: are
>>>>>>> the LPSC clocks really module clocks that belong to the IP that they are
>>>>>>> gating?
>>>>>>>
>>>>>> LPSC controls the clock enable/disable to the IP/module so answer is yes.
>>>>>> In certain cases LPSC controls clock to more than one IP as well.
>>>>>>
>>>>>>> If so then they could be defined within the node defining their parent
>>>>>>> IP. That might be enough to get rid of the LPSC index value. Again I
>>>>>>> might be over-engineering it. Just trying to get an understanding.
>>>>>>>
>>>>>> Am not sure I follow you here on not having the LPSC index. Sorry. 
>>>>>
>>>>> How are the 'reg' property and the 'lpsc' property related? Does the
>>>>> lpsc property modify the register address used to access the clock
>>>>> control bits?
>>>>>
>>>> Yes it does. Currently all nodes use fix address and then lpsc is
>>>> used as an index.
>>>
>>> Ok cool. Well the reason I brought that up was because I even had the
>>> idea to define these module clocks within the module nodes that own them
>>> in DT. I am way outside of my DT knowledge at this point but I wonder
>>> if the following type of binding is possible:
>>>
>>> module: module@4a308200 {
>>>       #address-cells = <1>;
>>>       #size-cells = <1>;
>>>       reg = <0x4a308200 0x1000>;
>>>
>>>       clock {
>>>               #clock-cells = <0>;
>>>               compatible = "keystone,psc-clk";
>>>               clocks = <&chipclk3>;
>>>               clock-output-names = "debugss_trc";
>>>               reg = <0x0256>;
>>>               pd = <1>;
>>>       };
>>> };
>>>
>>> Again, my DT knowledge is pretty limited, but could the reg property of
>>> the clock be directly affected by the parent node? That seems like it
>>> could nicely model what the hardware is really doing.
>>>
>> The module(I assume you mean IP here) reg address space is separate than
>> that used for clock control so that doesn't fit as such. Traditionally
>> clock controls even though targeted for specific modules sits in different
>> control as at least seen on OMAP and Keystone. OCP wrappers on OMAP
>> were bit of exceptions but they were little bit of glue logic without
>> much control within the address space.
> 
> Great, you perfectly answered my questions. I think that assigning the
> "final" address to the 'reg' property is the right way to go (fixed
> address + LPSC index).
> 
Thanks Mike.

Regards,
Santosh
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt
new file mode 100644
index 0000000..40afef5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt
@@ -0,0 +1,30 @@ 
+Binding for Keystone gate control driver which uses PSC controller IP.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "keystone,psc-clk".
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : parent clock phandle
+- reg :	psc address address space
+
+Optional properties:
+- clock-output-names : From common clock binding to override the
+			default output clock name
+- status : "enabled" if clock is always enabled
+- lpsc : lpsc module id, if not set defaults to zero
+- pd : power domain number, if not set defaults to zero (always ON)
+- gpsc : gpsc number, if not set defaults to zero
+
+Example:
+	clock {
+		#clock-cells = <0>;
+		compatible = "keystone,psc-clk";
+		clocks = <&chipclk3>;
+		clock-output-names = "debugss_trc";
+		reg = <0x02350000 4096>;
+		lpsc = <5>;
+		pd = <1>;
+	};
diff --git a/drivers/clk/keystone/gate.c b/drivers/clk/keystone/gate.c
new file mode 100644
index 0000000..72ac478
--- /dev/null
+++ b/drivers/clk/keystone/gate.c
@@ -0,0 +1,306 @@ 
+/*
+ * Clock driver for Keystone 2 based devices
+ *
+ * Copyright (C) 2013 Texas Instruments.
+ *	Murali Karicheri <m-karicheri2@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/module.h>
+
+/* PSC register offsets */
+#define PTCMD			0x120
+#define PTSTAT			0x128
+#define PDSTAT			0x200
+#define PDCTL			0x300
+#define MDSTAT			0x800
+#define MDCTL			0xa00
+
+/* PSC module states */
+#define PSC_STATE_SWRSTDISABLE	0
+#define PSC_STATE_SYNCRST	1
+#define PSC_STATE_DISABLE	2
+#define PSC_STATE_ENABLE	3
+
+#define MDSTAT_STATE_MASK	0x3f
+#define MDSTAT_MCKOUT		BIT(12)
+#define PDSTAT_STATE_MASK	0x1f
+#define MDCTL_FORCE		BIT(31)
+#define MDCTL_LRESET		BIT(8)
+#define PDCTL_NEXT		BIT(0)
+
+/* PSC flags. Disable state is SwRstDisable */
+#define PSC_SWRSTDISABLE	BIT(0)
+/* Force module state transtition */
+#define PSC_FORCE		BIT(1)
+/* Keep module in local reset */
+#define PSC_LRESET		BIT(2)
+#define NUM_GPSC		2
+#define REG_OFFSET		4
+
+/**
+ * struct clk_psc_data - PSC data
+ * @base: Base address for a PSC
+ * @flags: framework flags
+ * @lpsc: Is it local PSC
+ * @gpsc: Is it global PSC
+ * @domain: PSC domain
+ *
+ */
+struct clk_psc_data {
+	void __iomem *base;
+	u32	flags;
+	u32	psc_flags;
+	u8	lpsc;
+	u8	gpsc;
+	u8	domain;
+};
+
+/**
+ * struct clk_psc - PSC clock structure
+ * @hw: clk_hw for the psc
+ * @psc_data: PSC driver specific data
+ * @lock: Spinlock used by the driver
+ */
+struct clk_psc {
+	struct clk_hw hw;
+	struct clk_psc_data *psc_data;
+	spinlock_t *lock;
+};
+
+struct reg_psc {
+	u32 phy_base;
+	u32 size;
+	void __iomem *io_base;
+};
+
+static struct reg_psc psc_addr[NUM_GPSC];
+static DEFINE_SPINLOCK(psc_lock);
+
+#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)
+
+static void psc_config(void __iomem *psc_base, unsigned int domain,
+		unsigned int id, bool enable, u32 flags)
+{
+	u32 ptcmd, pdstat, pdctl, mdstat, mdctl, next_state;
+
+	if (enable)
+		next_state = PSC_STATE_ENABLE;
+	else if (flags & PSC_SWRSTDISABLE)
+		next_state = PSC_STATE_SWRSTDISABLE;
+	else
+		next_state = PSC_STATE_DISABLE;
+
+	mdctl = readl(psc_base + MDCTL + REG_OFFSET * id);
+	mdctl &= ~MDSTAT_STATE_MASK;
+	mdctl |= next_state;
+	if (flags & PSC_FORCE)
+		mdctl |= MDCTL_FORCE;
+	if (flags & PSC_LRESET)
+		mdctl &= ~MDCTL_LRESET;
+	writel(mdctl, psc_base + MDCTL + REG_OFFSET * id);
+
+	pdstat = readl(psc_base + PDSTAT + REG_OFFSET * domain);
+	if (!(pdstat & PDSTAT_STATE_MASK)) {
+		pdctl = readl(psc_base + PDCTL + REG_OFFSET * domain);
+		pdctl |= PDCTL_NEXT;
+		writel(pdctl, psc_base + PDCTL + REG_OFFSET * domain);
+	}
+
+	ptcmd = 1 << domain;
+	writel(ptcmd, psc_base + PTCMD);
+	while ((readl(psc_base + PTSTAT) >> domain) & 1)
+		;
+
+	do {
+		mdstat = readl(psc_base + MDSTAT + REG_OFFSET * id);
+	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
+}
+
+static int keystone_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_psc *psc = to_clk_psc(hw);
+	struct clk_psc_data *data = psc->psc_data;
+	u32 mdstat = readl(data->base + MDSTAT + REG_OFFSET * data->lpsc);
+
+	return (mdstat & MDSTAT_MCKOUT) ? 1 : 0;
+}
+
+static int keystone_clk_enable(struct clk_hw *hw)
+{
+	struct clk_psc *psc = to_clk_psc(hw);
+	struct clk_psc_data *data = psc->psc_data;
+	unsigned long flags = 0;
+
+	if (psc->lock)
+		spin_lock_irqsave(psc->lock, flags);
+
+	psc_config(data->base, data->domain, data->lpsc, 1, data->psc_flags);
+
+	if (psc->lock)
+		spin_unlock_irqrestore(psc->lock, flags);
+
+	return 0;
+}
+
+static void keystone_clk_disable(struct clk_hw *hw)
+{
+	struct clk_psc *psc = to_clk_psc(hw);
+	struct clk_psc_data *data = psc->psc_data;
+	unsigned long flags = 0;
+
+	if (psc->lock)
+		spin_lock_irqsave(psc->lock, flags);
+
+	psc_config(data->base, data->domain, data->lpsc, 0, data->psc_flags);
+
+	if (psc->lock)
+		spin_unlock_irqrestore(psc->lock, flags);
+}
+
+static const struct clk_ops clk_psc_ops = {
+	.enable = keystone_clk_enable,
+	.disable = keystone_clk_disable,
+	.is_enabled = keystone_clk_is_enabled,
+};
+
+/**
+ * clk_register_psc - register psc clock
+ * @dev: device that is registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @psc_data: platform data to configure this clock
+ * @lock: spinlock used by this clock
+ */
+static struct clk *clk_register_psc(struct device *dev,
+			const char *name,
+			const char *parent_name,
+			struct clk_psc_data *psc_data,
+			spinlock_t *lock)
+{
+	struct clk_init_data init;
+	struct clk_psc *psc;
+	struct clk *clk;
+
+	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
+	if (!psc)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_psc_ops;
+	init.flags = psc_data->flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	psc->psc_data = psc_data;
+	psc->lock = lock;
+	psc->hw.init = &init;
+
+	clk = clk_register(NULL, &psc->hw);
+	if (IS_ERR(clk))
+		kfree(psc);
+
+	return clk;
+}
+
+/**
+ * of_psc_clk_init - initialize psc clock through DT
+ * @node: device tree node for this clock
+ * @lock: spinlock used by this clock
+ */
+static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock)
+{
+	const char *parent_name, *status = NULL, *base_flags = NULL;
+	struct clk_psc_data *data;
+	const char *clk_name = node->name;
+	u32 gpsc = 0, lpsc = 0, pd = 0;
+	struct resource res;
+	struct clk *clk;
+	int rc;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	WARN_ON(!data);
+
+	if (of_address_to_resource(node, 0, &res)) {
+		pr_err("psc_clk_init - no reg property defined\n");
+		goto out;
+	}
+
+	of_property_read_u32(node, "gpsc", &gpsc);
+	of_property_read_u32(node, "lpsc", &lpsc);
+	of_property_read_u32(node, "pd", &pd);
+
+	if (gpsc >= NUM_GPSC) {
+		pr_err("psc_clk_init - no reg property defined\n");
+		goto out;
+	}
+
+	of_property_read_string(node,
+			"clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(node, 0);
+	WARN_ON(!parent_name);
+
+	/* Expected that same phy_base is used for all psc clocks of
+	 * a give gpsc. So ioremap is done only once.
+	 */
+	if (psc_addr[gpsc].phy_base) {
+		if (psc_addr[gpsc].phy_base != res.start) {
+			pr_err("Different psc base for same GPSC\n");
+			goto out;
+		}
+	} else {
+		psc_addr[gpsc].phy_base = res.start;
+		psc_addr[gpsc].io_base =
+			ioremap(res.start, resource_size(&res));
+	}
+
+	WARN_ON(!psc_addr[gpsc].io_base);
+	data->base = psc_addr[gpsc].io_base;
+	data->lpsc = lpsc;
+	data->gpsc = gpsc;
+	data->domain = pd;
+
+	if (of_property_read_bool(node, "ti,psc-lreset"))
+		data->psc_flags |= PSC_LRESET;
+	if (of_property_read_bool(node, "ti,psc-force"))
+		data->psc_flags |= PSC_FORCE;
+
+	clk = clk_register_psc(NULL, clk_name, parent_name,
+				data, lock);
+
+	if (clk) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+		rc = of_property_read_string(node, "status", &status);
+		if (status && !strcmp(status, "enabled"))
+			clk_prepare_enable(clk);
+		return;
+	}
+	pr_err("psc_clk_init - error registering psc clk %s\n", node->name);
+out:
+	kfree(data);
+	return;
+}
+
+/**
+ * of_keystone_psc_clk_init - initialize psc clock through DT
+ * @node: device tree node for this clock
+ */
+void __init of_keystone_psc_clk_init(struct device_node *node)
+{
+	of_psc_clk_init(node, &psc_lock);
+}
+EXPORT_SYMBOL_GPL(of_keystone_psc_clk_init);
+CLK_OF_DECLARE(keystone_gate_clk, "keystone,psc-clk", of_keystone_psc_clk_init);
diff --git a/include/linux/clk/keystone.h b/include/linux/clk/keystone.h
index 1ade95d..7b3e154 100644
--- a/include/linux/clk/keystone.h
+++ b/include/linux/clk/keystone.h
@@ -14,5 +14,6 @@ 
 #define __LINUX_CLK_KEYSTONE_H_
 
 extern void of_keystone_pll_clk_init(struct device_node *node);
+extern void of_keystone_psc_clk_init(struct device_node *node);
 
 #endif /* __LINUX_CLK_KEYSTONE_H_ */