diff mbox

[V2] clk: hi6220: Add the hi655x's pmic clock

Message ID 1491683412-12237-1-git-send-email-daniel.lezcano@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Lezcano April 8, 2017, 8:30 p.m. UTC
The hi655x multi function device is a PMIC providing regulators.

The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
this clock in order to add it in the hi655x MFD and allow proper wireless
initialization.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---

Changelog:

 V2:
    - Added COMPILE_TEST option, compiled on x86
    - Removed useless parenthesis
    - Used of_clk_hw_simple_get() instead of deref dance
    - Do bailout if the clock-names is not specified
    - Rollback on error
    - Folded mfd line change and binding
    - Added #clock-cells binding documentation
    - Added #clock-cells in the DT

 V1: initial post
---
---
 .../devicetree/bindings/mfd/hisilicon,hi655x.txt   |   6 +
 arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   1 +
 drivers/clk/Kconfig                                |   8 ++
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-hi655x.c                           | 140 +++++++++++++++++++++
 drivers/mfd/hi655x-pmic.c                          |   3 +-
 6 files changed, 158 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-hi655x.c

Comments

Lee Jones April 11, 2017, 2:06 p.m. UTC | #1
On Sat, 08 Apr 2017, Daniel Lezcano wrote:

> The hi655x multi function device is a PMIC providing regulators.
> 
> The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
> this clock in order to add it in the hi655x MFD and allow proper wireless
> initialization.
> 
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> 
> Changelog:
> 
>  V2:
>     - Added COMPILE_TEST option, compiled on x86
>     - Removed useless parenthesis
>     - Used of_clk_hw_simple_get() instead of deref dance
>     - Do bailout if the clock-names is not specified
>     - Rollback on error
>     - Folded mfd line change and binding

Why did you do that?
Daniel Lezcano April 11, 2017, 9:19 p.m. UTC | #2
On Tue, Apr 11, 2017 at 03:06:13PM +0100, Lee Jones wrote:
> On Sat, 08 Apr 2017, Daniel Lezcano wrote:
> 
> > The hi655x multi function device is a PMIC providing regulators.
> > 
> > The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
> > this clock in order to add it in the hi655x MFD and allow proper wireless
> > initialization.
> > 
> > Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> > ---
> > 
> > Changelog:
> > 
> >  V2:
> >     - Added COMPILE_TEST option, compiled on x86
> >     - Removed useless parenthesis
> >     - Used of_clk_hw_simple_get() instead of deref dance
> >     - Do bailout if the clock-names is not specified
> >     - Rollback on error
> >     - Folded mfd line change and binding
> 
> Why did you do that?

I thought as the V1 had comments you would have waited for the V2 and as it was
trivial enough, it could be folded and picked up via the clk tree via with your
acked-by.

I realize it was not a good idea.

Do you want to drop it from your tree or shall I resubmit a V3 without the mfd
change?
Lee Jones April 12, 2017, 8 a.m. UTC | #3
On Tue, 11 Apr 2017, Daniel Lezcano wrote:

> On Tue, Apr 11, 2017 at 03:06:13PM +0100, Lee Jones wrote:
> > On Sat, 08 Apr 2017, Daniel Lezcano wrote:
> > 
> > > The hi655x multi function device is a PMIC providing regulators.
> > > 
> > > The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
> > > this clock in order to add it in the hi655x MFD and allow proper wireless
> > > initialization.
> > > 
> > > Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> > > ---
> > > 
> > > Changelog:
> > > 
> > >  V2:
> > >     - Added COMPILE_TEST option, compiled on x86
> > >     - Removed useless parenthesis
> > >     - Used of_clk_hw_simple_get() instead of deref dance
> > >     - Do bailout if the clock-names is not specified
> > >     - Rollback on error
> > >     - Folded mfd line change and binding
> > 
> > Why did you do that?
> 
> I thought as the V1 had comments you would have waited for the V2 and as it was
> trivial enough, it could be folded and picked up via the clk tree via with your
> acked-by.

It's *always* a good idea to keep patches subsystem orthogonal if
at all possible.

> I realize it was not a good idea.
> 
> Do you want to drop it from your tree or shall I resubmit a V3 without the mfd
> change?

