-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'sunxi-drivers-for-3.16-2' of https://github.com/mripard/linux
into next/drivers Allwinner drivers changes for 3.16, take 2 Add reset driver for the A31 * tag 'sunxi-drivers-for-3.16-2' of https://github.com/mripard/linux: power: reset: Add Allwinner A31 reset code Signed-off-by: Arnd Bergmann <arnd@arndb.de>
- Loading branch information
Showing
3 changed files
with
93 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* Allwinner A31 SoCs reset code | ||
* | ||
* Copyright (C) 2012-2014 Maxime Ripard | ||
* | ||
* Maxime Ripard <maxime.ripard@free-electrons.com> | ||
* | ||
* This file is licensed under the terms of the GNU General Public | ||
* License version 2. This program is licensed "as is" without any | ||
* warranty of any kind, whether express or implied. | ||
*/ | ||
|
||
#include <linux/delay.h> | ||
#include <linux/io.h> | ||
#include <linux/module.h> | ||
#include <linux/of_address.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/reboot.h> | ||
|
||
#include <asm/system_misc.h> | ||
|
||
#define SUN6I_WATCHDOG1_IRQ_REG 0x00 | ||
#define SUN6I_WATCHDOG1_CTRL_REG 0x10 | ||
#define SUN6I_WATCHDOG1_CTRL_RESTART BIT(0) | ||
#define SUN6I_WATCHDOG1_CONFIG_REG 0x14 | ||
#define SUN6I_WATCHDOG1_CONFIG_RESTART BIT(0) | ||
#define SUN6I_WATCHDOG1_CONFIG_IRQ BIT(1) | ||
#define SUN6I_WATCHDOG1_MODE_REG 0x18 | ||
#define SUN6I_WATCHDOG1_MODE_ENABLE BIT(0) | ||
|
||
static void __iomem *wdt_base; | ||
|
||
static void sun6i_wdt_restart(enum reboot_mode mode, const char *cmd) | ||
{ | ||
if (!wdt_base) | ||
return; | ||
|
||
/* Disable interrupts */ | ||
writel(0, wdt_base + SUN6I_WATCHDOG1_IRQ_REG); | ||
|
||
/* We want to disable the IRQ and just reset the whole system */ | ||
writel(SUN6I_WATCHDOG1_CONFIG_RESTART, | ||
wdt_base + SUN6I_WATCHDOG1_CONFIG_REG); | ||
|
||
/* Enable timer. The default and lowest interval value is 0.5s */ | ||
writel(SUN6I_WATCHDOG1_MODE_ENABLE, | ||
wdt_base + SUN6I_WATCHDOG1_MODE_REG); | ||
|
||
/* Restart the watchdog. */ | ||
writel(SUN6I_WATCHDOG1_CTRL_RESTART, | ||
wdt_base + SUN6I_WATCHDOG1_CTRL_REG); | ||
|
||
while (1) { | ||
mdelay(5); | ||
writel(SUN6I_WATCHDOG1_MODE_ENABLE, | ||
wdt_base + SUN6I_WATCHDOG1_MODE_REG); | ||
} | ||
} | ||
|
||
static int sun6i_reboot_probe(struct platform_device *pdev) | ||
{ | ||
wdt_base = of_iomap(pdev->dev.of_node, 0); | ||
if (!wdt_base) { | ||
WARN(1, "failed to map watchdog base address"); | ||
return -ENODEV; | ||
} | ||
|
||
arm_pm_restart = sun6i_wdt_restart; | ||
|
||
return 0; | ||
} | ||
|
||
static struct of_device_id sun6i_reboot_of_match[] = { | ||
{ .compatible = "allwinner,sun6i-a31-wdt" }, | ||
{} | ||
}; | ||
|
||
static struct platform_driver sun6i_reboot_driver = { | ||
.probe = sun6i_reboot_probe, | ||
.driver = { | ||
.name = "sun6i-reboot", | ||
.of_match_table = sun6i_reboot_of_match, | ||
}, | ||
}; | ||
module_platform_driver(sun6i_reboot_driver); |