All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tero Kristo <t-kristo@ti.com>
To: linux-omap@vger.kernel.org, tony@atomide.com, s-anna@ti.com,
	paul@pwsan.com
Cc: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 01/17] ARM: OMAP2+: PRM: add support for reset controller
Date: Thu, 24 Sep 2015 17:26:42 +0300	[thread overview]
Message-ID: <1443104818-993-2-git-send-email-t-kristo@ti.com> (raw)
In-Reply-To: <1443104818-993-1-git-send-email-t-kristo@ti.com>

PRM driver now supports reset controller for the defined reset lines.
Reset configurations are provided through device tree. Later, functionality
like hwmod and system reboot will be changed to use the generic framework.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/Kconfig      |    1 +
 arch/arm/mach-omap2/prm_common.c |  167 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 07d2e10..ac3ef43 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -92,6 +92,7 @@ config ARCH_OMAP2PLUS
 	select SOC_BUS
 	select TI_PRIV_EDMA
 	select OMAP_IRQCHIP
+	select RESET_CONTROLLER
 	help
 	  Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
 
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 3fc2cbe..161d8ab 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -27,6 +27,8 @@
 #include <linux/of_address.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
 
 #include "soc.h"
 #include "prm2xxx_3xxx.h"
@@ -51,6 +53,11 @@
 #define OMAP_PRCM_MAX_NR_PENDING_REG		2
 
 /*
+ * Default partition for OMAP resets, maps to PRM
+ */
+#define OMAP_RESET_DEFAULT_PARTITION		1
+
+/*
  * prcm_irq_chips: an array of all of the "generic IRQ chips" in use
  * by the PRCM interrupt handler code.  There will be one 'chip' per
  * PRM_{IRQSTATUS,IRQENABLE}_MPU register pair.  (So OMAP3 will have
@@ -737,6 +744,162 @@ static const struct of_device_id const omap_prcm_dt_match_table[] __initconst =
 	{ }
 };
 
+struct ti_reset_data {
+	s16 module;
+	u16 offset;
+	u16 st_offset;
+	u8 shift;
+	u8 st_shift;
+	u8 part;
+};
+
+struct ti_reset_ctrl {
+	struct reset_controller_dev rcdev;
+	struct ti_reset_data **resets;
+	int num_resets;
+	int max_resets;
+	s16 offset;
+};
+
+#define to_ti_reset_ctrl(_rcdev) container_of(_rcdev, struct ti_reset_ctrl, \
+					      rcdev)
+
+static struct ti_reset_data *_get_reset(struct reset_controller_dev *rcdev,
+					unsigned long id)
+{
+	struct ti_reset_ctrl *ctrl = to_ti_reset_ctrl(rcdev);
+
+	return ctrl->resets[id];
+}
+
+static int ti_reset_assert(struct reset_controller_dev *rcdev,
+			   unsigned long id)
+{
+	struct ti_reset_data *reset = _get_reset(rcdev, id);
+
+	return omap_prm_assert_hardreset(reset->shift, reset->part,
+					 reset->module, reset->offset);
+}
+
+static int ti_reset_deassert(struct reset_controller_dev *rcdev,
+			     unsigned long id)
+{
+	struct ti_reset_data *reset = _get_reset(rcdev, id);
+
+	return omap_prm_deassert_hardreset(reset->shift, reset->st_shift,
+					   reset->part, reset->module,
+					   reset->offset, reset->st_offset);
+}
+
+static int ti_reset_status(struct reset_controller_dev *rcdev,
+			   unsigned long id)
+{
+	struct ti_reset_data *reset = _get_reset(rcdev, id);
+
+	return omap_prm_is_hardreset_asserted(reset->shift, reset->part,
+					      reset->module, reset->offset);
+}
+
+static struct reset_control_ops ti_reset_ops = {
+	.assert = ti_reset_assert,
+	.deassert = ti_reset_deassert,
+	.status = ti_reset_status,
+};
+
+static int ti_reset_xlate(struct reset_controller_dev *rcdev,
+			  const struct of_phandle_args *reset_spec)
+{
+	struct ti_reset_ctrl *ctrl = to_ti_reset_ctrl(rcdev);
+	s16 module;
+	u16 offset, st_offset;
+	u8 shift, st_shift;
+	int index = 0;
+	struct ti_reset_data *reset;
+
+	if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+		return -EINVAL;
+
+	module = reset_spec->args[0] - ctrl->offset;
+	offset = reset_spec->args[1];
+	shift = reset_spec->args[2];
+	st_offset = reset_spec->args[3];
+	st_shift = reset_spec->args[4];
+
+	for (index = 0; index < ctrl->num_resets; index++) {
+		reset = ctrl->resets[index];
+
+		if (module == reset->module && offset == reset->offset &&
+		    st_offset == reset->st_offset && shift == reset->shift &&
+		    st_shift == reset->st_shift)
+			return index;
+	}
+
+	reset = kzalloc(sizeof(*reset), GFP_KERNEL);
+
+	reset->module = module;
+	reset->offset = offset;
+	reset->st_offset = st_offset;
+	reset->shift = shift;
+	reset->st_shift = st_shift;
+	reset->part = OMAP_RESET_DEFAULT_PARTITION;
+
+	if (ctrl->num_resets + 1 > ctrl->max_resets) {
+		struct ti_reset_data **arr;
+		int num;
+
+		num = ctrl->num_resets;
+		num *= 2;
+		if (!num)
+			num = 1;
+
+		arr = kcalloc(num, sizeof(*arr), GFP_KERNEL);
+		ctrl->max_resets = num;
+		if (ctrl->num_resets)
+			memcpy(arr, ctrl->resets,
+			       sizeof(*arr) * ctrl->num_resets);
+
+		kfree(ctrl->resets);
+		ctrl->resets = arr;
+	}
+
+	ctrl->resets[index] = reset;
+	ctrl->num_resets++;
+
+	return index;
+}
+
+/**
+ * omap2_prm_reset_controller_register - register reset controller for a node
+ * @node: device node to register reset controller for
+ * @data: PRM init data for the node
+ *
+ * Registers a reset controller for the PRM node if applicable. Return 0
+ * in success, negative error value in failure.
+ */
+int __init
+omap2_prm_reset_controller_register(struct device_node *np,
+				    const struct omap_prcm_init_data *data)
+{
+	struct ti_reset_ctrl *ctrl;
+
+	/* Reset controllers available only for PRM nodes */
+	if (data->index != TI_CLKM_PRM)
+		return 0;
+
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+
+	ctrl->rcdev.of_node = np;
+	ctrl->rcdev.of_reset_n_cells = 5;
+	ctrl->rcdev.ops = &ti_reset_ops;
+	ctrl->rcdev.of_xlate = &ti_reset_xlate;
+
+	ctrl->offset = data->offset;
+
+	reset_controller_register(&ctrl->rcdev);
+
+	return 0;
+}
+
 /**
  * omap2_prm_base_init - initialize iomappings for the PRM driver
  *
@@ -802,6 +965,10 @@ int __init omap_prcm_init(void)
 		ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
 		if (ret)
 			return ret;
+
+		ret = omap2_prm_reset_controller_register(np, data);
+		if (ret)
+			return ret;
 	}
 
 	omap_cm_init();
-- 
1.7.9.5

WARNING: multiple messages have this Message-ID (diff)
From: t-kristo@ti.com (Tero Kristo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 01/17] ARM: OMAP2+: PRM: add support for reset controller
Date: Thu, 24 Sep 2015 17:26:42 +0300	[thread overview]
Message-ID: <1443104818-993-2-git-send-email-t-kristo@ti.com> (raw)
In-Reply-To: <1443104818-993-1-git-send-email-t-kristo@ti.com>

PRM driver now supports reset controller for the defined reset lines.
Reset configurations are provided through device tree. Later, functionality
like hwmod and system reboot will be changed to use the generic framework.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/Kconfig      |    1 +
 arch/arm/mach-omap2/prm_common.c |  167 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 07d2e10..ac3ef43 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -92,6 +92,7 @@ config ARCH_OMAP2PLUS
 	select SOC_BUS
 	select TI_PRIV_EDMA
 	select OMAP_IRQCHIP
+	select RESET_CONTROLLER
 	help
 	  Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
 
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 3fc2cbe..161d8ab 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -27,6 +27,8 @@
 #include <linux/of_address.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/ti.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
 
 #include "soc.h"
 #include "prm2xxx_3xxx.h"
@@ -51,6 +53,11 @@
 #define OMAP_PRCM_MAX_NR_PENDING_REG		2
 
 /*
+ * Default partition for OMAP resets, maps to PRM
+ */
+#define OMAP_RESET_DEFAULT_PARTITION		1
+
+/*
  * prcm_irq_chips: an array of all of the "generic IRQ chips" in use
  * by the PRCM interrupt handler code.  There will be one 'chip' per
  * PRM_{IRQSTATUS,IRQENABLE}_MPU register pair.  (So OMAP3 will have
@@ -737,6 +744,162 @@ static const struct of_device_id const omap_prcm_dt_match_table[] __initconst =
 	{ }
 };
 
+struct ti_reset_data {
+	s16 module;
+	u16 offset;
+	u16 st_offset;
+	u8 shift;
+	u8 st_shift;
+	u8 part;
+};
+
+struct ti_reset_ctrl {
+	struct reset_controller_dev rcdev;
+	struct ti_reset_data **resets;
+	int num_resets;
+	int max_resets;
+	s16 offset;
+};
+
+#define to_ti_reset_ctrl(_rcdev) container_of(_rcdev, struct ti_reset_ctrl, \
+					      rcdev)
+
+static struct ti_reset_data *_get_reset(struct reset_controller_dev *rcdev,
+					unsigned long id)
+{
+	struct ti_reset_ctrl *ctrl = to_ti_reset_ctrl(rcdev);
+
+	return ctrl->resets[id];
+}
+
+static int ti_reset_assert(struct reset_controller_dev *rcdev,
+			   unsigned long id)
+{
+	struct ti_reset_data *reset = _get_reset(rcdev, id);
+
+	return omap_prm_assert_hardreset(reset->shift, reset->part,
+					 reset->module, reset->offset);
+}
+
+static int ti_reset_deassert(struct reset_controller_dev *rcdev,
+			     unsigned long id)
+{
+	struct ti_reset_data *reset = _get_reset(rcdev, id);
+
+	return omap_prm_deassert_hardreset(reset->shift, reset->st_shift,
+					   reset->part, reset->module,
+					   reset->offset, reset->st_offset);
+}
+
+static int ti_reset_status(struct reset_controller_dev *rcdev,
+			   unsigned long id)
+{
+	struct ti_reset_data *reset = _get_reset(rcdev, id);
+
+	return omap_prm_is_hardreset_asserted(reset->shift, reset->part,
+					      reset->module, reset->offset);
+}
+
+static struct reset_control_ops ti_reset_ops = {
+	.assert = ti_reset_assert,
+	.deassert = ti_reset_deassert,
+	.status = ti_reset_status,
+};
+
+static int ti_reset_xlate(struct reset_controller_dev *rcdev,
+			  const struct of_phandle_args *reset_spec)
+{
+	struct ti_reset_ctrl *ctrl = to_ti_reset_ctrl(rcdev);
+	s16 module;
+	u16 offset, st_offset;
+	u8 shift, st_shift;
+	int index = 0;
+	struct ti_reset_data *reset;
+
+	if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+		return -EINVAL;
+
+	module = reset_spec->args[0] - ctrl->offset;
+	offset = reset_spec->args[1];
+	shift = reset_spec->args[2];
+	st_offset = reset_spec->args[3];
+	st_shift = reset_spec->args[4];
+
+	for (index = 0; index < ctrl->num_resets; index++) {
+		reset = ctrl->resets[index];
+
+		if (module == reset->module && offset == reset->offset &&
+		    st_offset == reset->st_offset && shift == reset->shift &&
+		    st_shift == reset->st_shift)
+			return index;
+	}
+
+	reset = kzalloc(sizeof(*reset), GFP_KERNEL);
+
+	reset->module = module;
+	reset->offset = offset;
+	reset->st_offset = st_offset;
+	reset->shift = shift;
+	reset->st_shift = st_shift;
+	reset->part = OMAP_RESET_DEFAULT_PARTITION;
+
+	if (ctrl->num_resets + 1 > ctrl->max_resets) {
+		struct ti_reset_data **arr;
+		int num;
+
+		num = ctrl->num_resets;
+		num *= 2;
+		if (!num)
+			num = 1;
+
+		arr = kcalloc(num, sizeof(*arr), GFP_KERNEL);
+		ctrl->max_resets = num;
+		if (ctrl->num_resets)
+			memcpy(arr, ctrl->resets,
+			       sizeof(*arr) * ctrl->num_resets);
+
+		kfree(ctrl->resets);
+		ctrl->resets = arr;
+	}
+
+	ctrl->resets[index] = reset;
+	ctrl->num_resets++;
+
+	return index;
+}
+
+/**
+ * omap2_prm_reset_controller_register - register reset controller for a node
+ * @node: device node to register reset controller for
+ * @data: PRM init data for the node
+ *
+ * Registers a reset controller for the PRM node if applicable. Return 0
+ * in success, negative error value in failure.
+ */
+int __init
+omap2_prm_reset_controller_register(struct device_node *np,
+				    const struct omap_prcm_init_data *data)
+{
+	struct ti_reset_ctrl *ctrl;
+
+	/* Reset controllers available only for PRM nodes */
+	if (data->index != TI_CLKM_PRM)
+		return 0;
+
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+
+	ctrl->rcdev.of_node = np;
+	ctrl->rcdev.of_reset_n_cells = 5;
+	ctrl->rcdev.ops = &ti_reset_ops;
+	ctrl->rcdev.of_xlate = &ti_reset_xlate;
+
+	ctrl->offset = data->offset;
+
+	reset_controller_register(&ctrl->rcdev);
+
+	return 0;
+}
+
 /**
  * omap2_prm_base_init - initialize iomappings for the PRM driver
  *
@@ -802,6 +965,10 @@ int __init omap_prcm_init(void)
 		ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
 		if (ret)
 			return ret;
+
+		ret = omap2_prm_reset_controller_register(np, data);
+		if (ret)
+			return ret;
 	}
 
 	omap_cm_init();
-- 
1.7.9.5

  reply	other threads:[~2015-09-24 14:26 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-24 14:26 [PATCH 00/17] ARM: OMAP2+: reset controller support Tero Kristo
2015-09-24 14:26 ` Tero Kristo
2015-09-24 14:26 ` Tero Kristo [this message]
2015-09-24 14:26   ` [PATCH 01/17] ARM: OMAP2+: PRM: add support for reset controller Tero Kristo
2015-10-06 12:06   ` Tony Lindgren
2015-10-06 12:06     ` Tony Lindgren
2015-11-30 17:09     ` Tony Lindgren
2015-11-30 17:09       ` Tony Lindgren
2015-09-24 14:26 ` [PATCH 02/17] ARM: OMAP2+: hwmod: parse also soc hierarchy for hwmod compatible nodes Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 03/17] ARM: dts: omap3: add reset data Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 04/17] ARM: dts: omap4: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 05/17] ARM: dts: omap5: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 06/17] ARM: dts: dra7: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 07/17] ARM: dts: am4372: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-25 12:57   ` Lokesh Vutla
2015-09-25 12:57     ` Lokesh Vutla
2015-09-28  8:11     ` Tero Kristo
2015-09-28  8:11       ` Tero Kristo
2015-09-24 14:26 ` [PATCH 08/17] ARM: dts: am33xx: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 09/17] ARM: dts: OMAP24xx: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 10/17] ARM: OMAP2+: hwmod: parse reset information from DT Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 11/17] ARM: OMAP2+: use system reset info from device tree data Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 12/17] ARM: OMAP4: hwmod_data: remove reset data Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 13/17] ARM: OMAP5: " Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 14/17] ARM: OMAP2: hwmod: AMx3xx: remove redundant reset info Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 15/17] ARM: OMAP24xx: hwmod: remove reset data from hwmod database Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 16/17] ARM: OMAP2+: hwmod: remove obsolete support for some hardreset logic Tero Kristo
2015-09-24 14:26   ` Tero Kristo
2015-09-24 14:26 ` [PATCH 17/17] ARM: OMAP2+: PRM: remove redundant system reset code Tero Kristo
2015-09-24 14:26   ` Tero Kristo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1443104818-993-2-git-send-email-t-kristo@ti.com \
    --to=t-kristo@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=paul@pwsan.com \
    --cc=s-anna@ti.com \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.