| /* | |
| * Renesas R-Mobile Reset Driver | |
| * | |
| * Copyright (C) 2014 Glider bvba | |
| * | |
| * This file is subject to the terms and conditions of the GNU General Public | |
| * License. See the file "COPYING" in the main directory of this archive | |
| * for more details. | |
| */ | |
| #include <linux/io.h> | |
| #include <linux/module.h> | |
| #include <linux/notifier.h> | |
| #include <linux/of_address.h> | |
| #include <linux/platform_device.h> | |
| #include <linux/printk.h> | |
| #include <linux/reboot.h> | |
| /* SYSC Register Bank 2 */ | |
| #define RESCNT2 0x20 /* Reset Control Register 2 */ | |
| /* Reset Control Register 2 */ | |
| #define RESCNT2_PRES 0x80000000 /* Soft power-on reset */ | |
| static void __iomem *sysc_base2; | |
| static int rmobile_reset_handler(struct notifier_block *this, | |
| unsigned long mode, void *cmd) | |
| { | |
| pr_debug("%s %lu\n", __func__, mode); | |
| /* Let's assume we have acquired the HPB semaphore */ | |
| writel(RESCNT2_PRES, sysc_base2 + RESCNT2); | |
| return NOTIFY_DONE; | |
| } | |
| static struct notifier_block rmobile_reset_nb = { | |
| .notifier_call = rmobile_reset_handler, | |
| .priority = 192, | |
| }; | |
| static int rmobile_reset_probe(struct platform_device *pdev) | |
| { | |
| int error; | |
| sysc_base2 = of_iomap(pdev->dev.of_node, 1); | |
| if (!sysc_base2) | |
| return -ENODEV; | |
| error = register_restart_handler(&rmobile_reset_nb); | |
| if (error) { | |
| dev_err(&pdev->dev, | |
| "cannot register restart handler (err=%d)\n", error); | |
| goto fail_unmap; | |
| } | |
| return 0; | |
| fail_unmap: | |
| iounmap(sysc_base2); | |
| return error; | |
| } | |
| static int rmobile_reset_remove(struct platform_device *pdev) | |
| { | |
| unregister_restart_handler(&rmobile_reset_nb); | |
| iounmap(sysc_base2); | |
| return 0; | |
| } | |
| static const struct of_device_id rmobile_reset_of_match[] = { | |
| { .compatible = "renesas,sysc-rmobile", }, | |
| { /* sentinel */ } | |
| }; | |
| MODULE_DEVICE_TABLE(of, rmobile_reset_of_match); | |
| static struct platform_driver rmobile_reset_driver = { | |
| .probe = rmobile_reset_probe, | |
| .remove = rmobile_reset_remove, | |
| .driver = { | |
| .name = "rmobile_reset", | |
| .of_match_table = rmobile_reset_of_match, | |
| }, | |
| }; | |
| module_platform_driver(rmobile_reset_driver); | |
| MODULE_DESCRIPTION("Renesas R-Mobile Reset Driver"); | |
| MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>"); | |
| MODULE_LICENSE("GPL v2"); |