The latter please.
Daniel Lezcano April 12, 2017, 12:10 p.m. UTC | #4
On 12/04/2017 10:00, Lee Jones wrote:
> On Tue, 11 Apr 2017, Daniel Lezcano wrote:
> 
>> On Tue, Apr 11, 2017 at 03:06:13PM +0100, Lee Jones wrote:
>>> On Sat, 08 Apr 2017, Daniel Lezcano wrote:
>>>
>>>> The hi655x multi function device is a PMIC providing regulators.
>>>>
>>>> The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
>>>> this clock in order to add it in the hi655x MFD and allow proper wireless
>>>> initialization.
>>>>
>>>> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>

[ ... ]

>> Do you want to drop it from your tree or shall I resubmit a V3 without the mfd
>> change?
> 
> The latter please.

Ok.

What about the DT binding change?
Lee Jones April 12, 2017, 1:34 p.m. UTC | #5
On Wed, 12 Apr 2017, Daniel Lezcano wrote:

> On 12/04/2017 10:00, Lee Jones wrote:
> > On Tue, 11 Apr 2017, Daniel Lezcano wrote:
> > 
> >> On Tue, Apr 11, 2017 at 03:06:13PM +0100, Lee Jones wrote:
> >>> On Sat, 08 Apr 2017, Daniel Lezcano wrote:
> >>>
> >>>> The hi655x multi function device is a PMIC providing regulators.
> >>>>
> >>>> The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
> >>>> this clock in order to add it in the hi655x MFD and allow proper wireless
> >>>> initialization.
> >>>>
> >>>> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> 
> [ ... ]
> 
> >> Do you want to drop it from your tree or shall I resubmit a V3 without the mfd
> >> change?
> > 
> > The latter please.
> 
> Ok.
> 
> What about the DT binding change?

If I haven't merged it already, you'll need to re-send that
(separately) too.
Stephen Boyd April 12, 2017, 3:02 p.m. UTC | #6
On 04/08, Daniel Lezcano wrote:
>  
>  Example:
>  	pmic: pmic@f8000000 {
> @@ -24,4 +29,5 @@ Example:
>  		interrupt-controller;
>  		#interrupt-cells = <2>;
>  		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
> +		clock-cells = <0>;

Should be #clock-cells instead.

>  	}
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 92c12b8..c19983a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -36,6 +36,7 @@ obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
>  obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
>  obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
>  obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
> +obj-$(CONFIG_COMMON_CLK_HI655X)		+= clk-hi655x.o
>  obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
>  obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
>  obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
> diff --git a/drivers/clk/clk-hi655x.c b/drivers/clk/clk-hi655x.c
> new file mode 100644
> index 0000000..b2bea32
> --- /dev/null
> +++ b/drivers/clk/clk-hi655x.c
> @@ -0,0 +1,140 @@
> +
> +static int hi655x_clk_probe(struct platform_device *pdev)
> +{
> +	struct device *parent = pdev->dev.parent;
> +	struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
> +	struct clk_init_data *hi655x_clk_init;

This can just go onto the stack? We don't need it around after
probe.

> +	struct hi655x_clk *hi655x_clk;
> +	const char *clk_name = "hi655x-clk";
> +	int ret;
> +
> +	hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
> +	if (!hi655x_clk)
> +		return -ENOMEM;
> +
> +	hi655x_clk_init = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk_init),
> +				       GFP_KERNEL);
> +	if (!hi655x_clk_init)
> +		return -ENOMEM;
> +
> +	of_property_read_string_index(parent->of_node, "clock-output-names",
> +				      0, &clk_name);
> +
> +	hi655x_clk_init->name	= clk_name;
> +	hi655x_clk_init->ops	= &hi655x_clk_ops;
> +
> +	hi655x_clk->clk_hw.init	= hi655x_clk_init;
> +	hi655x_clk->hi655x	= hi655x;
> +
> +	platform_set_drvdata(pdev, hi655x_clk);
> +
> +	ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
> +	if (ret)
> +		return ret;
> +
> +	ret = of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
> +				     &hi655x_clk->clk_hw);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);

Missed this last time. Do you use this clkdev lookup? The name is
usually supposed to be based on what the device is expecting,
instead of clk_name, and we would want some device name for the
third argument here.

