summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2015-09-01 09:43:55 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2015-09-01 09:43:55 +0200
commit67e0a30e77c0dadfb225eef7e9bdcccdcae4d679 (patch)
treeaa1887ec66dc1e48eaeacca93ac38b55a49a3f99
parentb7ab2081b1f1f13f0823bb6e8e33884510e105d7 (diff)
parentce36b4a05e275dcc12e74e96ddae99c21faad466 (diff)
downloadbarebox-67e0a30e77c0dadfb225eef7e9bdcccdcae4d679.tar.gz
barebox-67e0a30e77c0dadfb225eef7e9bdcccdcae4d679.tar.xz
Merge branch 'for-next/restart'
-rw-r--r--arch/arm/lib/bootm.c7
-rw-r--r--arch/arm/mach-at91/at91rm9200_time.c14
-rw-r--r--arch/arm/mach-at91/at91sam9_reset.S4
-rw-r--r--arch/arm/mach-at91/at91sam9g45_reset.S4
-rw-r--r--arch/arm/mach-at91/bootstrap.c3
-rw-r--r--arch/arm/mach-at91/setup.c9
-rw-r--r--arch/arm/mach-bcm2835/core.c21
-rw-r--r--arch/arm/mach-clps711x/reset.c12
-rw-r--r--arch/arm/mach-davinci/time.c14
-rw-r--r--arch/arm/mach-digic/Makefile2
-rw-r--r--arch/arm/mach-digic/core.c25
-rw-r--r--arch/arm/mach-ep93xx/clocksource.c19
-rw-r--r--arch/arm/mach-highbank/reset.c14
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c9
-rw-r--r--arch/arm/mach-mvebu/common.c13
-rw-r--r--arch/arm/mach-mvebu/dove.c9
-rw-r--r--arch/arm/mach-mvebu/include/mach/common.h1
-rw-r--r--arch/arm/mach-mvebu/kirkwood.c9
-rw-r--r--arch/arm/mach-mxs/soc-imx23.c8
-rw-r--r--arch/arm/mach-mxs/soc-imx28.c9
-rw-r--r--arch/arm/mach-netx/generic.c23
-rw-r--r--arch/arm/mach-nomadik/reset.c15
-rw-r--r--arch/arm/mach-omap/am33xx_generic.c7
-rw-r--r--arch/arm/mach-omap/include/mach/am33xx-generic.h2
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-generic.h2
-rw-r--r--arch/arm/mach-omap/include/mach/omap4-generic.h2
-rw-r--r--arch/arm/mach-omap/omap3_generic.c8
-rw-r--r--arch/arm/mach-omap/omap4_generic.c7
-rw-r--r--arch/arm/mach-omap/omap_generic.c11
-rw-r--r--arch/arm/mach-pxa/common.c14
-rw-r--r--arch/arm/mach-rockchip/core.c16
-rw-r--r--arch/arm/mach-samsung/generic.c15
-rw-r--r--arch/arm/mach-socfpga/reset-manager.c14
-rw-r--r--arch/arm/mach-tegra/tegra20-pmc.c9
-rw-r--r--arch/arm/mach-uemd/Makefile2
-rw-r--r--arch/arm/mach-uemd/reset.c24
-rw-r--r--arch/arm/mach-versatile/core.c7
-rw-r--r--arch/arm/mach-vexpress/reset.c15
-rw-r--r--arch/arm/mach-zynq/zynq.c24
-rw-r--r--arch/blackfin/lib/cpu.c13
-rw-r--r--arch/blackfin/lib/traps.c5
-rw-r--r--arch/efi/efi/efi.c13
-rw-r--r--arch/mips/lib/bootm.c3
-rw-r--r--arch/mips/mach-ar231x/ar231x_reset.c8
-rw-r--r--arch/mips/mach-ath79/reset.c15
-rw-r--r--arch/mips/mach-bcm47xx/reset.c16
-rw-r--r--arch/mips/mach-loongson/loongson1_reset.c15
-rw-r--r--arch/mips/mach-malta/reset.c16
-rw-r--r--arch/nios2/cpu/cpu.c12
-rw-r--r--arch/openrisc/cpu/cpu.c11
-rw-r--r--arch/ppc/lib/ppclinux.c3
-rw-r--r--arch/ppc/mach-mpc5xxx/cpu.c11
-rw-r--r--arch/ppc/mach-mpc85xx/cpu.c14
-rw-r--r--arch/sandbox/board/Makefile1
-rw-r--r--arch/sandbox/board/restart.c17
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h1
-rw-r--r--arch/sandbox/os/common.c6
-rw-r--r--arch/x86/mach-i386/Makefile2
-rw-r--r--arch/x86/mach-i386/reset.c30
-rw-r--r--commands/reset.c3
-rw-r--r--common/Makefile1
-rw-r--r--common/misc.c3
-rw-r--r--common/reset_source.c31
-rw-r--r--common/restart.c112
-rw-r--r--drivers/mfd/Kconfig11
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/da9053.c308
-rw-r--r--drivers/mfd/da9063.c169
-rw-r--r--drivers/usb/gadget/f_fastboot.c3
-rw-r--r--drivers/watchdog/davinci_wdt.c1
-rw-r--r--drivers/watchdog/im28wd.c1
-rw-r--r--drivers/watchdog/imxwd.c35
-rw-r--r--drivers/watchdog/jz4740.c37
-rw-r--r--drivers/watchdog/wd_core.c70
-rw-r--r--include/common.h1
-rw-r--r--include/reset_source.h14
-rw-r--r--include/restart.h21
-rw-r--r--include/watchdog.h8
78 files changed, 1150 insertions, 316 deletions
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 8327c3f560..7bb9b43656 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -16,6 +16,7 @@
#include <libbb.h>
#include <magicvar.h>
#include <binfmt.h>
+#include <restart.h>
#include <asm/byteorder.h>
#include <asm/setup.h>
@@ -111,7 +112,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem, int
start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree);
- reset_cpu(0);
+ restart_machine();
return -ERESTARTSYS;
}
@@ -378,7 +379,7 @@ static int do_bootm_barebox(struct image_data *data)
start_linux(barebox, 0, 0, 0, data->oftree);
- reset_cpu(0);
+ restart_machine();
}
static struct image_handler barebox_handler = {
@@ -518,7 +519,7 @@ static int do_bootm_aimage(struct image_data *data)
second();
- reset_cpu(0);
+ restart_machine();
}
close(fd);
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index ae0172b4f4..fd11223b6f 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -28,6 +28,7 @@
#include <common.h>
#include <init.h>
#include <clock.h>
+#include <restart.h>
#include <mach/hardware.h>
#include <mach/at91_tc.h>
#include <mach/at91_st.h>
@@ -77,7 +78,7 @@ core_initcall(clocksource_init);
/*
* Reset the cpu through the reset controller
*/
-void __noreturn reset_cpu (unsigned long ignored)
+static void __noreturn at91rm9200_restart_soc(struct restart_handler *rst)
{
/*
* Perform a hardware reset with the use of the Watchdog timer.
@@ -86,6 +87,13 @@ void __noreturn reset_cpu (unsigned long ignored)
at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
/* Not reached */
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(at91rm9200_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-at91/at91sam9_reset.S b/arch/arm/mach-at91/at91sam9_reset.S
index 3a3e77aaa5..890545edbf 100644
--- a/arch/arm/mach-at91/at91sam9_reset.S
+++ b/arch/arm/mach-at91/at91sam9_reset.S
@@ -20,9 +20,9 @@
.arm
- .globl reset_cpu
+ .globl restart_sam9
-reset_cpu: ldr r0, .at91_va_base_sdramc @ preload constants
+restart_sam9: ldr r0, .at91_va_base_sdramc @ preload constants
ldr r1, .at91_va_base_rstc_cr
mov r2, #1
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
index e70d733ac8..2cb113cdb4 100644
--- a/arch/arm/mach-at91/at91sam9g45_reset.S
+++ b/arch/arm/mach-at91/at91sam9g45_reset.S
@@ -17,9 +17,9 @@
.arm
- .globl reset_cpu
+ .globl restart_sam9g45
-reset_cpu: ldr r0, .at91_va_base_sdramc @ preload constants
+restart_sam9g45: ldr r0, .at91_va_base_sdramc @ preload constants
ldr r1, .at91_va_base_rstc_cr
mov r2, #1
diff --git a/arch/arm/mach-at91/bootstrap.c b/arch/arm/mach-at91/bootstrap.c
index 2d18dd6b32..1baf7323fe 100644
--- a/arch/arm/mach-at91/bootstrap.c
+++ b/arch/arm/mach-at91/bootstrap.c
@@ -9,6 +9,7 @@
#include <mach/bootstrap.h>
#include <linux/sizes.h>
#include <malloc.h>
+#include <restart.h>
#include <init.h>
#include <menu.h>
@@ -145,7 +146,7 @@ static void boot_mmc_disk_action(struct menu *m, struct menu_entry *me)
static void boot_reset_action(struct menu *m, struct menu_entry *me)
{
- reset_cpu(0);
+ restart_machine();
}
void at91_bootstrap_menu(void)
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 341979ae89..1fa50ac054 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <io.h>
#include <init.h>
+#include <restart.h>
#include <mach/hardware.h>
#include <mach/cpu.h>
@@ -296,6 +297,9 @@ static int at91_detect(void)
}
postcore_initcall(at91_detect);
+void restart_sam9(struct restart_handler *rst);
+void restart_sam9g45(struct restart_handler *rst);
+
static int at91_soc_device(void)
{
struct device_d *dev;
@@ -304,6 +308,11 @@ static int at91_soc_device(void)
dev_add_param_fixed(dev, "name", (char*)at91_get_soc_type(&at91_soc_initdata));
dev_add_param_fixed(dev, "subname", (char*)at91_get_soc_subtype(&at91_soc_initdata));
+ if (IS_ENABLED(CONFIG_AT91SAM9_RESET))
+ restart_handler_register_fn(restart_sam9);
+ if (IS_ENABLED(CONFIG_AT91SAM9G45_RESET))
+ restart_handler_register_fn(restart_sam9g45);
+
return 0;
}
coredevice_initcall(at91_soc_device);
diff --git a/arch/arm/mach-bcm2835/core.c b/arch/arm/mach-bcm2835/core.c
index 5d08012f8b..64f3781388 100644
--- a/arch/arm/mach-bcm2835/core.c
+++ b/arch/arm/mach-bcm2835/core.c
@@ -18,6 +18,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
@@ -51,13 +52,6 @@ static int bcm2835_clk_init(void)
}
postcore_initcall(bcm2835_clk_init);
-static int bcm2835_dev_init(void)
-{
- add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL);
- return 0;
-}
-coredevice_initcall(bcm2835_dev_init);
-
void bcm2835_register_uart(void)
{
amba_apb_device_add(NULL, "uart0-pl011", 0, BCM2835_UART0_BASE, 4096, NULL, 0);
@@ -72,7 +66,7 @@ void bcm2835_add_device_sdram(u32 size)
}
#define RESET_TIMEOUT 10
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn bcm2835_restart_soc(struct restart_handler *rst)
{
uint32_t rstc;
@@ -82,6 +76,13 @@ void __noreturn reset_cpu(unsigned long addr)
writel(PM_PASSWORD | RESET_TIMEOUT, PM_WDOG);
writel(PM_PASSWORD | rstc, PM_RSTC);
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int bcm2835_dev_init(void)
+{
+ add_generic_device("bcm2835-gpio", 0, NULL, BCM2835_GPIO_BASE, 0xB0, IORESOURCE_MEM, NULL);
+ restart_handler_register_fn(bcm2835_restart_soc);
+ return 0;
+}
+coredevice_initcall(bcm2835_dev_init);
diff --git a/arch/arm/mach-clps711x/reset.c b/arch/arm/mach-clps711x/reset.c
index 859d8ae574..03f40b73fa 100644
--- a/arch/arm/mach-clps711x/reset.c
+++ b/arch/arm/mach-clps711x/reset.c
@@ -8,8 +8,10 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn clps711x_restart_soc(struct restart_handler *rst)
{
shutdown_barebox();
@@ -17,3 +19,11 @@ void __noreturn reset_cpu(unsigned long addr)
hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(clps711x_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 60f0d192a3..4d1b570aa0 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <io.h>
#include <init.h>
+#include <restart.h>
#include <clock.h>
#include <mach/time.h>
@@ -164,7 +165,7 @@ static int clocksource_init(void)
core_initcall(clocksource_init);
/* reset board using watchdog timer */
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn davinci_restart_soc(struct restart_handler *rst)
{
u32 tgcr, wdtcr;
void __iomem *base;
@@ -204,6 +205,13 @@ void __noreturn reset_cpu(ulong addr)
wdtcr = 0x00004000;
__raw_writel(wdtcr, base + WDTCR);
- unreachable();
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(davinci_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-digic/Makefile b/arch/arm/mach-digic/Makefile
index 820eb10ac2..16a218658a 100644
--- a/arch/arm/mach-digic/Makefile
+++ b/arch/arm/mach-digic/Makefile
@@ -1 +1 @@
-obj-y += core.o
+obj- := __dummy__.o
diff --git a/arch/arm/mach-digic/core.c b/arch/arm/mach-digic/core.c
deleted file mode 100644
index b1caec0bc8..0000000000
--- a/arch/arm/mach-digic/core.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * See file CREDITS for list of people who contributed to this project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <common.h>
-
-void __noreturn reset_cpu(unsigned long ignored)
-{
- pr_err("%s: unimplemented\n", __func__);
- hang();
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-ep93xx/clocksource.c b/arch/arm/mach-ep93xx/clocksource.c
index f396d0a0a2..83c05cea00 100644
--- a/arch/arm/mach-ep93xx/clocksource.c
+++ b/arch/arm/mach-ep93xx/clocksource.c
@@ -20,6 +20,7 @@
#include <init.h>
#include <clock.h>
#include <io.h>
+#include <restart.h>
#include <mach/ep93xx-regs.h>
#define TIMER_CLKSEL (1 << 3)
@@ -63,10 +64,8 @@ static int clocksource_init(void)
core_initcall(clocksource_init);
-/*
- * Reset the cpu
- */
-void __noreturn reset_cpu(unsigned long addr)
+/* Reset the SoC */
+static void __noreturn ep92xx_restart_soc(struct restart_handler *rst)
{
struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE;
uint32_t value;
@@ -84,7 +83,13 @@ void __noreturn reset_cpu(unsigned long addr)
writel(value, &syscon->devicecfg);
/* Dying... */
- while (1)
- ; /* noop */
+ hang();
+}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(ep92xx_restart_soc);
+
+ return 0;
}
-EXPORT_SYMBOL(reset_cpu);
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-highbank/reset.c b/arch/arm/mach-highbank/reset.c
index b9664e41bb..929ded5951 100644
--- a/arch/arm/mach-highbank/reset.c
+++ b/arch/arm/mach-highbank/reset.c
@@ -6,17 +6,27 @@
#include <common.h>
#include <io.h>
+#include <restart.h>
+#include <init.h>
#include <mach/devices.h>
#include <mach/sysregs.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn highbank_restart_soc(struct restart_handler *rst)
{
hingbank_set_pwr_hard_reset();
asm(" wfi");
- while(1);
+ hang();
+}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(highbank_restart_soc);
+
+ return 0;
}
+coredevice_initcall(restart_register_feature);
void __noreturn poweroff()
{
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 2405629526..c362cfdabe 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -17,6 +17,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <of.h>
#include <of_address.h>
#include <asm/memory.h>
@@ -104,12 +105,12 @@ static int armada_370_xp_soc_id_fixup(void)
return 0;
}
-static void __noreturn armada_370_xp_reset_cpu(unsigned long addr)
+static void __noreturn armada_370_xp_restart_soc(struct restart_handler *rst)
{
writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x60);
writel(0x1, ARMADA_370_XP_SYSCTL_BASE + 0x64);
- while (1)
- ;
+
+ hang();
}
static int armada_xp_init_soc(struct device_node *root)
@@ -132,7 +133,7 @@ static int armada_370_xp_init_soc(struct device_node *root, void *context)
if (!of_machine_is_compatible("marvell,armada-370-xp"))
return 0;
- mvebu_set_reset(armada_370_xp_reset_cpu);
+ restart_handler_register_fn(armada_370_xp_restart_soc);
barebox_set_model("Marvell Armada 370/XP");
barebox_set_hostname("armada");
diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c
index 7d28d9c45a..cb40d0cb6f 100644
--- a/arch/arm/mach-mvebu/common.c
+++ b/arch/arm/mach-mvebu/common.c
@@ -123,16 +123,3 @@ int mvebu_set_memory(u64 phys_base, u64 phys_size)
return 0;
}
-
-static __noreturn void (*mvebu_reset_cpu)(unsigned long addr);
-
-void __noreturn reset_cpu(unsigned long addr)
-{
- mvebu_reset_cpu(addr);
-}
-EXPORT_SYMBOL(reset_cpu);
-
-void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr))
-{
- mvebu_reset_cpu = reset;
-}
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index a7284fd33a..ba4af3aae9 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -17,6 +17,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <asm/memory.h>
#include <linux/mbus.h>
#include <mach/dove-regs.h>
@@ -68,13 +69,13 @@ static inline void dove_memory_find(unsigned long *phys_base,
}
}
-static void __noreturn dove_reset_cpu(unsigned long addr)
+static void __noreturn dove_restart_soc(struct restart_handler *rst)
{
/* enable and assert RSTOUTn */
writel(SOFT_RESET_OUT_EN, DOVE_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
writel(SOFT_RESET_EN, DOVE_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
- while (1)
- ;
+
+ hang();
}
static int dove_init_soc(struct device_node *root, void *context)
@@ -84,7 +85,7 @@ static int dove_init_soc(struct device_node *root, void *context)
if (!of_machine_is_compatible("marvell,dove"))
return 0;
- mvebu_set_reset(dove_reset_cpu);
+ restart_handler_register_fn(dove_restart_soc);
barebox_set_model("Marvell Dove");
barebox_set_hostname("dove");
diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h
index 5ce33fd882..602af8f28f 100644
--- a/arch/arm/mach-mvebu/include/mach/common.h
+++ b/arch/arm/mach-mvebu/include/mach/common.h
@@ -21,6 +21,5 @@
#define MVEBU_REMAP_INT_REG_BASE 0xf1000000
int mvebu_set_memory(u64 phys_base, u64 phys_size);
-void mvebu_set_reset(void __noreturn (*reset)(unsigned long addr));
#endif
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index 19c6f07303..72a6b0db3c 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <asm/memory.h>
#include <linux/mbus.h>
#include <mach/kirkwood-regs.h>
@@ -43,12 +44,12 @@ static inline void kirkwood_memory_find(unsigned long *phys_base,
}
}
-static void __noreturn kirkwood_reset_cpu(unsigned long addr)
+static void __noreturn kirkwood_restart_soc(struct restart_handler *rst)
{
writel(SOFT_RESET_OUT_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_RSTOUT_MASK);
writel(SOFT_RESET_EN, KIRKWOOD_BRIDGE_BASE + BRIDGE_SYS_SOFT_RESET);
- for(;;)
- ;
+
+ hang();
}
static int kirkwood_init_soc(struct device_node *root, void *context)
@@ -58,7 +59,7 @@ static int kirkwood_init_soc(struct device_node *root, void *context)
if (!of_machine_is_compatible("marvell,kirkwood"))
return 0;
- mvebu_set_reset(kirkwood_reset_cpu);
+ restart_handler_register_fn(kirkwood_restart_soc);
barebox_set_model("Marvell Kirkwood");
barebox_set_hostname("kirkwood");
diff --git a/arch/arm/mach-mxs/soc-imx23.c b/arch/arm/mach-mxs/soc-imx23.c
index 339c57748f..d471c8eb5c 100644
--- a/arch/arm/mach-mxs/soc-imx23.c
+++ b/arch/arm/mach-mxs/soc-imx23.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <mach/imx23-regs.h>
#include <io.h>
@@ -23,18 +24,16 @@
# define HW_CLKCTRL_RESET_CHIP (1 << 1)
/* Reset the full i.MX23 SoC via a chipset feature */
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn imx23_restart_soc(struct restart_handler *rst)
{
u32 reg;
reg = readl(IMX_CCM_BASE + HW_CLKCTRL_RESET);
writel(reg | HW_CLKCTRL_RESET_CHIP, IMX_CCM_BASE + HW_CLKCTRL_RESET);
- while (1)
- ;
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
static int imx23_devices_init(void)
{
@@ -46,6 +45,7 @@ static int imx23_devices_init(void)
add_generic_device("imx23-gpio", 0, NULL, IMX_IOMUXC_BASE, 0x2000, IORESOURCE_MEM, NULL);
add_generic_device("imx23-gpio", 1, NULL, IMX_IOMUXC_BASE, 0x2000, IORESOURCE_MEM, NULL);
add_generic_device("imx23-gpio", 2, NULL, IMX_IOMUXC_BASE, 0x2000, IORESOURCE_MEM, NULL);
+ restart_handler_register_fn(imx23_restart_soc);
return 0;
}
diff --git a/arch/arm/mach-mxs/soc-imx28.c b/arch/arm/mach-mxs/soc-imx28.c
index b4ec38d912..dc6020aa36 100644
--- a/arch/arm/mach-mxs/soc-imx28.c
+++ b/arch/arm/mach-mxs/soc-imx28.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <mach/imx28-regs.h>
#include <io.h>
@@ -24,18 +25,16 @@
#define HW_CLKCTRL_WDOG_POR_DISABLE (1 << 5)
/* Reset the full i.MX28 SoC via a chipset feature */
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn imx28_restart_soc(struct restart_handler *rst)
{
u32 reg;
reg = readl(IMX_CCM_BASE + HW_CLKCTRL_RESET);
writel(reg | HW_CLKCTRL_RESET_CHIP, IMX_CCM_BASE + HW_CLKCTRL_RESET);
- while (1)
- ;
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
static int imx28_init(void)
{
@@ -50,6 +49,8 @@ static int imx28_init(void)
HW_CLKCTRL_WDOG_POR_DISABLE;
writel(reg, IMX_CCM_BASE + HW_CLKCTRL_RESET);
+ restart_handler_register_fn(imx28_restart_soc);
+
return 0;
}
postcore_initcall(imx28_init);
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
index 6127dde868..6c3b953d1f 100644
--- a/arch/arm/mach-netx/generic.c
+++ b/arch/arm/mach-netx/generic.c
@@ -15,8 +15,10 @@
*/
#include <common.h>
+#include <init.h>
#include <command.h>
#include <io.h>
+#include <restart.h>
#include <mach/netx-regs.h>
#include "eth_firmware.h"
@@ -134,17 +136,24 @@ failure:
return COMMAND_ERROR_USAGE;
}
-void __noreturn reset_cpu(unsigned long addr)
+BAREBOX_CMD_START(loadxc)
+ .cmd = do_loadxc,
+ BAREBOX_CMD_DESC("load XMAC/XPEC engine with ethernet firmware")
+ BAREBOX_CMD_GROUP(CMD_GRP_NET)
+BAREBOX_CMD_END
+
+static void __noreturn netx_restart_soc(struct restart_handler *rst)
{
SYSTEM_REG(SYSTEM_RES_CR) = 0x01000008;
/* Not reached */
- while (1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(netx_restart_soc);
-BAREBOX_CMD_START(loadxc)
- .cmd = do_loadxc,
- BAREBOX_CMD_DESC("load XMAC/XPEC engine with ethernet firmware")
- BAREBOX_CMD_GROUP(CMD_GRP_NET)
-BAREBOX_CMD_END
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-nomadik/reset.c b/arch/arm/mach-nomadik/reset.c
index bb5696a345..8bdaada8a1 100644
--- a/arch/arm/mach-nomadik/reset.c
+++ b/arch/arm/mach-nomadik/reset.c
@@ -15,10 +15,12 @@
*/
#include <common.h>
+#include <init.h>
#include <io.h>
+#include <restart.h>
#include <mach/hardware.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn nomadik_restart_soc(struct restart_handler *rst)
{
void __iomem *src_rstsr = (void *)(NOMADIK_SRC_BASE + 0x18);
@@ -28,6 +30,13 @@ void __noreturn reset_cpu(unsigned long addr)
writel(1, src_rstsr);
/* Not reached */
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(nomadik_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index 7ce32f01e1..ae0ee585a8 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -19,6 +19,7 @@
#include <init.h>
#include <io.h>
#include <net.h>
+#include <restart.h>
#include <asm/barebox-arm.h>
#include <mach/am33xx-silicon.h>
#include <mach/am33xx-clock.h>
@@ -28,11 +29,11 @@
#include <mach/gpmc.h>
#include <reset_source.h>
-void __noreturn am33xx_reset_cpu(unsigned long addr)
+static void __noreturn am33xx_restart_soc(struct restart_handler *rst)
{
writel(AM33XX_PRM_RSTCTRL_RESET, AM33XX_PRM_RSTCTRL);
- while (1);
+ hang();
}
/**
@@ -243,6 +244,8 @@ int am33xx_init(void)
{
omap_gpmc_base = (void *)AM33XX_GPMC_BASE;
+ restart_handler_register_fn(am33xx_restart_soc);
+
am33xx_enable_per_clocks();
if (IS_ENABLED(CONFIG_RESET_SOURCE))
diff --git a/arch/arm/mach-omap/include/mach/am33xx-generic.h b/arch/arm/mach-omap/include/mach/am33xx-generic.h
index 03418b053b..7e64e74d5c 100644
--- a/arch/arm/mach-omap/include/mach/am33xx-generic.h
+++ b/arch/arm/mach-omap/include/mach/am33xx-generic.h
@@ -28,8 +28,6 @@ u32 am33xx_running_in_flash(void);
u32 am33xx_running_in_sram(void);
u32 am33xx_running_in_sdram(void);
-void __noreturn am33xx_reset_cpu(unsigned long addr);
-
void am33xx_enable_per_clocks(void);
int am33xx_init(void);
int am33xx_devices_init(void);
diff --git a/arch/arm/mach-omap/include/mach/omap3-generic.h b/arch/arm/mach-omap/include/mach/omap3-generic.h
index ab53b98971..177862e4b1 100644
--- a/arch/arm/mach-omap/include/mach/omap3-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap3-generic.h
@@ -24,8 +24,6 @@ u32 omap3_running_in_flash(void);
u32 omap3_running_in_sram(void);
u32 omap3_running_in_sdram(void);
-void __noreturn omap3_reset_cpu(unsigned long addr);
-
int omap3_init(void);
int omap3_devices_init(void);
diff --git a/arch/arm/mach-omap/include/mach/omap4-generic.h b/arch/arm/mach-omap/include/mach/omap4-generic.h
index e246e360e5..7ec41d880b 100644
--- a/arch/arm/mach-omap/include/mach/omap4-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap4-generic.h
@@ -18,8 +18,6 @@ static inline void omap4_save_bootinfo(uint32_t *info)
memcpy((void *)OMAP44XX_SRAM_SCRATCH_SPACE, info, 3 * sizeof(uint32_t));
}
-void __noreturn omap4_reset_cpu(unsigned long addr);
-
int omap4_init(void);
int omap4_devices_init(void);
diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c
index 0f2e9ce6b7..5c29feaeb4 100644
--- a/arch/arm/mach-omap/omap3_generic.c
+++ b/arch/arm/mach-omap/omap3_generic.c
@@ -31,6 +31,7 @@
#include <bootsource.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <mach/omap3-silicon.h>
#include <mach/gpmc.h>
#include <mach/generic.h>
@@ -52,13 +53,12 @@
*
* @return void
*/
-void __noreturn omap3_reset_cpu(unsigned long addr)
+static void __noreturn omap3_restart_soc(struct restart_handler *rst)
{
writel(OMAP3_PRM_RSTCTRL_RESET, OMAP3_PRM_REG(RSTCTRL));
- while (1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
/**
* @brief Low level CPU type
@@ -490,6 +490,8 @@ int omap3_init(void)
{
omap_gpmc_base = (void *)OMAP3_GPMC_BASE;
+ restart_handler_register_fn(omap3_restart_soc);
+
return omap3_bootsource();
}
diff --git a/arch/arm/mach-omap/omap4_generic.c b/arch/arm/mach-omap/omap4_generic.c
index 0b683da181..a3f370df8f 100644
--- a/arch/arm/mach-omap/omap4_generic.c
+++ b/arch/arm/mach-omap/omap4_generic.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <bootsource.h>
#include <init.h>
+#include <restart.h>
#include <io.h>
#include <mach/omap4-clock.h>
#include <mach/omap4-silicon.h>
@@ -34,11 +35,11 @@
#define EMIF_L3_CONFIG_VAL_SYS_10_LL_0 0x0A0000FF
#define EMIF_L3_CONFIG_VAL_SYS_10_MPU_3_LL_0 0x0A300000
-void __noreturn omap4_reset_cpu(unsigned long addr)
+static void __noreturn omap4_restart_soc(struct restart_handler *rst)
{
writel(OMAP44XX_PRM_RSTCTRL_RESET, OMAP44XX_PRM_RSTCTRL);
- while (1);
+ hang();
}
void omap4_set_warmboot_order(u32 *device_list)
@@ -533,6 +534,8 @@ int omap4_init(void)
{
omap_gpmc_base = (void *)OMAP44XX_GPMC_BASE;
+ restart_handler_register_fn(omap4_restart_soc);
+
return omap4_bootsource();
}
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index 334cf8db56..165487c645 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -150,17 +150,6 @@ static int omap_env_init(void)
late_initcall(omap_env_init);
#endif
-void __noreturn reset_cpu(unsigned long addr)
-{
- if (cpu_is_omap3())
- omap3_reset_cpu(addr);
- if (cpu_is_omap4())
- omap4_reset_cpu(addr);
- if (cpu_is_am33xx())
- am33xx_reset_cpu(addr);
- while (1);
-}
-
static int omap_soc_from_dt(void)
{
if (of_machine_is_compatible("ti,am33xx"))
diff --git a/arch/arm/mach-pxa/common.c b/arch/arm/mach-pxa/common.c
index 2c27d812fc..c0281d69ef 100644
--- a/arch/arm/mach-pxa/common.c
+++ b/arch/arm/mach-pxa/common.c
@@ -16,6 +16,8 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <mach/pxa-regs.h>
#include <asm/io.h>
@@ -29,7 +31,7 @@
extern void pxa_clear_reset_source(void);
-void reset_cpu(ulong addr)
+static void __noreturn pxa_restart_soc(struct restart_handler *rst)
{
/* Clear last reset source */
pxa_clear_reset_source();
@@ -39,5 +41,13 @@ void reset_cpu(ulong addr)
writel(OSSR_M3, OSSR);
writel(readl(OSCR) + 368640, OSMR3); /* ... in 100 ms */
- while (1);
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(pxa_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-rockchip/core.c b/arch/arm/mach-rockchip/core.c
index bab06df63c..2428fee349 100644
--- a/arch/arm/mach-rockchip/core.c
+++ b/arch/arm/mach-rockchip/core.c
@@ -13,16 +13,24 @@
#include <asm/io.h>
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <mach/rockchip-regs.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn rockchip_restart_soc(struct restart_handler *rst)
{
/* Map bootrom from address 0 */
writel(RK_SOC_CON0_REMAP << 16, RK_GRF_BASE + RK_GRF_SOC_CON0);
/* Reset */
writel(0xeca8, RK_CRU_BASE + RK_CRU_GLB_SRST_SND);
- while (1)
- ;
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(rockchip_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-samsung/generic.c b/arch/arm/mach-samsung/generic.c
index 75965d7826..4f13fce13b 100644
--- a/arch/arm/mach-samsung/generic.c
+++ b/arch/arm/mach-samsung/generic.c
@@ -21,6 +21,7 @@
#include <config.h>
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <io.h>
#include <mach/s3c-iomap.h>
#include <mach/s3c-generic.h>
@@ -29,7 +30,7 @@
#define S3C_WTDAT (S3C_WATCHDOG_BASE + 0x04)
#define S3C_WTCNT (S3C_WATCHDOG_BASE + 0x08)
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn samsung_restart_soc(struct restart_handler *rst)
{
/* Disable watchdog */
writew(0x0000, S3C_WTCON);
@@ -41,7 +42,13 @@ void __noreturn reset_cpu(unsigned long addr)
writew(0x0021, S3C_WTCON);
/* loop forever and wait for reset to happen */
- while(1)
- ;
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(samsung_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-socfpga/reset-manager.c b/arch/arm/mach-socfpga/reset-manager.c
index a9e7e1448f..04522da4d1 100644
--- a/arch/arm/mach-socfpga/reset-manager.c
+++ b/arch/arm/mach-socfpga/reset-manager.c
@@ -17,6 +17,8 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/socfpga-regs.h>
#include <mach/reset-manager.h>
@@ -38,7 +40,7 @@ void watchdog_disable(void)
}
/* Write the reset manager register to cause reset */
-void reset_cpu(ulong addr)
+static void __noreturn socfpga_restart_soc(struct restart_handler *rst)
{
/* request a warm reset */
writel((1 << RSTMGR_CTRL_SWWARMRSTREQ_LSB),
@@ -47,5 +49,13 @@ void reset_cpu(ulong addr)
* infinite loop here as watchdog will trigger and reset
* the processor
*/
- while (1);
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(socfpga_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-tegra/tegra20-pmc.c b/arch/arm/mach-tegra/tegra20-pmc.c
index eaa5ac73ff..02f0bf7499 100644
--- a/arch/arm/mach-tegra/tegra20-pmc.c
+++ b/arch/arm/mach-tegra/tegra20-pmc.c
@@ -23,6 +23,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/reset.h>
@@ -36,13 +37,12 @@ static void __iomem *pmc_base;
static int tegra_num_powerdomains;
/* main SoC reset trigger */
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn tegra20_restart_soc(struct restart_handler *rst)
{
writel(PMC_CNTRL_MAIN_RST, pmc_base + PMC_CNTRL);
- unreachable();
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
static int tegra_powergate_set(int id, bool new_state)
{
@@ -219,7 +219,7 @@ static int tegra20_pmc_probe(struct device_d *dev)
static int do_tegrarcm(int argc, char *argv[])
{
writel(2, pmc_base + PMC_SCRATCH(0));
- reset_cpu(0);
+ restart_machine();
return 0;
}
@@ -244,6 +244,7 @@ static struct driver_d tegra20_pmc_driver = {
static int tegra20_pmc_init(void)
{
+ restart_handler_register_fn(tegra20_restart_soc);
return platform_driver_register(&tegra20_pmc_driver);
}
coredevice_initcall(tegra20_pmc_init);
diff --git a/arch/arm/mach-uemd/Makefile b/arch/arm/mach-uemd/Makefile
index f3cc6684b8..16a218658a 100644
--- a/arch/arm/mach-uemd/Makefile
+++ b/arch/arm/mach-uemd/Makefile
@@ -1 +1 @@
-obj-y += reset.o
+obj- := __dummy__.o
diff --git a/arch/arm/mach-uemd/reset.c b/arch/arm/mach-uemd/reset.c
deleted file mode 100644
index 00ae0be0b3..0000000000
--- a/arch/arm/mach-uemd/reset.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * This file is part of barebox.
- * See file CREDITS for list of people who contributed to this project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <common.h>
-
-void __noreturn reset_cpu(ulong addr)
-{
- hang();
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index c671aa6173..7c6e9523a2 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -26,6 +26,7 @@
#include <init.h>
#include <clock.h>
#include <debug_ll.h>
+#include <restart.h>
#include <linux/sizes.h>
#include <linux/clkdev.h>
@@ -184,7 +185,7 @@ void versatile_register_uart(unsigned id)
amba_apb_device_add(NULL, "uart-pl011", id, start, 4096, NULL, 0);
}
-void __noreturn reset_cpu (unsigned long ignored)
+static void versatile_reset_soc(struct restart_handler *rst)
{
u32 val;
@@ -195,9 +196,8 @@ void __noreturn reset_cpu (unsigned long ignored)
__raw_writel(val, VERSATILE_SYS_RESETCTL);
__raw_writel(0, VERSATILE_SYS_LOCK);
- while(1);
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
static int versatile_init(void)
{
@@ -205,6 +205,7 @@ static int versatile_init(void)
amba_apb_device_add(NULL, "pl061_gpio", 1, 0x101e5000, 4096, NULL, 0);
amba_apb_device_add(NULL, "pl061_gpio", 2, 0x101e6000, 4096, NULL, 0);
amba_apb_device_add(NULL, "pl061_gpio", 3, 0x101e7000, 4096, NULL, 0);
+ restart_handler_register_fn(versatile_reset_soc);
return 0;
}
coredevice_initcall(versatile_init);
diff --git a/arch/arm/mach-vexpress/reset.c b/arch/arm/mach-vexpress/reset.c
index ad6e06fe5f..3164ae3079 100644
--- a/arch/arm/mach-vexpress/reset.c
+++ b/arch/arm/mach-vexpress/reset.c
@@ -6,17 +6,26 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <linux/amba/sp805.h>
#include <mach/devices.h>
void __iomem *v2m_wdt_base;
-void reset_cpu(ulong addr)
+static void vexpress_reset_soc(struct restart_handler *rst)
{
writel(LOAD_MIN, v2m_wdt_base + WDTLOAD);
writeb(RESET_ENABLE, v2m_wdt_base + WDTCONTROL);
- while (1)
- ;
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(vexpress_reset_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/arm/mach-zynq/zynq.c b/arch/arm/mach-zynq/zynq.c
index bd29e13377..a0a8d0d249 100644
--- a/arch/arm/mach-zynq/zynq.c
+++ b/arch/arm/mach-zynq/zynq.c
@@ -17,8 +17,19 @@
#include <asm-generic/io.h>
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <mach/zynq7000-regs.h>
+static void __noreturn zynq_restart_soc(struct restart_handler *rst)
+{
+ /* write unlock key to slcr */
+ writel(0xDF0D, ZYNQ_SLCR_UNLOCK);
+ /* reset */
+ writel(0x1, ZYNQ_PSS_RST_CTRL);
+
+ hang();
+}
+
static int zynq_init(void)
{
u32 val;
@@ -40,17 +51,8 @@ static int zynq_init(void)
add_generic_device("zynq-clock", 0, NULL, ZYNQ_SLCR_BASE, 0x4000, IORESOURCE_MEM, NULL);
add_generic_device("smp_twd", 0, NULL, CORTEXA9_SCU_TIMER_BASE_ADDR,
0x4000, IORESOURCE_MEM, NULL);
+ restart_handler_register_fn(zynq_restart_soc);
+
return 0;
}
postcore_initcall(zynq_init);
-
-void __noreturn reset_cpu(unsigned long addr)
-{
- /* write unlock key to slcr */
- writel(0xDF0D, ZYNQ_SLCR_UNLOCK);
- /* reset */
- writel(0x1, ZYNQ_PSS_RST_CTRL);
-
- while (1)
- ;
-}
diff --git a/arch/blackfin/lib/cpu.c b/arch/blackfin/lib/cpu.c
index 9d4c6e3e89..34b93e78ac 100644
--- a/arch/blackfin/lib/cpu.c
+++ b/arch/blackfin/lib/cpu.c
@@ -27,8 +27,9 @@
#include <asm/entry.h>
#include <asm/cpu.h>
#include <init.h>
+#include <restart.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn blackfin_restart_cpu(struct restart_handler *rst)
{
icache_disable();
@@ -41,9 +42,17 @@ void __noreturn reset_cpu(unsigned long addr)
);
/* Not reached */
- while (1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(blackfin_restart_cpu);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
+
void icache_disable(void)
{
#ifdef __ADSPBF537__
diff --git a/arch/blackfin/lib/traps.c b/arch/blackfin/lib/traps.c
index c2dda73465..2111d255fd 100644
--- a/arch/blackfin/lib/traps.c
+++ b/arch/blackfin/lib/traps.c
@@ -30,6 +30,7 @@
*/
#include <common.h>
+#include <restart.h>
#include <linux/types.h>
#include <asm/system.h>
#include <asm/traps.h>
@@ -91,7 +92,7 @@ void trap_c (struct pt_regs *regs)
printf("\nPlease reset the board\n");
- reset_cpu(0);
+ restart_machine();
}
void blackfin_irq_panic(int reason, struct pt_regs *regs)
@@ -101,6 +102,6 @@ void blackfin_irq_panic(int reason, struct pt_regs *regs)
printf("Unhandled IRQ or exceptions!\n");
printf("Please reset the board \n");
- reset_cpu(0);
+ restart_machine();
}
diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c
index d3f520f60f..ed449dc8db 100644
--- a/arch/efi/efi/efi.c
+++ b/arch/efi/efi/efi.c
@@ -24,6 +24,7 @@
#include <command.h>
#include <magicvar.h>
#include <init.h>
+#include <restart.h>
#include <driver.h>
#include <ns16550.h>
#include <io.h>
@@ -273,13 +274,21 @@ static int efi_console_init(void)
}
console_initcall(efi_console_init);
-void reset_cpu(unsigned long addr)
+static void __noreturn efi_restart_system(struct restart_handler *rst)
{
RT->reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, NULL);
- while(1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(efi_restart_system);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
+
extern char image_base[];
extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
__barebox_initcalls_end[];
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 0e03aa9bcb..84f72f5ac0 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -5,6 +5,7 @@
#include <fs.h>
#include <errno.h>
#include <binfmt.h>
+#include <restart.h>
#include <asm/byteorder.h>
@@ -20,7 +21,7 @@ static int do_bootm_barebox(struct image_data *data)
barebox();
- reset_cpu(0);
+ restart_machine();
}
static struct image_handler barebox_handler = {
diff --git a/arch/mips/mach-ar231x/ar231x_reset.c b/arch/mips/mach-ar231x/ar231x_reset.c
index 0788add164..318f772108 100644
--- a/arch/mips/mach-ar231x/ar231x_reset.c
+++ b/arch/mips/mach-ar231x/ar231x_reset.c
@@ -10,6 +10,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <restart.h>
#include <linux/err.h>
#include <mach/ar2312_regs.h>
@@ -17,16 +18,16 @@
static void __iomem *reset_base;
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn ar2312x_restart_soc(struct restart_handler *rst)
{
printf("reseting cpu\n");
__raw_writel(0x10000,
(char *)KSEG1ADDR(AR2312_WD_TIMER));
__raw_writel(AR2312_WD_CTRL_RESET,
(char *)KSEG1ADDR(AR2312_WD_CTRL));
- unreachable();
+
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
static u32 ar231x_reset_readl(void)
{
@@ -69,6 +70,7 @@ static struct driver_d ar231x_reset_driver = {
static int ar231x_reset_init(void)
{
+ restart_handler_register_fn(ar2312x_restart_soc);
return platform_driver_register(&ar231x_reset_driver);
}
coredevice_initcall(ar231x_reset_init);
diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
index a0e9b349ca..0665788227 100644
--- a/arch/mips/mach-ath79/reset.c
+++ b/arch/mips/mach-ath79/reset.c
@@ -16,9 +16,11 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <mach/ath79.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn ath79_restart_soc(struct restart_handler *rst)
{
ath79_reset_wr(AR933X_RESET_REG_RESET_MODULE, AR71XX_RESET_FULL_CHIP);
/*
@@ -26,7 +28,14 @@ void __noreturn reset_cpu(ulong addr)
* pulling the reset pin. The system will reboot with PLL disabled.
* Always zero when read.
*/
- unreachable();
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(ath79_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/mips/mach-bcm47xx/reset.c b/arch/mips/mach-bcm47xx/reset.c
index 00aee190fe..6287adb374 100644
--- a/arch/mips/mach-bcm47xx/reset.c
+++ b/arch/mips/mach-bcm47xx/reset.c
@@ -17,12 +17,22 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/hardware.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn bcm47xx_restart_soc(struct restart_handler *rst)
{
__raw_writel(GORESET, (char *)SOFTRES_REG);
- while (1);
+
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(bcm47xx_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/mips/mach-loongson/loongson1_reset.c b/arch/mips/mach-loongson/loongson1_reset.c
index 8975392ca6..7a8f1d6836 100644
--- a/arch/mips/mach-loongson/loongson1_reset.c
+++ b/arch/mips/mach-loongson/loongson1_reset.c
@@ -14,14 +14,23 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/loongson1.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn longhorn_restart_soc(struct restart_handler *rst)
{
__raw_writel(0x1, LS1X_WDT_EN);
__raw_writel(0x1, LS1X_WDT_SET);
__raw_writel(0x1, LS1X_WDT_TIMER);
- unreachable();
+ hang();
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(longhorn_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/mips/mach-malta/reset.c b/arch/mips/mach-malta/reset.c
index f1dc68afb5..ff29cd5e9b 100644
--- a/arch/mips/mach-malta/reset.c
+++ b/arch/mips/mach-malta/reset.c
@@ -22,12 +22,22 @@
#include <common.h>
#include <io.h>
+#include <init.h>
+#include <restart.h>
#include <mach/hardware.h>
-void __noreturn reset_cpu(ulong addr)
+static void __noreturn malta_restart_soc(struct restart_handler *rst)
{
__raw_writel(GORESET, (char *)SOFTRES_REG);
- while (1);
+
+ hang();
/*NOTREACHED*/
}
-EXPORT_SYMBOL(reset_cpu);
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(malta_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/nios2/cpu/cpu.c b/arch/nios2/cpu/cpu.c
index fdbe9f9dad..b2164af812 100644
--- a/arch/nios2/cpu/cpu.c
+++ b/arch/nios2/cpu/cpu.c
@@ -18,14 +18,22 @@
*/
#include <common.h>
+#include <init.h>
+#include <restart.h>
#include <asm/system.h>
-void __noreturn reset_cpu(ulong ignored)
+static void __noreturn nios2_restart_soc(struct restart_handler *rst)
{
/* indirect call to go beyond 256MB limitation of toolchain */
nios2_callr(RESET_ADDR);
/* Not reached */
- while (1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(nios2_restart_soc);
+}
+coredevice_initcall(restart_register_feature);
+
diff --git a/arch/openrisc/cpu/cpu.c b/arch/openrisc/cpu/cpu.c
index d73a418f93..d52b021029 100644
--- a/arch/openrisc/cpu/cpu.c
+++ b/arch/openrisc/cpu/cpu.c
@@ -19,6 +19,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <asm/system.h>
#include <asm/openrisc_exc.h>
@@ -29,11 +30,17 @@ int cleanup_before_linux(void)
extern void __reset(void);
-void __noreturn reset_cpu(ulong ignored)
+static void __noreturn openrisc_restart_cpu(struct restart_handler *rst)
{
__reset();
/* not reached, __reset does not return */
/* Not reached */
- while (1);
+ hang();
}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(openrisc_restart_cpu, NULL, RESET_SCOPE_CPU);
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index e25efecd43..409c0cf261 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -10,6 +10,7 @@
#include <asm/processor.h>
#include <boot.h>
#include <errno.h>
+#include <restart.h>
#include <fs.h>
static int bootm_relocate_fdt(void *addr, struct image_data *data)
@@ -87,7 +88,7 @@ static int do_bootm_linux(struct image_data *data)
*/
kernel(data->oftree, kernel, 0, 0, 0);
- reset_cpu(0);
+ restart_machine();
error:
return -1;
diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c
index 3f826e4994..33835e7060 100644
--- a/arch/ppc/mach-mpc5xxx/cpu.c
+++ b/arch/ppc/mach-mpc5xxx/cpu.c
@@ -31,6 +31,7 @@
#include <types.h>
#include <errno.h>
#include <of.h>
+#include <restart.h>
#include <mach/clock.h>
int checkcpu (void)
@@ -59,7 +60,7 @@ int checkcpu (void)
/* ------------------------------------------------------------------------- */
-void __noreturn reset_cpu (unsigned long addr)
+static void __noreturn mpc5xxx_restart_soc(struct restart_handler *rst)
{
ulong msr;
/* Interrupts and MMU off */
@@ -71,9 +72,15 @@ void __noreturn reset_cpu (unsigned long addr)
/* Charge the watchdog timer */
*(vu_long *)(MPC5XXX_GPT0_COUNTER) = 0x0001000f;
*(vu_long *)(MPC5XXX_GPT0_ENABLE) = 0x9004; /* wden|ce|timer_ms */
- while(1);
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(mpc5xxx_restart_soc);
+}
+coredevice_initcall(restart_register_feature);
+
/* ------------------------------------------------------------------------- */
#ifdef CONFIG_OFTREE
diff --git a/arch/ppc/mach-mpc85xx/cpu.c b/arch/ppc/mach-mpc85xx/cpu.c
index 7c183c1b5e..42464e810c 100644
--- a/arch/ppc/mach-mpc85xx/cpu.c
+++ b/arch/ppc/mach-mpc85xx/cpu.c
@@ -26,12 +26,13 @@
#include <common.h>
#include <memory.h>
#include <init.h>
+#include <restart.h>
#include <asm/fsl_ddr_sdram.h>
#include <asm-generic/memory_layout.h>
#include <mach/mmu.h>
#include <mach/immap_85xx.h>
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn mpc85xx_restart_soc(struct restart_handler *rst)
{
void __iomem *regs = (void __iomem *)MPC85xx_GUTS_ADDR;
@@ -39,10 +40,17 @@ void __noreturn reset_cpu(unsigned long addr)
out_be32(regs + MPC85xx_GUTS_RSTCR_OFFSET, 0x2); /* HRESET_REQ */
udelay(100);
- while (1)
- ;
+ hang();
}
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(mpc85xx_restart_soc);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
+
long int initdram(int board_type)
{
phys_size_t dram_size = 0;
diff --git a/arch/sandbox/board/Makefile b/arch/sandbox/board/Makefile
index 460116332d..333638ced6 100644
--- a/arch/sandbox/board/Makefile
+++ b/arch/sandbox/board/Makefile
@@ -4,5 +4,6 @@ obj-y += hostfile.o
obj-y += console.o
obj-y += devices.o
obj-y += dtb.o
+obj-y += restart.o
extra-y += barebox.lds
diff --git a/arch/sandbox/board/restart.c b/arch/sandbox/board/restart.c
new file mode 100644
index 0000000000..79bf79a556
--- /dev/null
+++ b/arch/sandbox/board/restart.c
@@ -0,0 +1,17 @@
+#include <common.h>
+#include <init.h>
+#include <restart.h>
+#include <mach/linux.h>
+
+static void sandbox_restart_cpu(struct restart_handler *restart)
+{
+ linux_exit();
+}
+
+static int restart_register_feature(void)
+{
+ restart_handler_register_fn(sandbox_restart_cpu);
+
+ return 0;
+}
+coredevice_initcall(restart_register_feature);
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index 990173e10b..1e53f69ad7 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -15,6 +15,7 @@ int linux_read_nonblock(int fd, void *buf, size_t count);
ssize_t linux_write(int fd, const void *buf, size_t count);
off_t linux_lseek(int fildes, off_t offset);
int linux_tstc(int fd);
+void __attribute__((noreturn)) linux_exit(void);
int linux_execve(const char * filename, char *const argv[], char *const envp[]);
diff --git a/arch/sandbox/os/common.c b/arch/sandbox/os/common.c
index d627391890..67667d40da 100644
--- a/arch/sandbox/os/common.c
+++ b/arch/sandbox/os/common.c
@@ -115,7 +115,7 @@ uint64_t linux_get_time(void)
return now;
}
-void __attribute__((noreturn)) reset_cpu(unsigned long addr)
+void __attribute__((noreturn)) linux_exit(void)
{
cookmode();
exit(0);
@@ -133,7 +133,7 @@ int linux_read(int fd, void *buf, size_t count)
if (ret == 0) {
printf("read on fd %d returned 0, device gone? - exiting\n", fd);
- reset_cpu(0);
+ linux_exit();
} else if (ret == -1) {
if (errno == EAGAIN)
return -errno;
@@ -141,7 +141,7 @@ int linux_read(int fd, void *buf, size_t count)
continue;
else {
printf("read on fd %d returned -1, errno %d - exiting\n", fd, errno);
- reset_cpu(0);
+ linux_exit();
}
}
} while (ret <= 0);
diff --git a/arch/x86/mach-i386/Makefile b/arch/x86/mach-i386/Makefile
index e46aa5b5ee..225b4811c5 100644
--- a/arch/x86/mach-i386/Makefile
+++ b/arch/x86/mach-i386/Makefile
@@ -1,4 +1,2 @@
-obj-y += reset.o
-
# reference clocksource
obj-y += pit_timer.o
diff --git a/arch/x86/mach-i386/reset.c b/arch/x86/mach-i386/reset.c
deleted file mode 100644
index 65f7d35537..0000000000
--- a/arch/x86/mach-i386/reset.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 Juergen Beisert, Pengutronix
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *
- */
-
-/**
- * @file
- * @brief Resetting an x86 CPU
- */
-
-#include <common.h>
-
-void __noreturn reset_cpu(unsigned long addr)
-{
- /** How to reset the machine? */
- while(1)
- ;
-}
-EXPORT_SYMBOL(reset_cpu);
diff --git a/commands/reset.c b/commands/reset.c
index 4f42b91e0f..830048049a 100644
--- a/commands/reset.c
+++ b/commands/reset.c
@@ -21,6 +21,7 @@
#include <command.h>
#include <complete.h>
#include <getopt.h>
+#include <restart.h>
static int cmd_reset(int argc, char *argv[])
{
@@ -39,7 +40,7 @@ static int cmd_reset(int argc, char *argv[])
if (shutdown_flag)
shutdown_barebox();
- reset_cpu(0);
+ restart_machine();
/* Not reached */
return 1;
diff --git a/common/Makefile b/common/Makefile
index ed131c8c56..1e7a08190c 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -8,6 +8,7 @@ obj-y += misc.o
obj-pbl-y += memsize.o
obj-y += resource.o
obj-y += bootsource.o
+obj-y += restart.o
obj-$(CONFIG_AUTO_COMPLETE) += complete.o
obj-$(CONFIG_BANNER) += version.o
obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o
diff --git a/common/misc.c b/common/misc.c
index 6da71c7ab7..5532349e43 100644
--- a/common/misc.c
+++ b/common/misc.c
@@ -24,6 +24,7 @@
#include <environment.h>
#include <led.h>
#include <of.h>
+#include <restart.h>
int errno;
EXPORT_SYMBOL(errno);
@@ -206,7 +207,7 @@ void __noreturn panic(const char *fmt, ...)
hang();
} else {
udelay(100000); /* allow messages to go out */
- reset_cpu(0);
+ restart_machine();
}
}
EXPORT_SYMBOL(panic);
diff --git a/common/reset_source.c b/common/reset_source.c
index 80002a93e6..0a69f90a6e 100644
--- a/common/reset_source.c
+++ b/common/reset_source.c
@@ -11,6 +11,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "reset-source: " fmt
#include <common.h>
#include <init.h>
@@ -30,6 +31,7 @@ static const char * const reset_src_names[] = {
};
static enum reset_src_type reset_source;
+static unsigned int reset_source_priority;
enum reset_src_type reset_source_get(void)
{
@@ -37,20 +39,41 @@ enum reset_src_type reset_source_get(void)
}
EXPORT_SYMBOL(reset_source_get);
-void reset_source_set(enum reset_src_type st)
+void reset_source_set_priority(enum reset_src_type st, unsigned int priority)
{
+ if (priority <= reset_source_priority)
+ return;
+
reset_source = st;
+ reset_source_priority = priority;
- globalvar_add_simple("system.reset", reset_src_names[reset_source]);
+ pr_debug("Setting reset source to %s with priority %d\n",
+ reset_src_names[reset_source], priority);
}
EXPORT_SYMBOL(reset_source_set);
-/* ensure this runs after the 'global' device is already registerd */
static int reset_source_init(void)
{
- reset_source_set(reset_source);
+ globalvar_add_simple_enum("system.reset", (unsigned int *)&reset_source,
+ reset_src_names, ARRAY_SIZE(reset_src_names));
return 0;
}
coredevice_initcall(reset_source_init);
+
+/**
+ * of_get_reset_source_priority() - get the desired reset source priority from
+ * device tree
+ * @node: The device_node to read the property from
+ *
+ * return: The priority
+ */
+unsigned int of_get_reset_source_priority(struct device_node *node)
+{
+ unsigned int priority = RESET_SOURCE_DEFAULT_PRIORITY;
+
+ of_property_read_u32(node, "reset-source-priority", &priority);
+
+ return priority;
+}
diff --git a/common/restart.c b/common/restart.c
new file mode 100644
index 0000000000..8fd5ffd1a2
--- /dev/null
+++ b/common/restart.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(fmt) "restart: " fmt
+
+#include <common.h>
+#include <restart.h>
+#include <malloc.h>
+#include <of.h>
+
+static LIST_HEAD(restart_handler_list);
+
+/**
+ * restart_handler_register() - register a handler for restarting the system
+ * @rst: The handler struct
+ *
+ * This adds @rst to the list of registered restart handlers.
+ *
+ * return: 0 for success or negative error code
+ */
+int restart_handler_register(struct restart_handler *rst)
+{
+ if (!rst->name)
+ rst->name = RESTART_DEFAULT_NAME;
+ if (!rst->priority)
+ rst->priority = RESTART_DEFAULT_PRIORITY;
+
+ list_add_tail(&rst->list, &restart_handler_list);
+
+ pr_debug("registering restart handler \"%s\" with priority %d\n",
+ rst->name, rst->priority);
+
+ return 0;
+}
+
+/**
+ * restart_handler_register_fn() - register a handler function
+ * @restart_fn: The restart function
+ *
+ * convenience wrapper for restart_handler_register() to register a handler
+ * with given function and default values otherwise.
+ *
+ * return: 0 for success or negative error code
+ */
+int restart_handler_register_fn(void (*restart_fn)(struct restart_handler *))
+{
+ struct restart_handler *rst;
+ int ret;
+
+ rst = xzalloc(sizeof(*rst));
+
+ rst->restart = restart_fn;
+
+ ret = restart_handler_register(rst);
+
+ if (ret)
+ free(rst);
+
+ return ret;
+}
+
+/**
+ * restart_machine() - reset the whole system
+ */
+void __noreturn restart_machine(void)
+{
+ struct restart_handler *rst = NULL, *tmp;
+ unsigned int priority = 0;
+
+ list_for_each_entry(tmp, &restart_handler_list, list) {
+ if (tmp->priority > priority) {
+ priority = tmp->priority;
+ rst = tmp;
+ }
+ }
+
+ if (rst) {
+ pr_debug("%s: using restart handler %s\n", __func__, rst->name);
+ console_flush();
+ rst->restart(rst);
+ }
+
+ hang();
+}
+
+/**
+ * of_get_restart_priority() - get the desired restart priority from device tree
+ * @node: The device_node to read the property from
+ *
+ * return: The priority
+ */
+unsigned int of_get_restart_priority(struct device_node *node)
+{
+ unsigned int priority = RESTART_DEFAULT_PRIORITY;
+
+ of_property_read_u32(node, "restart-priority", &priority);
+
+ return priority;
+}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3af904dd6d..417c9ce96c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -4,6 +4,17 @@ config MFD_ACT8846
depends on I2C
bool "ACT8846 driver"
+config MFD_DA9053
+ depends on I2C
+ bool "DA9053 PMIC driver"
+ help
+ This power management controller provides configurable power supplies,
+ a machine restart feature and a watchdog.
+
+config MFD_DA9063
+ depends on I2C
+ bool "DA9063 PMIC driver"
+
config MFD_LP3972
depends on I2C
bool "LP3972 driver"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 49b9e35663..041915a7c6 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -1,4 +1,6 @@
obj-$(CONFIG_MFD_ACT8846) += act8846.o
+obj-$(CONFIG_MFD_DA9053) += da9053.o
+obj-$(CONFIG_MFD_DA9063) += da9063.o
obj-$(CONFIG_MFD_LP3972) += lp3972.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx.o
obj-$(CONFIG_MFD_MC34704) += mc34704.o
diff --git a/drivers/mfd/da9053.c b/drivers/mfd/da9053.c
new file mode 100644
index 0000000000..3fb5295cf9
--- /dev/null
+++ b/drivers/mfd/da9053.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2013 Jan Luebbe <jlu@pengutronix.de>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <reset_source.h>
+
+#include <i2c/i2c.h>
+#include <restart.h>
+
+#define DRIVERNAME "da9053"
+
+/* STATUS REGISTERS */
+#define DA9053_STATUS_A_REG 1
+#define DA9053_STATUS_B_REG 2
+#define DA9053_STATUS_C_REG 3
+#define DA9053_STATUS_D_REG 4
+
+/* PARK REGISTER */
+#define DA9053_PARK_REGISTER DA9053_STATUS_D_REG
+
+/* EVENT REGISTERS */
+#define DA9053_EVENT_A_REG 5
+#define DA9053_EVENT_B_REG 6
+#define DA9053_EVENT_C_REG 7
+#define DA9053_EVENT_D_REG 8
+#define DA9053_FAULTLOG_REG 9
+
+/* IRQ REGISTERS */
+#define DA9053_IRQ_MASK_A_REG 10
+#define DA9053_IRQ_MASK_B_REG 11
+#define DA9053_IRQ_MASK_C_REG 12
+#define DA9053_IRQ_MASK_D_REG 13
+
+/* CONTROL REGISTERS */
+#define DA9053_CONTROL_A_REG 14
+#define DA9053_CONTROL_B_REG 15
+#define DA9053_CONTROL_C_REG 16
+#define DA9053_CONTROL_D_REG 17
+
+#define DA9053_PDDIS_REG 18
+#define DA9053_INTERFACE_REG 19
+#define DA9053_RESET_REG 20
+
+/* FAULT LOG REGISTER BITS */
+#define DA9053_FAULTLOG_WAITSET 0X80
+#define DA9053_FAULTLOG_NSDSET 0X40
+#define DA9053_FAULTLOG_KEYSHUT 0X20
+#define DA9053_FAULTLOG_TEMPOVER 0X08
+#define DA9053_FAULTLOG_VDDSTART 0X04
+#define DA9053_FAULTLOG_VDDFAULT 0X02
+#define DA9053_FAULTLOG_TWDERROR 0X01
+
+/* CONTROL REGISTER B BITS */
+#define DA9053_CONTROLB_SHUTDOWN 0X80
+#define DA9053_CONTROLB_DEEPSLEEP 0X40
+#define DA9053_CONTROLB_WRITEMODE 0X20
+#define DA9053_CONTROLB_BBATEN 0X10
+#define DA9053_CONTROLB_OTPREADEN 0X08
+#define DA9053_CONTROLB_AUTOBOOT 0X04
+#define DA9053_CONTROLB_ACTDIODE 0X02
+#define DA9053_CONTROLB_BUCKMERGE 0X01
+
+/* CONTROL REGISTER D BITS */
+#define DA9053_CONTROLD_WATCHDOG 0X80
+#define DA9053_CONTROLD_ACCDETEN 0X40
+#define DA9053_CONTROLD_GPI1415SD 0X20
+#define DA9053_CONTROLD_NONKEYSD 0X10
+#define DA9053_CONTROLD_KEEPACTEN 0X08
+#define DA9053_CONTROLD_TWDSCALE 0X07
+
+struct da9053_priv {
+ struct watchdog wd;
+ struct i2c_client *client;
+ struct device_d *dev;
+ struct restart_handler restart;
+};
+
+#define wd_to_da9053_priv(x) container_of(x, struct da9053_priv, wd)
+
+static int da9053_reg_read(struct da9053_priv *da9053, u32 reg, u8 *val)
+{
+ int ret;
+
+ ret = i2c_read_reg(da9053->client, reg, val, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+
+static int da9053_reg_write(struct da9053_priv *da9053, u32 reg, u8 val)
+{
+ int ret;
+
+ ret = i2c_write_reg(da9053->client, reg, &val, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+
+static int da9053_park(struct da9053_priv *da9053)
+{
+ int ret;
+ u8 val;
+
+ ret = i2c_read_reg(da9053->client, DA9053_PARK_REGISTER, &val, 1);
+
+ return ret == 1 ? 0 : ret;
+}
+
+static int da9053_enable_multiwrite(struct da9053_priv *da9053)
+{
+ int ret;
+ u8 val;
+
+ ret = da9053_reg_read(da9053, DA9053_CONTROL_B_REG, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val & DA9053_CONTROLB_WRITEMODE) {
+ val &= ~DA9053_CONTROLB_WRITEMODE;
+ ret = da9053_reg_write(da9053, DA9053_CONTROL_B_REG, val);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = da9053_park(da9053);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int da9053_set_timeout(struct watchdog *wd, unsigned timeout)
+{
+ struct da9053_priv *da9053 = wd_to_da9053_priv(wd);
+ struct device_d *dev = da9053->cdev.dev;
+ unsigned scale = 0;
+ int ret;
+ u8 val;
+
+ if (timeout > 131)
+ return -EINVAL;
+
+ if (timeout) {
+ timeout *= 1000; /* convert to ms */
+ scale = 0;
+ while (timeout > (2048 << scale) && scale <= 6)
+ scale++;
+ dev_dbg(dev, "calculated TWDSCALE=%u (req=%ims calc=%ims)\n",
+ scale, timeout, 2048 << scale);
+ scale++; /* scale 0 disables the WD */
+ }
+
+ ret = da9053_reg_read(da9053, DA9053_CONTROL_D_REG, &val);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dev, "read watchdog (val=0x%02x)\n", val);
+
+ if (scale && scale == (val & DA9053_CONTROLD_TWDSCALE)) {
+ /* trigger WD */
+ val |= DA9053_CONTROLD_WATCHDOG;
+ ret = da9053_reg_write(da9053, DA9053_CONTROL_D_REG, val);
+ if (ret < 0)
+ return ret;
+ dev_dbg(dev, "triggered watchdog (val=0x%02x)\n", val);
+ } else {
+ /* disable WD first */
+ val &= ~DA9053_CONTROLD_TWDSCALE;
+ ret = da9053_reg_write(da9053, DA9053_CONTROL_D_REG, val);
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(dev, "disabled watchdog (val=0x%02x)\n", val);
+ if (scale) {
+ /* park before waiting */
+ ret = da9053_park(da9053);
+ if (ret < 0)
+ return ret;
+
+ /* wait required time */
+ udelay(150);
+
+ /* enable WD with new timeout */
+ val |= scale;
+ ret = da9053_reg_write(da9053, DA9053_CONTROL_D_REG, val);
+ if (ret < 0)
+ return ret;
+ dev_dbg(dev, "enabled watchdog (val=0x%02x)\n", val);
+ }
+ }
+
+ ret = da9053_park(da9053);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void da9053_detect_reset_source(struct da9053_priv *da9053)
+{
+ unsigned int priority;
+ enum reset_src_type type;
+ int ret;
+ u8 val;
+
+ ret = da9053_reg_read(da9053, DA9053_FAULTLOG_REG, &val);
+ if (ret < 0)
+ return;
+
+ ret = da9053_park(da9053);
+ if (ret < 0)
+ return;
+
+ if (val & DA9053_FAULTLOG_TWDERROR)
+ type = RESET_WDG;
+ else if (val & DA9053_FAULTLOG_VDDFAULT)
+ type = RESET_POR;
+ else if (val & DA9053_FAULTLOG_NSDSET)
+ type = RESET_RST;
+ else
+ return;
+
+ priority = of_get_reset_source_priority(da9053->dev->device_node);
+
+ reset_source_set_priority(type, priority);
+}
+
+static void __noreturn da9053_force_system_reset(struct restart_handler *rst)
+{
+ struct da9053_priv *da9053 = container_of(rst, struct da9053_priv, restart);
+ u8 val;
+ int ret;
+
+ ret = da9053_reg_read(da9053, DA9053_CONTROL_B_REG, &val);
+ if (ret < 0)
+ hang();
+
+ val |= DA9053_CONTROLB_SHUTDOWN;
+ ret = da9053_reg_write(da9053, DA9053_CONTROL_B_REG, val);
+ if (ret < 0)
+ hang();
+
+ da9053_park(da9053);
+
+ hang();
+}
+
+static int da9053_probe(struct device_d *dev)
+{
+ struct da9053_priv *da9053;
+ int ret;
+
+ da9053 = xzalloc(sizeof(*da9053));
+ da9053->dev = dev;
+ da9053->cdev.name = DRIVERNAME;
+ da9053->client = to_i2c_client(dev);
+ da9053->wd.set_timeout = da9053_set_timeout;
+ da9053->wd.priority = of_get_watchdog_priority(dev->device_node);
+ da9053->wd.dev = dev;
+
+ ret = da9053_enable_multiwrite(da9053);
+ if (ret < 0)
+ return ret;
+
+ ret = watchdog_register(&da9053->wd);
+ if (ret)
+ return ret;
+
+ da9053_detect_reset_source(da9053);
+
+ da9053->restart.priority = of_get_restart_priority(dev->device_node);
+ da9053->restart.name = "da9063";
+ da9053->restart.restart = &da9053_force_system_reset;
+
+ restart_handler_register(&da9053->restart);
+
+ return 0;
+}
+
+static struct driver_d da9053_driver = {
+ .name = DRIVERNAME,
+ .probe = da9053_probe,
+};
+
+static int da9053_init(void)
+{
+ i2c_driver_register(&da9053_driver);
+ return 0;
+}
+
+device_initcall(da9053_init);
diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c
new file mode 100644
index 0000000000..4a335c9983
--- /dev/null
+++ b/drivers/mfd/da9063.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2015 Pengutronix, Philipp Zabel <p.zabel@pengutronix.de>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <restart.h>
+#include <init.h>
+#include <i2c/i2c.h>
+#include <malloc.h>
+#include <notifier.h>
+#include <reset_source.h>
+#include <watchdog.h>
+
+struct da9063 {
+ struct restart_handler restart;
+ struct watchdog wd;
+ struct i2c_client *client;
+ struct device_d *dev;
+};
+
+/* System Control and Event Registers */
+#define DA9063_REG_FAULT_LOG 0x05
+#define DA9063_REG_CONTROL_D 0x11
+#define DA9063_REG_CONTROL_F 0x13
+
+/* DA9063_REG_FAULT_LOG (addr=0x05) */
+#define DA9063_TWD_ERROR 0x01
+#define DA9063_POR 0x02
+#define DA9063_NSHUTDOWN 0x40
+
+/* DA9063_REG_CONTROL_D (addr=0x11) */
+#define DA9063_TWDSCALE_MASK 0x07
+
+/* DA9063_REG_CONTROL_F (addr=0x13) */
+#define DA9063_SHUTDOWN 0x02
+
+static int da9063_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
+{
+ struct da9063 *priv = container_of(wd, struct da9063, wd);
+ struct device_d *dev = priv->dev;
+ unsigned int scale = 0;
+ int ret;
+ u8 val;
+
+ if (timeout > 131)
+ return -EINVAL;
+
+ if (timeout) {
+ timeout *= 1000; /* convert to ms */
+ scale = 0;
+ while (timeout > (2048 << scale) && scale <= 6)
+ scale++;
+ dev_dbg(dev, "calculated TWDSCALE=%u (req=%ims calc=%ims)\n",
+ scale, timeout, 2048 << scale);
+ scale++; /* scale 0 disables the WD */
+ }
+
+ ret = i2c_read_reg(priv->client, DA9063_REG_CONTROL_D, &val, 1);
+ if (ret < 0)
+ return ret;
+
+ val &= ~DA9063_TWDSCALE_MASK;
+ val |= scale;
+
+ ret = i2c_write_reg(priv->client, DA9063_REG_CONTROL_D, &val, 1);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void da9063_detect_reset_source(struct da9063 *priv)
+{
+ int ret;
+ u8 val;
+ unsigned int priority;
+ enum reset_src_type type;
+
+ ret = i2c_read_reg(priv->client, DA9063_REG_FAULT_LOG, &val, 1);
+ if (ret < 0)
+ return;
+
+ /* Write one to clear */
+ i2c_write_reg(priv->client, DA9063_REG_FAULT_LOG, &val, 1);
+
+ if (val & DA9063_TWD_ERROR)
+ type = RESET_WDG;
+ else if (val & DA9063_POR)
+ type = RESET_POR;
+ else if (val & DA9063_NSHUTDOWN)
+ type = RESET_RST;
+ else
+ return;
+
+ priority = of_get_reset_source_priority(priv->dev->device_node);
+
+ reset_source_set_priority(type, priority);
+}
+
+static void da9063_restart(struct restart_handler *rst)
+{
+ struct da9063 *priv = container_of(rst, struct da9063, restart);
+
+ u8 val = DA9063_SHUTDOWN;
+
+ i2c_write_reg(priv->client, DA9063_REG_CONTROL_F, &val, 1);
+}
+
+static int da9063_probe(struct device_d *dev)
+{
+ struct da9063 *priv = NULL;
+ int ret;
+
+ priv = xzalloc(sizeof(struct da9063));
+ priv->wd.priority = of_get_watchdog_priority(dev->device_node);
+ priv->wd.set_timeout = da9063_watchdog_set_timeout;
+ priv->wd.dev = dev;
+ priv->client = to_i2c_client(dev);
+ priv->dev = dev;
+
+ ret = watchdog_register(&priv->wd);
+ if (ret)
+ goto on_error;
+
+ da9063_detect_reset_source(priv);
+
+ priv->restart.priority = of_get_restart_priority(dev->device_node);
+ priv->restart.name = "da9063";
+ priv->restart.restart = &da9063_restart;
+
+ restart_handler_register(&priv->restart);
+
+ return 0;
+
+on_error:
+ if (priv)
+ free(priv);
+ return ret;
+}
+
+static struct platform_device_id da9063_id[] = {
+ { "da9063", },
+ { }
+};
+
+static struct driver_d da9063_driver = {
+ .name = "da9063",
+ .probe = da9063_probe,
+ .id_table = da9063_id,
+};
+
+static int da9063_init(void)
+{
+ return i2c_driver_register(&da9063_driver);
+}
+
+device_initcall(da9063_init);
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 76879db1f1..bf28f7c22a 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -31,6 +31,7 @@
#include <progress.h>
#include <environment.h>
#include <globalvar.h>
+#include <restart.h>
#include <usb/ch9.h>
#include <usb/gadget.h>
#include <usb/fastboot.h>
@@ -520,7 +521,7 @@ static int fastboot_tx_print(struct f_fastboot *f_fb, const char *fmt, ...)
static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
{
- reset_cpu(0);
+ restart_machine();
}
static void cb_reboot(struct usb_ep *ep, struct usb_request *req, const char *cmd)
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index ecf6e89b47..dfabee230c 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -147,6 +147,7 @@ static int davinci_wdt_probe(struct device_d *dev)
clk_enable(davinci_wdt->clk);
davinci_wdt->wd.set_timeout = davinci_wdt_set_timeout;
+ davinci_wdt->wd.dev = dev;
ret = watchdog_register(&davinci_wdt->wd);
if (ret < 0)
diff --git a/drivers/watchdog/im28wd.c b/drivers/watchdog/im28wd.c
index a9093a7b51..3510776a3a 100644
--- a/drivers/watchdog/im28wd.c
+++ b/drivers/watchdog/im28wd.c
@@ -197,6 +197,7 @@ static int imx28_wd_probe(struct device_d *dev)
if (IS_ERR(priv->regs))
return PTR_ERR(priv->regs);
priv->wd.set_timeout = imx28_watchdog_set_timeout;
+ priv->wd.dev = dev;
if (!(readl(priv->regs + MXS_RTC_STAT) & MXS_RTC_STAT_WD_PRESENT)) {
rc = -ENODEV;
diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c
index 5ffbac7cdd..dd11a62613 100644
--- a/drivers/watchdog/imxwd.c
+++ b/drivers/watchdog/imxwd.c
@@ -18,6 +18,7 @@
#include <of.h>
#include <errno.h>
#include <malloc.h>
+#include <restart.h>
#include <watchdog.h>
#include <reset_source.h>
@@ -33,6 +34,7 @@ struct imx_wd {
void __iomem *base;
struct device_d *dev;
const struct imx_wd_ops *ops;
+ struct restart_handler restart;
};
#define to_imx_wd(h) container_of(h, struct imx_wd, wd)
@@ -121,12 +123,11 @@ static int imx_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
return priv->ops->set_timeout(priv, timeout);
}
-static struct imx_wd *reset_wd;
-
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn imxwd_force_soc_reset(struct restart_handler *rst)
{
- if (reset_wd)
- reset_wd->ops->set_timeout(reset_wd, -1);
+ struct imx_wd *priv = container_of(rst, struct imx_wd, restart);
+
+ priv->ops->set_timeout(priv, -1);
mdelay(1000);
@@ -185,11 +186,9 @@ static int imx_wd_probe(struct device_d *dev)
}
priv->ops = ops;
priv->wd.set_timeout = imx_watchdog_set_timeout;
+ priv->wd.dev = dev;
priv->dev = dev;
- if (!reset_wd)
- reset_wd = priv;
-
if (IS_ENABLED(CONFIG_WATCHDOG_IMX)) {
ret = watchdog_register(&priv->wd);
if (ret)
@@ -206,28 +205,21 @@ static int imx_wd_probe(struct device_d *dev)
dev->priv = priv;
+ priv->restart.name = "imxwd";
+ priv->restart.restart = imxwd_force_soc_reset;
+
+ restart_handler_register(&priv->restart);
+
return 0;
error_unregister:
if (IS_ENABLED(CONFIG_WATCHDOG_IMX))
watchdog_deregister(&priv->wd);
on_error:
- if (reset_wd && reset_wd != priv)
- free(priv);
+ free(priv);
return ret;
}
-static void imx_wd_remove(struct device_d *dev)
-{
- struct imx_wd *priv = dev->priv;
-
- if (IS_ENABLED(CONFIG_WATCHDOG_IMX))
- watchdog_deregister(&priv->wd);
-
- if (reset_wd && reset_wd != priv)
- free(priv);
-}
-
static const struct imx_wd_ops imx21_wd_ops = {
.set_timeout = imx21_watchdog_set_timeout,
.init = imx21_wd_init,
@@ -264,7 +256,6 @@ static struct platform_device_id imx_wdt_ids[] = {
static struct driver_d imx_wd_driver = {
.name = "imx-watchdog",
.probe = imx_wd_probe,
- .remove = imx_wd_remove,
.of_compatible = DRV_OF_COMPAT(imx_wdt_dt_ids),
.id_table = imx_wdt_ids,
};
diff --git a/drivers/watchdog/jz4740.c b/drivers/watchdog/jz4740.c
index 8ac51e060a..3d45b46ee2 100644
--- a/drivers/watchdog/jz4740.c
+++ b/drivers/watchdog/jz4740.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <init.h>
+#include <restart.h>
#include <io.h>
#define JZ_REG_WDT_TIMER_DATA 0x0
@@ -39,33 +40,30 @@
#define JZ_EXTAL 24000000
struct jz4740_wdt_drvdata {
+ struct restart_handler restart;
void __iomem *base;
};
-static struct jz4740_wdt_drvdata *reset_wd;
-
-void __noreturn reset_cpu(unsigned long addr)
+static void __noreturn jz4740_reset_soc(struct restart_handler *rst)
{
- if (reset_wd) {
- void __iomem *base = reset_wd->base;
+ struct jz4740_wdt_drvdata *priv =
+ container_of(rst, struct jz4740_wdt_drvdata, restart);
+ void __iomem *base = priv->base;
- writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT,
- base + JZ_REG_WDT_TIMER_CONTROL);
- writew(0, base + JZ_REG_WDT_TIMER_COUNTER);
+ writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT,
+ base + JZ_REG_WDT_TIMER_CONTROL);
+ writew(0, base + JZ_REG_WDT_TIMER_COUNTER);
- /* reset after 4ms */
- writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA);
+ /* reset after 4ms */
+ writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA);
- /* start wdt */
- writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE);
+ /* start wdt */
+ writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE);
- mdelay(1000);
- } else
- pr_err("%s: can't reset cpu\n", __func__);
+ mdelay(1000);
hang();
}
-EXPORT_SYMBOL(reset_cpu);
static int jz4740_wdt_probe(struct device_d *dev)
{
@@ -78,11 +76,12 @@ static int jz4740_wdt_probe(struct device_d *dev)
return -ENODEV;
}
- if (!reset_wd)
- reset_wd = priv;
-
dev->priv = priv;
+ priv->restart.name = "jz4740-wdt";
+ priv->restart.restart = jz4740_reset_soc;
+ restart_handler_register(&priv->restart);
+
return 0;
}
diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c
index 3d0cfc635d..3a3f519648 100644
--- a/drivers/watchdog/wd_core.c
+++ b/drivers/watchdog/wd_core.c
@@ -11,6 +11,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "watchdog: " fmt
#include <common.h>
#include <command.h>
@@ -18,40 +19,85 @@
#include <linux/ctype.h>
#include <watchdog.h>
-/*
- * Note: this simple framework supports one watchdog only.
- */
-static struct watchdog *watchdog;
+static LIST_HEAD(watchdog_list);
+
+static const char *watchdog_name(struct watchdog *wd)
+{
+ if (wd->dev)
+ return dev_name(wd->dev);
+ if (wd->name)
+ return wd->name;
+
+ return "unknown";
+}
int watchdog_register(struct watchdog *wd)
{
- if (watchdog != NULL)
- return -EBUSY;
+ if (!wd->priority)
+ wd->priority = WATCHDOG_DEFAULT_PRIORITY;
+
+ list_add_tail(&wd->list, &watchdog_list);
+
+ pr_debug("registering watchdog %s with priority %d\n", watchdog_name(wd),
+ wd->priority);
- watchdog = wd;
return 0;
}
EXPORT_SYMBOL(watchdog_register);
int watchdog_deregister(struct watchdog *wd)
{
- if (watchdog == NULL || wd != watchdog)
- return -ENODEV;
+ list_del(&wd->list);
- watchdog = NULL;
return 0;
}
EXPORT_SYMBOL(watchdog_deregister);
+static struct watchdog *watchdog_get_default(void)
+{
+ struct watchdog *tmp, *wd = NULL;
+ int priority = 0;
+
+ list_for_each_entry(tmp, &watchdog_list, list) {
+ if (tmp->priority > priority) {
+ priority = tmp->priority;
+ wd = tmp;
+ }
+ }
+
+ return wd;
+}
+
/*
* start, stop or retrigger the watchdog
* timeout in [seconds]. timeout of '0' will disable the watchdog (if possible)
*/
int watchdog_set_timeout(unsigned timeout)
{
- if (watchdog == NULL)
+ struct watchdog *wd;
+
+ wd = watchdog_get_default();
+
+ if (!wd)
return -ENODEV;
- return watchdog->set_timeout(watchdog, timeout);
+ pr_debug("setting timeout on %s to %ds\n", watchdog_name(wd), timeout);
+
+ return wd->set_timeout(wd, timeout);
}
EXPORT_SYMBOL(watchdog_set_timeout);
+
+/**
+ * of_get_watchdog_priority() - get the desired watchdog priority from device tree
+ * @node: The device_node to read the property from
+ *
+ * return: The priority
+ */
+unsigned int of_get_watchdog_priority(struct device_node *node)
+{
+ unsigned int priority = WATCHDOG_DEFAULT_PRIORITY;
+
+ of_property_read_u32(node, "watchdog-priority", &priority);
+
+ return priority;
+}
diff --git a/include/common.h b/include/common.h
index 6b9dd4d799..553a7f4f44 100644
--- a/include/common.h
+++ b/include/common.h
@@ -67,7 +67,6 @@ int readline (const char *prompt, char *buf, int len);
long get_ram_size (volatile long *, long);
/* $(CPU)/cpu.c */
-void __noreturn reset_cpu(unsigned long addr);
void __noreturn poweroff(void);
/* lib_$(ARCH)/time.c */
diff --git a/include/reset_source.h b/include/reset_source.h
index 367f93b2ad..d484836dff 100644
--- a/include/reset_source.h
+++ b/include/reset_source.h
@@ -25,10 +25,11 @@ enum reset_src_type {
};
#ifdef CONFIG_RESET_SOURCE
-void reset_source_set(enum reset_src_type);
+void reset_source_set_priority(enum reset_src_type, unsigned int priority);
enum reset_src_type reset_source_get(void);
#else
-static inline void reset_source_set(enum reset_src_type unused)
+static inline void reset_source_set_priority(enum reset_src_type type,
+ unsigned int priority)
{
}
@@ -38,4 +39,13 @@ static inline enum reset_src_type reset_source_get(void)
}
#endif
+#define RESET_SOURCE_DEFAULT_PRIORITY 100
+
+static inline void reset_source_set(enum reset_src_type type)
+{
+ reset_source_set_priority(type, RESET_SOURCE_DEFAULT_PRIORITY);
+}
+
+unsigned int of_get_reset_source_priority(struct device_node *node);
+
#endif /* __INCLUDE_RESET_SOURCE_H */
diff --git a/include/restart.h b/include/restart.h
new file mode 100644
index 0000000000..79b57c8e11
--- /dev/null
+++ b/include/restart.h
@@ -0,0 +1,21 @@
+#ifndef __INCLUDE_RESTART_H
+#define __INCLUDE_RESTART_H
+
+void __noreturn restart_machine(void);
+
+struct restart_handler {
+ void (*restart)(struct restart_handler *);
+ int priority;
+ const char *name;
+ struct list_head list;
+};
+
+int restart_handler_register(struct restart_handler *);
+int restart_handler_register_fn(void (*restart_fn)(struct restart_handler *));
+
+#define RESTART_DEFAULT_PRIORITY 100
+#define RESTART_DEFAULT_NAME "default"
+
+unsigned int of_get_restart_priority(struct device_node *node);
+
+#endif /* __INCLUDE_RESTART_H */
diff --git a/include/watchdog.h b/include/watchdog.h
index 7a98ae4434..6fd896734b 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -15,6 +15,10 @@
struct watchdog {
int (*set_timeout)(struct watchdog *, unsigned);
+ const char *name;
+ struct device_d *dev;
+ unsigned int priority;
+ struct list_head list;
};
#ifdef CONFIG_WATCHDOG
@@ -38,4 +42,8 @@ static inline int watchdog_set_timeout(unsigned t)
}
#endif
+#define WATCHDOG_DEFAULT_PRIORITY 100
+
+unsigned int of_get_watchdog_priority(struct device_node *node);
+
#endif /* INCLUDE_WATCHDOG_H */