All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers
@ 2013-10-25 13:22 Maxime Ripard
  2013-10-25 13:22 ` [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver Maxime Ripard
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Maxime Ripard @ 2013-10-25 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi everyone,

This patchset adds support for the reset controllers found in the Allwinner A31
SoCs. Since these controllers are pretty simple, basically just a few MMIO
registers, with a single bit controlling the reset state of the other devices
it asserts in reset, the driver is quite simple as well.

However, one of the IPs asserted in reset by these controllers are the timers,
the only thing standing out is that it requires to be registered before the
timers are initialized.

Thanks,
Maxime

Changes from v2:
  - Changed the commit logs to be a bit more generic
  - Fixed a stupid breakage in the Makefile

Changes from v1:
  - Don't call request_mem_region, since some of these controllers will share
    registers with clock drivers
  - Switched to a more generic allwinner,sun4i-clock-reset compatible, since a
    lot of these controllers are found in other SoCs than the A31
  - Switched to a "real" driver using the device model for all these reset
    controllers but the one that needs to be initialised early.
  - Fixed a typo in one of the DT bindings that was leading to a compilation
    breakage

Maxime Ripard (4):
  reset: Add Allwinner SoCs Reset Controller Driver
  ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER
  ARM: sunxi: Register the A31 reset IP in init_time
  ARM: sun6i: Add the reset controller to the DTSI

 arch/arm/boot/dts/sun6i-a31.dtsi |  24 ++++++
 arch/arm/mach-sunxi/Kconfig      |   1 +
 arch/arm/mach-sunxi/sunxi.c      |  10 ++-
 drivers/reset/Makefile           |   1 +
 drivers/reset/reset-sunxi.c      | 156 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 191 insertions(+), 1 deletion(-)
 create mode 100644 drivers/reset/reset-sunxi.c

-- 
1.8.4

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver
  2013-10-25 13:22 [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
@ 2013-10-25 13:22 ` Maxime Ripard
  2013-11-11 10:18   ` Philipp Zabel
  2013-10-25 13:22 ` [PATCH v3 2/4] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER Maxime Ripard
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Maxime Ripard @ 2013-10-25 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

The Allwinner A31 and most of the other Allwinner SoCs have an IP
maintaining a few other IPs in the SoC in reset by default. Among these
IPs are the A31's High Speed Timers, hence why we can't use the regular
driver construct in every cases, and need to call the registering
function directly during machine initialisation.

Apart from this, the implementation is fairly straightforward, and could
easily be moved to a generic MMIO-based reset controller driver if the
need ever arise.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/reset/Makefile      |   1 +
 drivers/reset/reset-sunxi.c | 156 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 157 insertions(+)
 create mode 100644 drivers/reset/reset-sunxi.c

diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 1e2d83f..cc29832 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
new file mode 100644
index 0000000..5bbd59a
--- /dev/null
+++ b/drivers/reset/reset-sunxi.c
@@ -0,0 +1,156 @@
+/*
+ * Allwinner SoCs Reset Controller driver
+ *
+ * Copyright 2013 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.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/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+struct sunxi_reset_data {
+	void __iomem				*membase;
+	struct reset_controller_dev		rcdev;
+};
+
+static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct sunxi_reset_data *data = container_of(rcdev,
+						     struct sunxi_reset_data,
+						     rcdev);
+	int bank = id / BITS_PER_LONG;
+	int offset = id % BITS_PER_LONG;
+	u32 reg = readl(data->membase + (bank * 4));
+
+	writel(reg & ~BIT(offset), data->membase + (bank * 4));
+
+	return 0;
+}
+
+static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct sunxi_reset_data *data = container_of(rcdev,
+						     struct sunxi_reset_data,
+						     rcdev);
+	int bank = id / BITS_PER_LONG;
+	int offset = id % BITS_PER_LONG;
+	u32 reg = readl(data->membase + (bank * 4));
+
+	writel(reg | BIT(offset), data->membase + (bank * 4));
+
+	return 0;
+}
+
+static struct reset_control_ops sunxi_reset_ops = {
+	.assert		= sunxi_reset_assert,
+	.deassert	= sunxi_reset_deassert,
+};
+
+static int sunxi_reset_init(struct device_node *np)
+{
+	struct sunxi_reset_data *data;
+	struct resource res;
+	resource_size_t size;
+	int ret;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		goto err_alloc;
+
+	size = resource_size(&res);
+	data->membase = ioremap(res.start, size);
+	if (!data->membase) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = size * 32;
+	data->rcdev.ops = &sunxi_reset_ops;
+	data->rcdev.of_node = np;
+	reset_controller_register(&data->rcdev);
+
+	return 0;
+
+err_alloc:
+	kfree(data);
+	return ret;
+};
+
+/*
+ * These are the reset controller we need to initialize early on in
+ * our system, before we can even think of using a regular device
+ * driver for it.
+ */
+static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = {
+	{ .compatible = "allwinner,sun6i-a31-ahb1-reset", },
+	{ /* sentinel */ },
+};
+
+void __init sun6i_reset_init(void)
+{
+	struct device_node *np;
+
+	for_each_matching_node(np, sunxi_early_reset_dt_ids)
+		sunxi_reset_init(np);
+}
+
+/*
+ * And these are the controllers we can register through the regular
+ * device model.
+ */
+static const struct of_device_id sunxi_reset_dt_ids[] = {
+	 { .compatible = "allwinner,sun4i-clock-reset", },
+	 { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, sunxi_reset_dt_ids);
+
+static int sunxi_reset_probe(struct platform_device *pdev)
+{
+	return sunxi_reset_init(pdev->dev.of_node);
+}
+
+static int sunxi_reset_remove(struct platform_device *pdev)
+{
+	struct sunxi_reset_data *data = platform_get_drvdata(pdev);
+
+	reset_controller_unregister(&data->rcdev);
+	iounmap(data->membase);
+	kfree(data);
+
+	return 0;
+}
+
+static struct platform_driver sunxi_reset_driver = {
+	.probe	= sunxi_reset_probe,
+	.remove	= sunxi_reset_remove,
+	.driver = {
+		.name		= "sunxi-reset",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sunxi_reset_dt_ids,
+	},
+};
+module_platform_driver(sunxi_reset_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner SoCs Reset Controller Driver");
+MODULE_LICENSE("GPL");
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/4] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER
  2013-10-25 13:22 [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
  2013-10-25 13:22 ` [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver Maxime Ripard
@ 2013-10-25 13:22 ` Maxime Ripard
  2013-10-25 13:22 ` [PATCH v3 3/4] ARM: sunxi: Register the A31 reset IP in init_time Maxime Ripard
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Maxime Ripard @ 2013-10-25 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

The A31 has a reset controller, and we have to select this option to
have access to the reset controller framework.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/mach-sunxi/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index bce0d42..547004c 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1,5 +1,6 @@
 config ARCH_SUNXI
 	bool "Allwinner A1X SOCs" if ARCH_MULTI_V7
+	select ARCH_HAS_RESET_CONTROLLER
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_GIC
 	select CLKSRC_MMIO
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 3/4] ARM: sunxi: Register the A31 reset IP in init_time
  2013-10-25 13:22 [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
  2013-10-25 13:22 ` [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver Maxime Ripard
  2013-10-25 13:22 ` [PATCH v3 2/4] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER Maxime Ripard
@ 2013-10-25 13:22 ` Maxime Ripard
  2013-10-25 13:22 ` [PATCH v3 4/4] ARM: sun6i: Add the reset controller to the DTSI Maxime Ripard
  2013-11-10 10:58 ` [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
  4 siblings, 0 replies; 8+ messages in thread
From: Maxime Ripard @ 2013-10-25 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

The A31 has a reset IP that maintains a few other IPs in reset by
default. Among these IPs are the UARTs, and most notably the timers. We
thus need to register the reset driver before initializing the timers so
that the reset timer can use the reset framework.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/mach-sunxi/sunxi.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index f184f6c..2e79736 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -142,9 +142,17 @@ static const char * const sun6i_board_dt_compat[] = {
 	NULL,
 };
 
+extern void __init sun6i_reset_init(void);
+static void __init sun6i_timer_init(void)
+{
+	sunxi_init_clocks();
+	sun6i_reset_init();
+	clocksource_of_init();
+}
+
 DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family")
 	.init_machine	= sunxi_dt_init,
-	.init_time	= sunxi_timer_init,
+	.init_time	= sun6i_timer_init,
 	.dt_compat	= sun6i_board_dt_compat,
 	.restart	= sun6i_restart,
 MACHINE_END
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 4/4] ARM: sun6i: Add the reset controller to the DTSI
  2013-10-25 13:22 [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
                   ` (2 preceding siblings ...)
  2013-10-25 13:22 ` [PATCH v3 3/4] ARM: sunxi: Register the A31 reset IP in init_time Maxime Ripard
@ 2013-10-25 13:22 ` Maxime Ripard
  2013-11-10 10:58 ` [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
  4 siblings, 0 replies; 8+ messages in thread
From: Maxime Ripard @ 2013-10-25 13:22 UTC (permalink / raw)
  To: linux-arm-kernel

The A31 has a reset controller IP that maintains a few other IPs in
reset, among which we can find the UARTs, high speed timers or the I2C.
Now that we have support for them, add the reset controllers to the DTSI.

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

diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index c1751a6..c7e0658 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -209,6 +209,24 @@
 			};
 		};
 
+		ahb1_rst: reset at 01c202c0 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun6i-a31-ahb1-reset";
+			reg = <0x01c202c0 0xc>;
+		};
+
+		apb1_rst: reset at 01c202d0 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-clock-reset";
+			reg = <0x01c202d0 0x4>;
+		};
+
+		apb2_rst: reset at 01c202d8 {
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-clock-reset";
+			reg = <0x01c202d8 0x4>;
+		};
+
 		timer at 01c20c00 {
 			compatible = "allwinner,sun4i-timer";
 			reg = <0x01c20c00 0xa0>;
@@ -232,6 +250,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			clocks = <&apb2_gates 16>;
+			resets = <&apb2_rst 16>;
 			status = "disabled";
 		};
 
@@ -242,6 +261,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			clocks = <&apb2_gates 17>;
+			resets = <&apb2_rst 17>;
 			status = "disabled";
 		};
 