> +	if (ret)
> +		of_clk_del_provider(parent->of_node);
> +
> +	return ret;
Daniel Lezcano April 16, 2017, 8:57 p.m. UTC | #7
On Wed, Apr 12, 2017 at 08:02:45AM -0700, Stephen Boyd wrote:
> On 04/08, Daniel Lezcano wrote:
> >  
> >  Example:
> >  	pmic: pmic@f8000000 {
> > @@ -24,4 +29,5 @@ Example:
> >  		interrupt-controller;
> >  		#interrupt-cells = <2>;
> >  		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
> > +		clock-cells = <0>;
> 
> Should be #clock-cells instead.

Ok.

> > +static int hi655x_clk_probe(struct platform_device *pdev)
> > +{
> > +	struct device *parent = pdev->dev.parent;
> > +	struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
> > +	struct clk_init_data *hi655x_clk_init;
> 
> This can just go onto the stack? We don't need it around after
> probe.

Agree.
 
> > +	struct hi655x_clk *hi655x_clk;
> > +	const char *clk_name = "hi655x-clk";
> > +	int ret;
> > +
> > +	hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
> > +	if (!hi655x_clk)
> > +		return -ENOMEM;
> > +
> > +	hi655x_clk_init = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk_init),
> > +				       GFP_KERNEL);
> > +	if (!hi655x_clk_init)
> > +		return -ENOMEM;
> > +
> > +	of_property_read_string_index(parent->of_node, "clock-output-names",
> > +				      0, &clk_name);
> > +
> > +	hi655x_clk_init->name	= clk_name;
> > +	hi655x_clk_init->ops	= &hi655x_clk_ops;
> > +
> > +	hi655x_clk->clk_hw.init	= hi655x_clk_init;
> > +	hi655x_clk->hi655x	= hi655x;
> > +
> > +	platform_set_drvdata(pdev, hi655x_clk);
> > +
> > +	ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
> > +				     &hi655x_clk->clk_hw);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
> 
> Missed this last time. Do you use this clkdev lookup? The name is
> usually supposed to be based on what the device is expecting,
> instead of clk_name, and we would want some device name for the
> third argument here.

I'm not sure to get your comment. Are you saying the clk_name should be the
third argument?
Stephen Boyd April 19, 2017, 4 p.m. UTC | #8
On 04/16, Daniel Lezcano wrote:
> On Wed, Apr 12, 2017 at 08:02:45AM -0700, Stephen Boyd wrote:
> > On 04/08, Daniel Lezcano wrote:
>  
> > > +	struct hi655x_clk *hi655x_clk;
> > > +	const char *clk_name = "hi655x-clk";
> > > +	int ret;
> > > +
> > > +	hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
> > > +	if (!hi655x_clk)
> > > +		return -ENOMEM;
> > > +
> > > +	hi655x_clk_init = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk_init),
> > > +				       GFP_KERNEL);
> > > +	if (!hi655x_clk_init)
> > > +		return -ENOMEM;
> > > +
> > > +	of_property_read_string_index(parent->of_node, "clock-output-names",
> > > +				      0, &clk_name);
> > > +
> > > +	hi655x_clk_init->name	= clk_name;
> > > +	hi655x_clk_init->ops	= &hi655x_clk_ops;
> > > +
> > > +	hi655x_clk->clk_hw.init	= hi655x_clk_init;
> > > +	hi655x_clk->hi655x	= hi655x;
> > > +
> > > +	platform_set_drvdata(pdev, hi655x_clk);
> > > +
> > > +	ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	ret = of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
> > > +				     &hi655x_clk->clk_hw);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
> > 
> > Missed this last time. Do you use this clkdev lookup? The name is
> > usually supposed to be based on what the device is expecting,
> > instead of clk_name, and we would want some device name for the
> > third argument here.
> 
> I'm not sure to get your comment. Are you saying the clk_name should be the
> third argument?
> 
> 

Sorry, no. I meant that con_id is typically something like "core"
or "ahb" or something like that, and dev_id is something like
"a456002.pmic_device" or whatever dev_name(pmic_dev) would return for
the consuming device. That way when we call clk_get(dev, "core")
it will find the lookup with "core" and "a456002.pmic_device" to
match up the clk lookup.

