[PATCH 1/3] reset: Add of_reset_control_get

62 views
Skip to first unread message

Maxime Ripard

unread,
Dec 20, 2013, 4:41:07 PM12/20/13
to p.z...@pengutronix.de, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Maxime Ripard
In some cases, you might need to deassert from reset an hardware block that
doesn't associated to a struct device (CPUs, timers, etc.).

Add a small helper to retrieve the reset controller from the device tree
without the need to pass a struct device.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
drivers/reset/core.c | 39 ++++++++++++++++++++++++++++++---------
include/linux/reset.h | 4 ++++
2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index d1b6089..4f3dda7 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -127,15 +127,16 @@ int reset_control_deassert(struct reset_control *rstc)
EXPORT_SYMBOL_GPL(reset_control_deassert);

/**
- * reset_control_get - Lookup and obtain a reference to a reset controller.
- * @dev: device to be reset by the controller
+ * of_reset_control_get - Lookup and obtain a reference to a reset controller.
+ * @node: device to be reset by the controller
* @id: reset line name
*
* Returns a struct reset_control or IS_ERR() condition containing errno.
*
* Use of id names is optional.
*/
-struct reset_control *reset_control_get(struct device *dev, const char *id)
+struct reset_control *of_reset_control_get(struct device_node *node,
+ const char *id)
{
struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER);
struct reset_controller_dev *r, *rcdev;
@@ -144,13 +145,10 @@ struct reset_control *reset_control_get(struct device *dev, const char *id)
int rstc_id;
int ret;

- if (!dev)
- return ERR_PTR(-EINVAL);
-
if (id)
- index = of_property_match_string(dev->of_node,
+ index = of_property_match_string(node,
"reset-names", id);
- ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells",
+ ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
index, &args);
if (ret)
return ERR_PTR(ret);
@@ -185,12 +183,35 @@ struct reset_control *reset_control_get(struct device *dev, const char *id)
return ERR_PTR(-ENOMEM);
}

- rstc->dev = dev;
rstc->rcdev = rcdev;
rstc->id = rstc_id;

return rstc;
}
+EXPORT_SYMBOL_GPL(of_reset_control_get);
+
+/**
+ * reset_control_get - Lookup and obtain a reference to a reset controller.
+ * @dev: device to be reset by the controller
+ * @id: reset line name
+ *
+ * Returns a struct reset_control or IS_ERR() condition containing errno.
+ *
+ * Use of id names is optional.
+ */
+struct reset_control *reset_control_get(struct device *dev, const char *id)
+{
+ struct reset_control *rstc;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ rstc = of_reset_control_get(dev->of_node, id);
+ if (!IS_ERR(rstc))
+ rstc->dev = dev;
+
+ return rstc;
+}
EXPORT_SYMBOL_GPL(reset_control_get);

