diff options
author | Heiko Stübner <heiko@sntech.de> | 2014-08-19 20:45:37 -0400 |
---|---|---|
committer | Heiko Stuebner <heiko@sntech.de> | 2014-10-01 08:14:46 -0400 |
commit | e317c19470f6d690122519bf9ed1c9f21ea11906 (patch) | |
tree | f34377071df2a93aa92f0c714a790e1d52752c11 | |
parent | 6f1294b5a87238c2f87f74a9942faf2f4ffa63b2 (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.c | 29 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s3c2443.c | 19 |
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 */ |
31 | enum s3c2412_plls { | 33 | enum 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 | ||
209 | static 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 | |||
226 | static 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 | ||
272 | static void __init s3c2412_clk_init(struct device_node *np) | 301 | static 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 */ |
38 | enum supported_socs { | 40 | enum 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 | ||
359 | static 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 | |||
366 | static 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 | ||
452 | static void __init s3c2416_clk_init(struct device_node *np) | 471 | static void __init s3c2416_clk_init(struct device_node *np) |