If anything, the clk_name should just go into the con_id for now,
and then it will need to be a globally unique identifier for the
clk. But that is going against how clkdev is supposed to be used.
Hence the question if you even need to use it. If not, just don't
add it. I can fix up v3 of this patch to put clk_name back at
con_id if you like. No need to resend.
Daniel Lezcano April 19, 2017, 7:47 p.m. UTC | #9
On Wed, Apr 19, 2017 at 09:00:05AM -0700, Stephen Boyd wrote:
> On 04/16, Daniel Lezcano wrote:
> > On Wed, Apr 12, 2017 at 08:02:45AM -0700, Stephen Boyd wrote:
> > > On 04/08, Daniel Lezcano wrote:

[ ... ]

> > > > +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
> > > 
> > > Missed this last time. Do you use this clkdev lookup? The name is
> > > usually supposed to be based on what the device is expecting,
> > > instead of clk_name, and we would want some device name for the
> > > third argument here.
> > 
> > I'm not sure to get your comment. Are you saying the clk_name should be the
> > third argument?
> > 
> > 
> 
> Sorry, no. I meant that con_id is typically something like "core"
> or "ahb" or something like that, and dev_id is something like
> "a456002.pmic_device" or whatever dev_name(pmic_dev) would return for
> the consuming device. That way when we call clk_get(dev, "core")
> it will find the lookup with "core" and "a456002.pmic_device" to
> match up the clk lookup.
> 
> If anything, the clk_name should just go into the con_id for now,
> and then it will need to be a globally unique identifier for the
> clk. But that is going against how clkdev is supposed to be used.
> Hence the question if you even need to use it. If not, just don't
> add it. I can fix up v3 of this patch to put clk_name back at
> con_id if you like. No need to resend.

Ok, I'm not very used with the CCF, so perhaps clk_name is not needed at all. I
gave a try with the following combination:

 - con_id = NULL, dev_id = clk_name
 - con_id = clk_name, dev_id = NULL
 - con_id = NULL, dev_id = NULL

All worked.

And finally I removed the clk_hw_register_clkdev() call and it worked also.

So I'm not sure about this function.

Any idea ?

> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> a Linux Foundation Collaborative Project
Stephen Boyd April 22, 2017, 2:14 a.m. UTC | #10
On 04/19, Daniel Lezcano wrote:
> On Wed, Apr 19, 2017 at 09:00:05AM -0700, Stephen Boyd wrote:
> > On 04/16, Daniel Lezcano wrote:
> > > On Wed, Apr 12, 2017 at 08:02:45AM -0700, Stephen Boyd wrote:
> > > > On 04/08, Daniel Lezcano wrote:
> 
> [ ... ]
> 
> > > > > +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
> > > > 
> > > > Missed this last time. Do you use this clkdev lookup? The name is
> > > > usually supposed to be based on what the device is expecting,
> > > > instead of clk_name, and we would want some device name for the
> > > > third argument here.
> > > 
> > > I'm not sure to get your comment. Are you saying the clk_name should be the
> > > third argument?
> > > 
> > > 
> > 
> > Sorry, no. I meant that con_id is typically something like "core"
> > or "ahb" or something like that, and dev_id is something like
> > "a456002.pmic_device" or whatever dev_name(pmic_dev) would return for
> > the consuming device. That way when we call clk_get(dev, "core")
> > it will find the lookup with "core" and "a456002.pmic_device" to
> > match up the clk lookup.
> > 
> > If anything, the clk_name should just go into the con_id for now,
> > and then it will need to be a globally unique identifier for the
> > clk. But that is going against how clkdev is supposed to be used.
> > Hence the question if you even need to use it. If not, just don't
> > add it. I can fix up v3 of this patch to put clk_name back at
> > con_id if you like. No need to resend.
> 
> Ok, I'm not very used with the CCF, so perhaps clk_name is not needed at all. I
> gave a try with the following combination:
> 
>  - con_id = NULL, dev_id = clk_name
>  - con_id = clk_name, dev_id = NULL
>  - con_id = NULL, dev_id = NULL
> 
> All worked.
> 
> And finally I removed the clk_hw_register_clkdev() call and it worked also.
> 
> So I'm not sure about this function.
> 

