From: heiko@sntech.de (Heiko Stübner)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/5] ARM: S3C24XX: add generic handler for swrst resets
Date: Mon, 06 Jan 2014 19:38:38 +0100 [thread overview]
Message-ID: <1569032.VYgrksRbsn@phil> (raw)
In-Reply-To: <3105326.uFdOVLyXH8@phil>
Previously the s3c24xx socs using the swrst machnism simply wrote
the needed value to a statically mapped register.
To generalize and make it usable in the dt case create a reset handler
similar to the already existing watchdog-reset used by different samsung
architectures.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
arch/arm/mach-s3c24xx/Kconfig | 5 ++
arch/arm/mach-s3c24xx/Makefile | 1 +
arch/arm/mach-s3c24xx/common.h | 16 ++++
arch/arm/mach-s3c24xx/swrst-reset.c | 160 +++++++++++++++++++++++++++++++++++
4 files changed, 182 insertions(+)
create mode 100644 arch/arm/mach-s3c24xx/swrst-reset.c
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index e19e314..bb0f653 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -30,6 +30,11 @@ config S3C2410_COMMON_DCLK
Temporary symbol to build the dclk driver based on the common clock
framework.
+config S3C24XX_SWRST
+ bool
+ help
+ Handle resets using the swrst register available on some s3c24xx SoCs.
+
menu "SAMSUNG S3C24XX SoCs Support"
comment "S3C24XX SoCs"
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
index 2235d0d..9cc1d58 100644
--- a/arch/arm/mach-s3c24xx/Makefile
+++ b/arch/arm/mach-s3c24xx/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_CPU_S3C2443) += s3c2443.o
# PM
obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o
+obj-$(CONFIG_S3C24XX_SWRST) += swrst-reset.o
# common code
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
index 0f548c5..caf1534 100644
--- a/arch/arm/mach-s3c24xx/common.h
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -131,4 +131,20 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
void __iomem *reg_base);
#endif
+#ifdef CONFIG_S3C24XX_SWRST
+void s3c24xx_swrst_reset(void);
+bool s3c24xx_swrst_reset_available(void);
+void s3c24xx_swrst_reset_of_init(void);
+void s3c24xx_swrst_reset_init(void __iomem *base, bool is_s3c2412);
+#else
+static inline void s3c24xx_swrst_reset(void) {}
+static inline bool s3c24xx_swrst_reset_available(void)
+{
+ return false;
+}
+static inline void s3c24xx_swrst_reset_of_init(void) {}
+static inline void s3c24xx_swrst_reset_init(void __iomem *base,
+ bool is_s3c2412) {}
+#endif
+
#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
diff --git a/arch/arm/mach-s3c24xx/swrst-reset.c b/arch/arm/mach-s3c24xx/swrst-reset.c
new file mode 100644
index 0000000..d027c4a
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/swrst-reset.c
@@ -0,0 +1,160 @@
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+/*
+ * Although the manuals state that the string to write to the register
+ * is soc-specific, at least the s3c2416 and s3c2450 do not seem to care
+ * what gets written to the register and have been using the s3c2443
+ * string all along.
+ */
+#define S3C2412_SWRST_RESET (0x533C2412)
+#define S3C2443_SWRST_RESET (0x533C2443)
+
+enum s3c_cpu_type {
+ TYPE_S3C2412,
+ TYPE_S3C2443,
+};
+
+struct s3c24xx_swrst_drv_data {
+ int cpu_type;
+};
+
+struct s3c2412_rst_clocks {
+ const char *clk;
+ const char *new_parent;
+};
+
+/* S3C2412 errata "Watch-dog/Software Reset Problem" specifies
+ * that this reset must be done with the SYSCLK sourced from
+ * EXTCLK instead of FOUT to avoid a glitch in the reset
+ * mechanism.
+ *
+ * See the watchdog section of the S3C2412 manual for more
+ * information on this fix.
+ *
+ * The proposed fix is to write "0" to the clksrc register,
+ * to reset the sysclk "which generates the ARMCLK, HCLK, PCLK".
+ * Translated to the clock implementation, this looks like:
+ */
+struct s3c2412_rst_clocks s3c2412_clocks[] = {
+ { "mdivclk", "xti" },
+ { "msysclk", "mdivclk" },
+};
+
+static void __iomem *swrst_base;
+static int swrst_type;
+
+void s3c24xx_swrst_reset(void)
+{
+ int i;
+ bool has_faults = true;
+
+ if (!swrst_base) {
+ pr_err("%s: swrst reset not initialized\n", __func__);
+ /* delay to allow the serial port to show the message */
+ mdelay(50);
+ return;
+ }
+
+ switch (swrst_type) {
+ case TYPE_S3C2412:
+ /* handle the needed clock changes */
+ for (i = 0; i < ARRAY_SIZE(s3c2412_clocks); i++) {
+ struct s3c2412_rst_clocks *entry = &s3c2412_clocks[i];
+ struct clk *clk, *new_parent;
+ int ret;
+
+ clk = clk_get(NULL, entry->clk);
+ if (IS_ERR(clk)) {
+ pr_err("s3c24xx-swrst: could not get clock %s, err %ld\n",
+ entry->clk, PTR_ERR(clk));
+ has_faults = true;
+ continue;
+ }
+
+ new_parent = clk_get(NULL, entry->new_parent);
+ if (IS_ERR(new_parent)) {
+ pr_err("s3c24xx-swrst: could not get clock %s, err %ld\n",
+ entry->new_parent, PTR_ERR(new_parent));
+ has_faults = true;
+ clk_put(clk);
+ continue;
+ }
+
+ ret = clk_set_parent(clk, new_parent);
+ if (ret) {
+ pr_err("s3c24xx-swrst: could not set the parent clock of %s to %s, err %d\n",
+ entry->clk, entry->new_parent, ret);
+ has_faults = true;
+ }
+
+ clk_put(new_parent);
+ clk_put(clk);
+ }
+
+ if (has_faults) {
+ pr_warn("s3c24xx-swrst: some clocks could not be set to the needed parent.\n");
+ pr_warn("s3c24xx-swrst: this can trigger a glitch in the s3c2412 soc\n");
+ }
+
+ writel(S3C2412_SWRST_RESET, swrst_base);
+ break;
+ case TYPE_S3C2443:
+ writel(S3C2443_SWRST_RESET, swrst_base);
+ break;
+ }
+}
+
+bool s3c24xx_swrst_reset_available(void)
+{
+ return !!swrst_base;
+}
+
+#ifdef CONFIG_OF
+static struct s3c24xx_swrst_drv_data s3c24xx_swrst_drv_data_array[] = {
+ [TYPE_S3C2412] = { TYPE_S3C2412 },
+ [TYPE_S3C2443] = { TYPE_S3C2443 },
+};
+
+static const struct of_device_id s3c24xx_swrst_match[] = {
+ {
+ .compatible = "samsung,s3c2412-swrst",
+ .data = &s3c24xx_swrst_drv_data_array[TYPE_S3C2412],
+ }, {
+ .compatible = "samsung,s3c2443-swrst",
+ .data = &s3c24xx_swrst_drv_data_array[TYPE_S3C2443],
+ },
+ {},
+};
+
+void __init s3c24xx_swrst_reset_of_init(void)
+{
+ struct device_node *np;
+ const struct of_device_id *match;
+ struct s3c24xx_swrst_drv_data *data;
+
+ np = of_find_matching_node_and_match(NULL, s3c24xx_swrst_match, &match);
+ if (!np)
+ return;
+
+ data = (struct s3c24xx_swrst_drv_data *)match->data;
+ swrst_type = data->cpu_type;
+
+ swrst_base = of_iomap(np, 0);
+ if (!swrst_base) {
+ pr_err("%s: failed to map swrst register\n", __func__);
+ return;
+ }
+
+}
+#endif
+
+void __init s3c24xx_swrst_reset_init(void __iomem *base, bool is_s3c2412)
+{
+ swrst_base = base;
+ swrst_type = (is_s3c2412) ? TYPE_S3C2412 : TYPE_S3C2443;
+}
--
1.7.10.4
next prev parent reply other threads:[~2014-01-06 18:38 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-06 18:35 [PATCH 0/5] ARM: S3C24XX: unify restart functions Heiko Stübner
2014-01-06 18:37 ` [PATCH 1/5] dt-bindings: document the s3c24xx software-reset register Heiko Stübner
2014-01-23 18:09 ` Tomasz Figa
2014-01-06 18:38 ` Heiko Stübner [this message]
2014-01-06 18:39 ` [PATCH 3/5] ARM: S3C24XX: add common reset function Heiko Stübner
2014-01-06 18:40 ` [PATCH 4/5] ARM: S3C24XX: convert boards to use common restart function Heiko Stübner
2014-01-23 18:12 ` Tomasz Figa
2014-01-23 18:36 ` Heiko Stübner
2014-01-23 18:51 ` Tomasz Figa
2014-01-23 19:02 ` Heiko Stübner
2014-01-23 22:35 ` Tomasz Figa
2014-01-24 8:03 ` Heiko Stübner
2014-01-24 10:08 ` Tomasz Figa
2014-01-06 18:40 ` [PATCH 5/5] ARM: S3C24XX: remove obsolete SoC-specific restart functions Heiko Stübner
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=1569032.VYgrksRbsn@phil \
--to=heiko@sntech.de \
--cc=linux-arm-kernel@lists.infradead.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).