@@ -252,6 +272,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			clocks = <&apb2_gates 18>;
+			resets = <&apb2_rst 18>;
 			status = "disabled";
 		};
 
@@ -262,6 +283,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			clocks = <&apb2_gates 19>;
+			resets = <&apb2_rst 19>;
 			status = "disabled";
 		};
 
@@ -272,6 +294,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			clocks = <&apb2_gates 20>;
+			resets = <&apb2_rst 20>;
 			status = "disabled";
 		};
 
@@ -282,6 +305,7 @@
 			reg-shift = <2>;
 			reg-io-width = <4>;
 			clocks = <&apb2_gates 21>;
+			resets = <&apb2_rst 21>;
 			status = "disabled";
 		};
 
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers
  2013-10-25 13:22 [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
                   ` (3 preceding siblings ...)
  2013-10-25 13:22 ` [PATCH v3 4/4] ARM: sun6i: Add the reset controller to the DTSI Maxime Ripard
@ 2013-11-10 10:58 ` Maxime Ripard
  4 siblings, 0 replies; 8+ messages in thread
From: Maxime Ripard @ 2013-11-10 10:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Philipp,

On Fri, Oct 25, 2013 at 02:22:41PM +0100, Maxime Ripard wrote:
> Hi everyone,
> 
> This patchset adds support for the reset controllers found in the Allwinner A31
> SoCs. Since these controllers are pretty simple, basically just a few MMIO
> registers, with a single bit controlling the reset state of the other devices
> it asserts in reset, the driver is quite simple as well.
> 
> However, one of the IPs asserted in reset by these controllers are the timers,
> the only thing standing out is that it requires to be registered before the
> timers are initialized.

I'll submit a v3 on this, because of a minor thing in the
compatible-related thing (on sun4i (Allwinner A10) the reset parts are
in the same registers as clock control ones, so we won't be able to
use this driver in that case, which makes the compatible a bit different).

Do you have any comment before I send the new version?

Thanks
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131110/8064eeae/attachment.sig>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver
  2013-10-25 13:22 ` [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver Maxime Ripard
@ 2013-11-11 10:18   ` Philipp Zabel
  2013-11-11 18:55     ` Maxime Ripard
  0 siblings, 1 reply; 8+ messages in thread
From: Philipp Zabel @ 2013-11-11 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Maxime,

Am Freitag, den 25.10.2013, 14:22 +0100 schrieb Maxime Ripard:
> The Allwinner A31 and most of the other Allwinner SoCs have an IP
> maintaining a few other IPs in the SoC in reset by default. Among these
> IPs are the A31's High Speed Timers, hence why we can't use the regular
> driver construct in every cases, and need to call the registering
> function directly during machine initialisation.
> 
> Apart from this, the implementation is fairly straightforward, and could
> easily be moved to a generic MMIO-based reset controller driver if the
> need ever arise.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/reset/Makefile      |   1 +
>  drivers/reset/reset-sunxi.c | 156 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 157 insertions(+)
>  create mode 100644 drivers/reset/reset-sunxi.c
> 
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 1e2d83f..cc29832 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -1 +1,2 @@
>  obj-$(CONFIG_RESET_CONTROLLER) += core.o
> +obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
> diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
> new file mode 100644
> index 0000000..5bbd59a
> --- /dev/null
> +++ b/drivers/reset/reset-sunxi.c
> @@ -0,0 +1,156 @@
> +/*
> + * Allwinner SoCs Reset Controller driver
> + *
> + * Copyright 2013 Maxime Ripard
> + *
> + * Maxime Ripard <maxime.ripard@free-electrons.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/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +
> +struct sunxi_reset_data {
> +	void __iomem				*membase;
> +	struct reset_controller_dev		rcdev;
> +};
> +
> +static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
> +			      unsigned long id)
> +{
> +	struct sunxi_reset_data *data = container_of(rcdev,
> +						     struct sunxi_reset_data,
> +						     rcdev);
> +	int bank = id / BITS_PER_LONG;
> +	int offset = id % BITS_PER_LONG;
> +	u32 reg = readl(data->membase + (bank * 4));
> +
> +	writel(reg & ~BIT(offset), data->membase + (bank * 4));

the reset core just passes through calls to reset_controller_assert
directly, ...

> +
> +	return 0;
> +}
> +
> +static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
> +				unsigned long id)
> +{
> +	struct sunxi_reset_data *data = container_of(rcdev,
> +						     struct sunxi_reset_data,
> +						     rcdev);
> +	int bank = id / BITS_PER_LONG;
> +	int offset = id % BITS_PER_LONG;
> +	u32 reg = readl(data->membase + (bank * 4));
> +
> +	writel(reg | BIT(offset), data->membase + (bank * 4));

... so those read-modify-write cycles in sunxi_reset_assert and here
should be protected with a lock.

> +	return 0;
> +}
> +
> +static struct reset_control_ops sunxi_reset_ops = {
> +	.assert		= sunxi_reset_assert,
> +	.deassert	= sunxi_reset_deassert,
> +};
> +
> +static int sunxi_reset_init(struct device_node *np)
> +{
> +	struct sunxi_reset_data *data;
> +	struct resource res;
> +	resource_size_t size;
> +	int ret;
> +
> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	ret = of_address_to_resource(np, 0, &res);
> +	if (ret)
> +		goto err_alloc;
> +
> +	size = resource_size(&res);
> +	data->membase = ioremap(res.start, size);
> +	if (!data->membase) {
> +		ret = -ENOMEM;
> +		goto err_alloc;
> +	}
> +
> +	data->rcdev.owner = THIS_MODULE;
> +	data->rcdev.nr_resets = size * 32;
> +	data->rcdev.ops = &sunxi_reset_ops;
> +	data->rcdev.of_node = np;
> +	reset_controller_register(&data->rcdev);
> +
> +	return 0;
> +
> +err_alloc:
> +	kfree(data);
> +	return ret;
> +};
> +
> +/*
> + * These are the reset controller we need to initialize early on in
> + * our system, before we can even think of using a regular device
> + * driver for it.
> + */
> +static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = {
> +	{ .compatible = "allwinner,sun6i-a31-ahb1-reset", },
> +	{ /* sentinel */ },
> +};
> +
> +void __init sun6i_reset_init(void)
> +{
> +	struct device_node *np;
> +
> +	for_each_matching_node(np, sunxi_early_reset_dt_ids)
> +		sunxi_reset_init(np);
> +}
> +
> +/*
> + * And these are the controllers we can register through the regular
> + * device model.
> + */
> +static const struct of_device_id sunxi_reset_dt_ids[] = {
> +	 { .compatible = "allwinner,sun4i-clock-reset", },
> +	 { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, sunxi_reset_dt_ids);
> +
> +static int sunxi_reset_probe(struct platform_device *pdev)
> +{
> +	return sunxi_reset_init(pdev->dev.of_node);
> +}
> +
> +static int sunxi_reset_remove(struct platform_device *pdev)
> +{
> +	struct sunxi_reset_data *data = platform_get_drvdata(pdev);
> +
> +	reset_controller_unregister(&data->rcdev);
> +	iounmap(data->membase);
> +	kfree(data);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver sunxi_reset_driver = {
> +	.probe	= sunxi_reset_probe,
> +	.remove	= sunxi_reset_remove,
> +	.driver = {
> +		.name		= "sunxi-reset",
> +		.owner		= THIS_MODULE,
> +		.of_match_table	= sunxi_reset_dt_ids,
> +	},
> +};
> +module_platform_driver(sunxi_reset_driver);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
> +MODULE_DESCRIPTION("Allwinner SoCs Reset Controller Driver");
> +MODULE_LICENSE("GPL");

regards
Philipp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver
  2013-11-11 10:18   ` Philipp Zabel
@ 2013-11-11 18:55     ` Maxime Ripard
  0 siblings, 0 replies; 8+ messages in thread
From: Maxime Ripard @ 2013-11-11 18:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Philipp,

On Mon, Nov 11, 2013 at 11:18:55AM +0100, Philipp Zabel wrote:
> > +static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
> > +			      unsigned long id)
> > +{
> > +	struct sunxi_reset_data *data = container_of(rcdev,
> > +						     struct sunxi_reset_data,
> > +						     rcdev);
> > +	int bank = id / BITS_PER_LONG;
> > +	int offset = id % BITS_PER_LONG;
> > +	u32 reg = readl(data->membase + (bank * 4));
> > +
> > +	writel(reg & ~BIT(offset), data->membase + (bank * 4));
> 
> the reset core just passes through calls to reset_controller_assert
> directly, ...
> 
> > +
> > +	return 0;
> > +}
> > +
> > +static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
> > +				unsigned long id)
> > +{
> > +	struct sunxi_reset_data *data = container_of(rcdev,
> > +						     struct sunxi_reset_data,
> > +						     rcdev);
> > +	int bank = id / BITS_PER_LONG;
> > +	int offset = id % BITS_PER_LONG;
> > +	u32 reg = readl(data->membase + (bank * 4));
> > +
> > +	writel(reg | BIT(offset), data->membase + (bank * 4));
> 
> ... so those read-modify-write cycles in sunxi_reset_assert and here
> should be protected with a lock.

Right, I'll fix this in the v3.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20131111/971e9f19/attachment.sig>

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-11-11 18:55 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-25 13:22 [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard
2013-10-25 13:22 ` [PATCH v3 1/4] reset: Add Allwinner SoCs Reset Controller Driver Maxime Ripard
2013-11-11 10:18   ` Philipp Zabel
2013-11-11 18:55     ` Maxime Ripard
2013-10-25 13:22 ` [PATCH v3 2/4] ARM: sunxi: Select ARCH_HAS_RESET_CONTROLLER Maxime Ripard
2013-10-25 13:22 ` [PATCH v3 3/4] ARM: sunxi: Register the A31 reset IP in init_time Maxime Ripard
2013-10-25 13:22 ` [PATCH v3 4/4] ARM: sun6i: Add the reset controller to the DTSI Maxime Ripard
2013-11-10 10:58 ` [PATCH v3 0/4] Add support for the Allwinner A31 Reset Controllers Maxime Ripard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.