If you've removed it and it still works, then it means you're
using DT and you don't need clkdev at all. That's the of_clk
provider thing that you're using. So I'll go remove this clkdev
lookup because it's not used. If someone needs it they can add it
later.
Lee Jones April 24, 2017, 9:31 a.m. UTC | #11
On Sat, 08 Apr 2017, Daniel Lezcano wrote:

> The hi655x multi function device is a PMIC providing regulators.
> 
> The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
> this clock in order to add it in the hi655x MFD and allow proper wireless
> initialization.
> 
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
> 
> Changelog:
> 
>  V2:
>     - Added COMPILE_TEST option, compiled on x86
>     - Removed useless parenthesis
>     - Used of_clk_hw_simple_get() instead of deref dance
>     - Do bailout if the clock-names is not specified
>     - Rollback on error
>     - Folded mfd line change and binding
>     - Added #clock-cells binding documentation
>     - Added #clock-cells in the DT
> 
>  V1: initial post
> ---

??

> ---

I'm unsure if this as been mentioned before, but bundling;
driver & architecture changes and documentation into a single patch is
very seldom a good idea.  In this case, you should split this into at
least 3, perhaps 4 patches.

>  .../devicetree/bindings/mfd/hisilicon,hi655x.txt   |   6 +

Patch 1

>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   1 +

Patch 2

>  drivers/clk/Kconfig                                |   8 ++
>  drivers/clk/Makefile                               |   1 +
>  drivers/clk/clk-hi655x.c                           | 140 +++++++++++++++++++++

Patch 3

>  drivers/mfd/hi655x-pmic.c                          |   3 +-

Patch 4

[...]