/**
diff --git a/include/linux/reset.h b/include/linux/reset.h
index 6082247..a398025 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -1,6 +1,8 @@
#ifndef _LINUX_RESET_H_
#define _LINUX_RESET_H_

+#include <linux/of.h>
+
struct device;
struct reset_control;

@@ -8,6 +10,8 @@ int reset_control_reset(struct reset_control *rstc);
int reset_control_assert(struct reset_control *rstc);
int reset_control_deassert(struct reset_control *rstc);

+struct reset_control *of_reset_control_get(struct device_node *node,
+ const char *id);
struct reset_control *reset_control_get(struct device *dev, const char *id);
void reset_control_put(struct reset_control *rstc);
struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
--
1.8.4.2

Maxime Ripard

unread,
Dec 20, 2013, 4:41:08 PM12/20/13
to p.z...@pengutronix.de, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Maxime Ripard
The Allwinner A31 that uses this timer has the timer IP asserted in reset.
Add an optional reset property to the DT, and deassert the timer from reset if
it's there.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
.../devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt | 4 ++++
drivers/clocksource/timer-sun5i.c | 6 ++++++
2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
index 7c26154..27cfc7d 100644
--- a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
+++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.txt
@@ -9,6 +9,9 @@ Required properties:
one)
- clocks: phandle to the source clock (usually the AHB clock)

+Optionnal properties:
+- resets: phandle to a reset controller asserting the timer
+
Example:

timer@01c60000 {
@@ -19,4 +22,5 @@ timer@01c60000 {
<0 53 1>,
<0 54 1>;
clocks = <&ahb1_gates 19>;
+ resets = <&ahb1rst 19>;
};
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index bddc522..f74d75e 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
+#include <linux/reset.h>
#include <linux/sched_clock.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -143,6 +144,7 @@ static u32 sun5i_timer_sched_read(void)

static void __init sun5i_timer_init(struct device_node *node)
{
+ struct reset_control *rstc;
unsigned long rate;
struct clk *clk;
int ret, irq;
@@ -162,6 +164,10 @@ static void __init sun5i_timer_init(struct device_node *node)
clk_prepare_enable(clk);
rate = clk_get_rate(clk);

+ rstc = of_reset_control_get(node, NULL);
+ if (!IS_ERR(rstc))
+ reset_control_deassert(rstc);
+
writel(~0, timer_base + TIMER_INTVAL_LO_REG(1));
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
timer_base + TIMER_CTL_REG(1));
--
1.8.4.2

Maxime Ripard

unread,
Dec 20, 2013, 4:41:09 PM12/20/13
to p.z...@pengutronix.de, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Maxime Ripard
The Allwinner A31 has support for four high speed timers. Apart for the
number of timers (4 vs 2), it's basically the same logic than the high
speed timers found in the sun5i chips.

Now that we have a driver to support it, we can enable them in the
device tree.

Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 5256ad9..9145c6d 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -312,6 +312,17 @@
status = "disabled";
};

+ hstimer@01c60000 {
+ compatible = "allwinner,sun7i-a20-hstimer";
+ reg = <0x01c60000 0x1000>;
+ interrupts = <0 51 4>,
+ <0 52 4>,
+ <0 53 4>,
+ <0 54 4>;
+ clocks = <&ahb1_gates 19>;
+ resets = <&ahb1_rst 19>;
+ };
+
gic: interrupt-controller@01c81000 {
compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
reg = <0x01c81000 0x1000>,
--
1.8.4.2

Maxime Ripard

unread,
Dec 20, 2013, 4:41:06 PM12/20/13
to p.z...@pengutronix.de, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Maxime Ripard
Hi everyone,

This patchset enables support for the High Speed Timer IP found in the
Allwinner A31 SoCs.

These timers are asserted in reset, and are not associated with any struct
device, so we also add a small helper to the reset framework along the way to
be able to retrieve the reset controller from the device tree directly.

Thanks,
Maxime

Maxime Ripard (3):
reset: Add of_reset_control_get
clocksource: sun5i: Add support for reset controller
ARM: sun6i: a31: Add support for the High Speed Timers

.../bindings/timer/allwinner,sun5i-a13-hstimer.txt | 4 +++
arch/arm/boot/dts/sun6i-a31.dtsi | 11 ++++++
drivers/clocksource/timer-sun5i.c | 6 ++++
drivers/reset/core.c | 39 +++++++++++++++++-----
include/linux/reset.h | 4 +++
5 files changed, 55 insertions(+), 9 deletions(-)

--
1.8.4.2

Thomas Petazzoni

unread,
Dec 21, 2013, 3:42:13 AM12/21/13
to Maxime Ripard, p.z...@pengutronix.de, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Gregory Clément, Ezequiel Garcia
Maxime, Philipp,

On Fri, 20 Dec 2013 22:41:07 +0100, Maxime Ripard wrote:
> In some cases, you might need to deassert from reset an hardware block that
> doesn't associated to a struct device (CPUs, timers, etc.).
>
> Add a small helper to retrieve the reset controller from the device tree
> without the need to pass a struct device.
>
> Signed-off-by: Maxime Ripard <maxime...@free-electrons.com>
> ---
> drivers/reset/core.c | 39 ++++++++++++++++++++++++++++++---------
> include/linux/reset.h | 4 ++++
> 2 files changed, 34 insertions(+), 9 deletions(-)

I'd like to add that I have the exact same need as Maxime. Maxime needs
of_reset_control_get() for timers, and in my case, I need it for CPUs,
since I associated a reset controller to CPU nodes in my DT.

Funnily, even though Maxime and I work like 3 meters away from each
other, both of us came up independently with almost exactly the same
implementation to solve the exact same problem, without talking to each
other about this need. It's only yesterday that we discovered we've had
to solve the same problem.

So, definitely looking forward to seeing the feedback about this.

Thanks!

Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

Philipp Zabel

unread,
Jan 6, 2014, 12:42:51 PM1/6/14
to Thomas Petazzoni, Maxime Ripard, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Gregory Clément, Ezequiel Garcia
This looks like a useful addition. I'll reorder the GPIO reset patch for
this.

regards
Philipp

Maxime Ripard

unread,
Jan 8, 2014, 5:38:43 AM1/8/14
to Philipp Zabel, Thomas Petazzoni, linux-ar...@lists.infradead.org, Thomas Petazzoni, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Gregory Clément, Ezequiel Garcia
Hi Philipp,
How do you want to get this merged? You'll probably want to take this
patch, and patches 2/3 and 3/3 depend on some patches merged by Daniel
Lezcano (that I forgot to CC on this, I'll resend).

Maybe the best way would be simply to merge this one for 3.14 through
your branch, and merge the two other patches in 3.15.

Maxime

--
Maxime Ripard, Free Electrons
signature.asc

Philipp Zabel

unread,
Jan 8, 2014, 6:11:34 AM1/8/14
to Maxime Ripard, Thomas Petazzoni, linux-ar...@lists.infradead.org, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Gregory Clément, Ezequiel Garcia
Alright, this is applied to my branch. I'll wait a bit for feedback on
the GPIO reset patches and then send a pull request.

regards
Philipp

Maxime Ripard

unread,
Jan 8, 2014, 6:54:10 AM1/8/14
to Philipp Zabel, Thomas Petazzoni, linux-ar...@lists.infradead.org, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Gregory Clément, Ezequiel Garcia
Great then, thanks!
signature.asc

Maxime Ripard

unread,
Feb 5, 2014, 5:50:29 AM2/5/14
to Philipp Zabel, Thomas Petazzoni, linux-ar...@lists.infradead.org, linux...@googlegroups.com, kevin....@gmail.com, su...@allwinnertech.com, sh...@allwinnertech.com, zhuzh...@allwinnertech.com, Gregory Clément, Ezequiel Garcia
Hi Philipp,

On Wed, Jan 08, 2014 at 12:11:34PM +0100, Philipp Zabel wrote:
> > How do you want to get this merged? You'll probably want to take this
> > patch, and patches 2/3 and 3/3 depend on some patches merged by Daniel
> > Lezcano (that I forgot to CC on this, I'll resend).
> >
> > Maybe the best way would be simply to merge this one for 3.14 through
> > your branch, and merge the two other patches in 3.15.
>
> Alright, this is applied to my branch. I'll wait a bit for feedback on
> the GPIO reset patches and then send a pull request.

It doesn't seem to be in 3.14. Did I miss something?

Thanks,
signature.asc
Reply all
Reply to author
Forward
0 new messages