aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHeiko Stübner <heiko@sntech.de>2014-08-19 20:45:37 -0400
committerHeiko Stuebner <heiko@sntech.de>2014-10-01 08:14:46 -0400
commite317c19470f6d690122519bf9ed1c9f21ea11906 (patch)
treef34377071df2a93aa92f0c714a790e1d52752c11
parent6f1294b5a87238c2f87f74a9942faf2f4ffa63b2 (diff)
clk: samsung: register restart handlers for s3c2412 and s3c2443
S3C2412, S3C2443 and their derivatives contain a special software-reset register in their system-controller. Therefore register a restart handler for those. Tested on a s3c2416-based board, s3c2412 compile-tested. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c29
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c19
2 files changed, 48 insertions, 0 deletions
diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c
index 34af09f6a155..2ceedaf8ce18 100644
--- a/drivers/clk/samsung/clk-s3c2412.c
+++ b/drivers/clk/samsung/clk-s3c2412.c
@@ -14,6 +14,7 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/reboot.h>
17 18
18#include <dt-bindings/clock/s3c2412.h> 19#include <dt-bindings/clock/s3c2412.h>
19 20
@@ -26,6 +27,7 @@
26#define CLKCON 0x0c 27#define CLKCON 0x0c
27#define CLKDIVN 0x14 28#define CLKDIVN 0x14
28#define CLKSRC 0x1c 29#define CLKSRC 0x1c
30#define SWRST 0x30
29 31
30/* list of PLLs to be registered */ 32/* list of PLLs to be registered */
31enum s3c2412_plls { 33enum s3c2412_plls {
@@ -204,6 +206,28 @@ struct samsung_clock_alias s3c2412_aliases[] __initdata = {
204 ALIAS(MSYSCLK, NULL, "fclk"), 206 ALIAS(MSYSCLK, NULL, "fclk"),
205}; 207};
206 208
209static int s3c2412_restart(struct notifier_block *this,
210 unsigned long mode, void *cmd)
211{
212 /* errata "Watch-dog/Software Reset Problem" specifies that
213 * this reset must be done with the SYSCLK sourced from
214 * EXTCLK instead of FOUT to avoid a glitch in the reset
215 * mechanism.
216 *
217 * See the watchdog section of the S3C2412 manual for more
218 * information on this fix.
219 */
220
221 __raw_writel(0x00, reg_base + CLKSRC);
222 __raw_writel(0x533C2412, reg_base + SWRST);
223 return NOTIFY_DONE;
224}
225
226static struct notifier_block s3c2412_restart_handler = {
227 .notifier_call = s3c2412_restart,
228 .priority = 129,
229};
230
207/* 231/*
208 * fixed rate clocks generated outside the soc 232 * fixed rate clocks generated outside the soc
209 * Only necessary until the devicetree-move is complete 233 * Only necessary until the devicetree-move is complete
@@ -233,6 +257,7 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
233 unsigned long ext_f, void __iomem *base) 257 unsigned long ext_f, void __iomem *base)
234{ 258{
235 struct samsung_clk_provider *ctx; 259 struct samsung_clk_provider *ctx;
260 int ret;
236 reg_base = base; 261 reg_base = base;
237 262
238 if (np) { 263 if (np) {
@@ -267,6 +292,10 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f,
267 s3c2412_clk_sleep_init(); 292 s3c2412_clk_sleep_init();
268 293
269 samsung_clk_of_add_provider(np, ctx); 294 samsung_clk_of_add_provider(np, ctx);
295
296 ret = register_restart_handler(&s3c2412_restart_handler);
297 if (ret)
298 pr_warn("cannot register restart handler, %d\n", ret);
270} 299}
271 300
272static void __init s3c2412_clk_init(struct device_node *np) 301static void __init s3c2412_clk_init(struct device_node *np)
diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c
index c92f853fca9f..0c3c182b902a 100644
--- a/drivers/clk/samsung/clk-s3c2443.c
+++ b/drivers/clk/samsung/clk-s3c2443.c
@@ -14,6 +14,7 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/syscore_ops.h> 16#include <linux/syscore_ops.h>
17#include <linux/reboot.h>
17 18
18#include <dt-bindings/clock/s3c2443.h> 19#include <dt-bindings/clock/s3c2443.h>
19 20
@@ -33,6 +34,7 @@
33#define HCLKCON 0x30 34#define HCLKCON 0x30
34#define PCLKCON 0x34 35#define PCLKCON 0x34
35#define SCLKCON 0x38 36#define SCLKCON 0x38
37#define SWRST 0x44
36 38
37/* the soc types */ 39/* the soc types */
38enum supported_socs { 40enum supported_socs {
@@ -354,6 +356,18 @@ struct samsung_clock_alias s3c2450_aliases[] __initdata = {
354 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), 356 ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"),
355}; 357};
356 358
359static int s3c2443_restart(struct notifier_block *this,
360 unsigned long mode, void *cmd)
361{
362 __raw_writel(0x533c2443, reg_base + SWRST);
363 return NOTIFY_DONE;
364}
365
366static struct notifier_block s3c2443_restart_handler = {
367 .notifier_call = s3c2443_restart,
368 .priority = 129,
369};
370
357/* 371/*
358 * fixed rate clocks generated outside the soc 372 * fixed rate clocks generated outside the soc
359 * Only necessary until the devicetree-move is complete 373 * Only necessary until the devicetree-move is complete
@@ -378,6 +392,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
378 void __iomem *base) 392 void __iomem *base)
379{ 393{
380 struct samsung_clk_provider *ctx; 394 struct samsung_clk_provider *ctx;
395 int ret;
381 reg_base = base; 396 reg_base = base;
382 397
383 if (np) { 398 if (np) {
@@ -447,6 +462,10 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
447 s3c2443_clk_sleep_init(); 462 s3c2443_clk_sleep_init();
448 463
449 samsung_clk_of_add_provider(np, ctx); 464 samsung_clk_of_add_provider(np, ctx);
465
466 ret = register_restart_handler(&s3c2443_restart_handler);
467 if (ret)
468 pr_warn("cannot register restart handler, %d\n", ret);
450} 469}
451 470
452static void __init s3c2416_clk_init(struct device_node *np) 471static void __init s3c2416_clk_init(struct device_node *np)