>  6 files changed, 158 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/clk-hi655x.c
> 
> diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt b/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
> index 0548569..194e2a9fd 100644
> --- a/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
> +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
> @@ -16,6 +16,11 @@ Required properties:
>  - reg:                  Base address of PMIC on Hi6220 SoC.
>  - interrupt-controller: Hi655x has internal IRQs (has own IRQ domain).
>  - pmic-gpios:           The GPIO used by PMIC IRQ.
> +- #clock-cells:		From common clock binding; shall be set to 0
> +
> +Optional properties:
> +- clock-output-names: From common clock binding to override the
> +  default output clock name
>  
>  Example:
>  	pmic: pmic@f8000000 {
> @@ -24,4 +29,5 @@ Example:
>  		interrupt-controller;
>  		#interrupt-cells = <2>;
>  		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
> +		clock-cells = <0>;
>  	}
> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> index dba3c13..bb9afb1 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
> @@ -328,6 +328,7 @@
>  		interrupt-controller;
>  		#interrupt-cells = <2>;
>  		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
> +		#clock-cells = <0>;
>  
>  		regulators {
>  			ldo2: LDO2 {
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 9356ab4..36cfea3 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -47,6 +47,14 @@ config COMMON_CLK_RK808
>  	  clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
>  	  by control register.
>  
> +config COMMON_CLK_HI655X
> +	tristate "Clock driver for Hi655x"
> +	depends on MFD_HI655X_PMIC || COMPILE_TEST
> +	---help---
> +	  This driver supports the hi655x PMIC clock. This
> +	  multi-function device has one fixed-rate oscillator, clocked
> +	  at 32KHz.
> +
>  config COMMON_CLK_SCPI
>  	tristate "Clock driver controlled via SCPI interface"
>  	depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 92c12b8..c19983a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -36,6 +36,7 @@ obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
>  obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
>  obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
>  obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
> +obj-$(CONFIG_COMMON_CLK_HI655X)		+= clk-hi655x.o
>  obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
>  obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
>  obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
> diff --git a/drivers/clk/clk-hi655x.c b/drivers/clk/clk-hi655x.c
> new file mode 100644
> index 0000000..b2bea32
> --- /dev/null
> +++ b/drivers/clk/clk-hi655x.c
> @@ -0,0 +1,140 @@
> +/*
> + * Clock driver for Hi655x
> + *
> + * Copyright (c) 2016, Linaro Ltd.
> + *
> + * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + */
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mfd/hi655x-pmic.h>
> +
> +#define HI655X_CLK_BASE	HI655X_BUS_ADDR(0x1c)
> +#define HI655X_CLK_SET	BIT(6)
> +
> +struct hi655x_clk {
> +	struct hi655x_pmic *hi655x;
> +	struct clk_hw       clk_hw;
> +};
> +
> +static unsigned long hi655x_clk_recalc_rate(struct clk_hw *hw,
> +					    unsigned long parent_rate)
> +{
> +	return 32768;
> +}
> +
> +static int hi655x_clk_enable(struct clk_hw *hw, bool enable)
> +{
> +	struct hi655x_clk *hi655x_clk =
> +		container_of(hw, struct hi655x_clk, clk_hw);
> +
> +	struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
> +
> +	return regmap_update_bits(hi655x->regmap, HI655X_CLK_BASE,
> +				  HI655X_CLK_SET, enable ? HI655X_CLK_SET : 0);
> +}
> +
> +static int hi655x_clk_prepare(struct clk_hw *hw)
> +{
> +	return hi655x_clk_enable(hw, true);
> +}
> +
> +static void hi655x_clk_unprepare(struct clk_hw *hw)
> +{
> +	hi655x_clk_enable(hw, false);
> +}
> +
> +static int hi655x_clk_is_prepared(struct clk_hw *hw)
> +{
> +	struct hi655x_clk *hi655x_clk =
> +		container_of(hw, struct hi655x_clk, clk_hw);
> +	struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
> +	int ret;
> +	uint32_t val;
> +
> +	ret = regmap_read(hi655x->regmap, HI655X_CLK_BASE, &val);
> +	if (ret < 0)
> +		return ret;
> +
> +	return val & HI655X_CLK_BASE;
> +}
> +
> +static const struct clk_ops hi655x_clk_ops = {
> +	.prepare     = hi655x_clk_prepare,
> +	.unprepare   = hi655x_clk_unprepare,
> +	.is_prepared = hi655x_clk_is_prepared,
> +	.recalc_rate = hi655x_clk_recalc_rate,
> +};
> +
> +static int hi655x_clk_probe(struct platform_device *pdev)
> +{
> +	struct device *parent = pdev->dev.parent;
> +	struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
> +	struct clk_init_data *hi655x_clk_init;
> +	struct hi655x_clk *hi655x_clk;
> +	const char *clk_name = "hi655x-clk";
> +	int ret;
> +
> +	hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
> +	if (!hi655x_clk)
> +		return -ENOMEM;
> +
> +	hi655x_clk_init = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk_init),
> +				       GFP_KERNEL);
> +	if (!hi655x_clk_init)
> +		return -ENOMEM;
> +
> +	of_property_read_string_index(parent->of_node, "clock-output-names",
> +				      0, &clk_name);
> +
> +	hi655x_clk_init->name	= clk_name;
> +	hi655x_clk_init->ops	= &hi655x_clk_ops;
> +
> +	hi655x_clk->clk_hw.init	= hi655x_clk_init;
> +	hi655x_clk->hi655x	= hi655x;
> +
> +	platform_set_drvdata(pdev, hi655x_clk);
> +
> +	ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
> +	if (ret)
> +		return ret;
> +
> +	ret = of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
> +				     &hi655x_clk->clk_hw);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
> +	if (ret)
> +		of_clk_del_provider(parent->of_node);
> +
> +	return ret;
> +}
> +
> +static struct platform_driver hi655x_clk_driver = {
> +	.probe =  hi655x_clk_probe,
> +	.driver		= {
> +		.name	= "hi655x-clk",
> +	},
> +};
> +
> +module_platform_driver(hi655x_clk_driver);
> +
> +MODULE_DESCRIPTION("Clk driver for the hi655x series PMICs");
> +MODULE_AUTHOR("Daniel Lezcano <daniel.lezcano@linaro.org>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:hi655x-clk");
> diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c
> index ba706ad..c37ccbf 100644
> --- a/drivers/mfd/hi655x-pmic.c
> +++ b/drivers/mfd/hi655x-pmic.c
> @@ -77,7 +77,8 @@
>  		.num_resources	= ARRAY_SIZE(pwrkey_resources),
>  		.resources	= &pwrkey_resources[0],
>  	},
> -	{	.name		= "hi655x-regulator", },
> +	{	.name		= "hi655x-regulator",	},
> +	{	.name		= "hi655x-clk",		},
>  };
>  
>  static void hi655x_local_irq_clear(struct regmap *map)
Daniel Lezcano April 24, 2017, 9:43 a.m. UTC | #12
On Mon, Apr 24, 2017 at 10:31:54AM +0100, Lee Jones wrote:
> On Sat, 08 Apr 2017, Daniel Lezcano wrote:
> 
> > The hi655x multi function device is a PMIC providing regulators.
> > 
> > The PMIC also provides a clock for the WiFi and the Bluetooth, let's implement
> > this clock in order to add it in the hi655x MFD and allow proper wireless
> > initialization.
> > 
> > Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> > ---
> > 
> > Changelog:
> > 
> >  V2:
> >     - Added COMPILE_TEST option, compiled on x86
> >     - Removed useless parenthesis
> >     - Used of_clk_hw_simple_get() instead of deref dance
> >     - Do bailout if the clock-names is not specified
> >     - Rollback on error
> >     - Folded mfd line change and binding
> >     - Added #clock-cells binding documentation
> >     - Added #clock-cells in the DT
> > 
> >  V1: initial post
> > ---
> 
> ??
> 
> > ---
> 
> I'm unsure if this as been mentioned before, but bundling;
> driver & architecture changes and documentation into a single patch is
> very seldom a good idea.  In this case, you should split this into at
> least 3, perhaps 4 patches.
> 
> >  .../devicetree/bindings/mfd/hisilicon,hi655x.txt   |   6 +
> 
> Patch 1
> 
> >  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts     |   1 +
> 
> Patch 2
> 
> >  drivers/clk/Kconfig                                |   8 ++
> >  drivers/clk/Makefile                               |   1 +
> >  drivers/clk/clk-hi655x.c                           | 140 +++++++++++++++++++++
> 
> Patch 3
> 
> >  drivers/mfd/hi655x-pmic.c                          |   3 +-
> 
> Patch 4
> 
> [...]

Yep. Will do that next time.

Thanks.

  -- Daniel
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt b/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
index 0548569..194e2a9fd 100644
--- a/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
@@ -16,6 +16,11 @@  Required properties:
 - reg:                  Base address of PMIC on Hi6220 SoC.
 - interrupt-controller: Hi655x has internal IRQs (has own IRQ domain).
 - pmic-gpios:           The GPIO used by PMIC IRQ.
+- #clock-cells:		From common clock binding; shall be set to 0
+
+Optional properties:
+- clock-output-names: From common clock binding to override the
+  default output clock name
 
 Example:
 	pmic: pmic@f8000000 {
@@ -24,4 +29,5 @@  Example:
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		clock-cells = <0>;
 	}
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
index dba3c13..bb9afb1 100644
--- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
@@ -328,6 +328,7 @@ 
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		#clock-cells = <0>;
 
 		regulators {
 			ldo2: LDO2 {
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9356ab4..36cfea3 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -47,6 +47,14 @@  config COMMON_CLK_RK808
 	  clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
 	  by control register.
 
+config COMMON_CLK_HI655X
+	tristate "Clock driver for Hi655x"
+	depends on MFD_HI655X_PMIC || COMPILE_TEST
+	---help---
+	  This driver supports the hi655x PMIC clock. This
+	  multi-function device has one fixed-rate oscillator, clocked
+	  at 32KHz.
+
 config COMMON_CLK_SCPI
 	tristate "Clock driver controlled via SCPI interface"
 	depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 92c12b8..c19983a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -36,6 +36,7 @@  obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
+obj-$(CONFIG_COMMON_CLK_HI655X)		+= clk-hi655x.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
diff --git a/drivers/clk/clk-hi655x.c b/drivers/clk/clk-hi655x.c
new file mode 100644
index 0000000..b2bea32
--- /dev/null
+++ b/drivers/clk/clk-hi655x.c
@@ -0,0 +1,140 @@ 
+/*
+ * Clock driver for Hi655x
+ *
+ * Copyright (c) 2016, Linaro Ltd.
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/hi655x-pmic.h>
+
+#define HI655X_CLK_BASE	HI655X_BUS_ADDR(0x1c)
+#define HI655X_CLK_SET	BIT(6)
+
+struct hi655x_clk {
+	struct hi655x_pmic *hi655x;
+	struct clk_hw       clk_hw;
+};
+
+static unsigned long hi655x_clk_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	return 32768;
+}
+
+static int hi655x_clk_enable(struct clk_hw *hw, bool enable)
+{
+	struct hi655x_clk *hi655x_clk =
+		container_of(hw, struct hi655x_clk, clk_hw);
+
+	struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
+
+	return regmap_update_bits(hi655x->regmap, HI655X_CLK_BASE,
+				  HI655X_CLK_SET, enable ? HI655X_CLK_SET : 0);
+}
+
+static int hi655x_clk_prepare(struct clk_hw *hw)
+{
+	return hi655x_clk_enable(hw, true);
+}
+
+static void hi655x_clk_unprepare(struct clk_hw *hw)
+{
+	hi655x_clk_enable(hw, false);
+}
+
+static int hi655x_clk_is_prepared(struct clk_hw *hw)
+{
+	struct hi655x_clk *hi655x_clk =
+		container_of(hw, struct hi655x_clk, clk_hw);
+	struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
+	int ret;
+	uint32_t val;
+
+	ret = regmap_read(hi655x->regmap, HI655X_CLK_BASE, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & HI655X_CLK_BASE;
+}
+
+static const struct clk_ops hi655x_clk_ops = {
+	.prepare     = hi655x_clk_prepare,
+	.unprepare   = hi655x_clk_unprepare,
+	.is_prepared = hi655x_clk_is_prepared,
+	.recalc_rate = hi655x_clk_recalc_rate,
+};
+
+static int hi655x_clk_probe(struct platform_device *pdev)
+{
+	struct device *parent = pdev->dev.parent;
+	struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
+	struct clk_init_data *hi655x_clk_init;
+	struct hi655x_clk *hi655x_clk;
+	const char *clk_name = "hi655x-clk";
+	int ret;
+
+	hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
+	if (!hi655x_clk)
+		return -ENOMEM;
+
+	hi655x_clk_init = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk_init),
+				       GFP_KERNEL);
+	if (!hi655x_clk_init)
+		return -ENOMEM;
+
+	of_property_read_string_index(parent->of_node, "clock-output-names",
+				      0, &clk_name);
+
+	hi655x_clk_init->name	= clk_name;
+	hi655x_clk_init->ops	= &hi655x_clk_ops;
+
+	hi655x_clk->clk_hw.init	= hi655x_clk_init;
+	hi655x_clk->hi655x	= hi655x;
+
+	platform_set_drvdata(pdev, hi655x_clk);
+
+	ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
+	if (ret)
+		return ret;
+
+	ret = of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
+				     &hi655x_clk->clk_hw);
+	if (ret)
+		return ret;
+
+	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
+	if (ret)
+		of_clk_del_provider(parent->of_node);
+
+	return ret;
+}
+
+static struct platform_driver hi655x_clk_driver = {
+	.probe =  hi655x_clk_probe,
+	.driver		= {
+		.name	= "hi655x-clk",
+	},
+};
+
+module_platform_driver(hi655x_clk_driver);
+
+MODULE_DESCRIPTION("Clk driver for the hi655x series PMICs");
+MODULE_AUTHOR("Daniel Lezcano <daniel.lezcano@linaro.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hi655x-clk");
diff --git a/drivers/mfd/hi655x-pmic.c b/drivers/mfd/hi655x-pmic.c
index ba706ad..c37ccbf 100644
--- a/drivers/mfd/hi655x-pmic.c
+++ b/drivers/mfd/hi655x-pmic.c
@@ -77,7 +77,8 @@ 
 		.num_resources	= ARRAY_SIZE(pwrkey_resources),
 		.resources	= &pwrkey_resources[0],
 	},
-	{	.name		= "hi655x-regulator", },
+	{	.name		= "hi655x-regulator",	},
+	{	.name		= "hi655x-clk",		},
 };
 
 static void hi655x_local_irq_clear(struct regmap *map)