| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2014 STMicroelectronics | 
|  | 3 | * | 
|  | 4 | * Power off Restart driver, used in STMicroelectronics devices. | 
|  | 5 | * | 
|  | 6 | * Author: Christophe Kerello <christophe.kerello@st.com> | 
|  | 7 | * | 
|  | 8 | * This program is free software; you can redistribute it and/or modify | 
|  | 9 | * it under the terms of the GNU General Public License version 2, as | 
|  | 10 | * published by the Free Software Foundation. | 
|  | 11 | */ | 
|  | 12 |  | 
|  | 13 | #include <linux/module.h> | 
|  | 14 | #include <linux/of.h> | 
|  | 15 | #include <linux/of_platform.h> | 
|  | 16 | #include <linux/platform_device.h> | 
|  | 17 | #include <linux/mfd/syscon.h> | 
|  | 18 | #include <linux/reboot.h> | 
|  | 19 | #include <linux/regmap.h> | 
|  | 20 |  | 
|  | 21 | struct reset_syscfg { | 
|  | 22 | struct regmap *regmap; | 
|  | 23 | /* syscfg used for reset */ | 
|  | 24 | unsigned int offset_rst; | 
|  | 25 | unsigned int mask_rst; | 
|  | 26 | /* syscfg used for unmask the reset */ | 
|  | 27 | unsigned int offset_rst_msk; | 
|  | 28 | unsigned int mask_rst_msk; | 
|  | 29 | }; | 
|  | 30 |  | 
|  | 31 | /* STiH407 */ | 
|  | 32 | #define STIH407_SYSCFG_4000	0x0 | 
|  | 33 | #define STIH407_SYSCFG_4008	0x20 | 
|  | 34 |  | 
|  | 35 | static struct reset_syscfg stih407_reset = { | 
|  | 36 | .offset_rst = STIH407_SYSCFG_4000, | 
|  | 37 | .mask_rst = BIT(0), | 
|  | 38 | .offset_rst_msk = STIH407_SYSCFG_4008, | 
|  | 39 | .mask_rst_msk = BIT(0) | 
|  | 40 | }; | 
|  | 41 |  | 
|  | 42 |  | 
|  | 43 | static struct reset_syscfg *st_restart_syscfg; | 
|  | 44 |  | 
|  | 45 | static int st_restart(struct notifier_block *this, unsigned long mode, | 
|  | 46 | void *cmd) | 
|  | 47 | { | 
|  | 48 | /* reset syscfg updated */ | 
|  | 49 | regmap_update_bits(st_restart_syscfg->regmap, | 
|  | 50 | st_restart_syscfg->offset_rst, | 
|  | 51 | st_restart_syscfg->mask_rst, | 
|  | 52 | 0); | 
|  | 53 |  | 
|  | 54 | /* unmask the reset */ | 
|  | 55 | regmap_update_bits(st_restart_syscfg->regmap, | 
|  | 56 | st_restart_syscfg->offset_rst_msk, | 
|  | 57 | st_restart_syscfg->mask_rst_msk, | 
|  | 58 | 0); | 
|  | 59 |  | 
|  | 60 | return NOTIFY_DONE; | 
|  | 61 | } | 
|  | 62 |  | 
|  | 63 | static struct notifier_block st_restart_nb = { | 
|  | 64 | .notifier_call = st_restart, | 
|  | 65 | .priority = 192, | 
|  | 66 | }; | 
|  | 67 |  | 
|  | 68 | static const struct of_device_id st_reset_of_match[] = { | 
|  | 69 | { | 
|  | 70 | .compatible = "st,stih407-restart", | 
|  | 71 | .data = (void *)&stih407_reset, | 
|  | 72 | }, | 
|  | 73 | {} | 
|  | 74 | }; | 
|  | 75 |  | 
|  | 76 | static int st_reset_probe(struct platform_device *pdev) | 
|  | 77 | { | 
|  | 78 | struct device_node *np = pdev->dev.of_node; | 
|  | 79 | const struct of_device_id *match; | 
|  | 80 | struct device *dev = &pdev->dev; | 
|  | 81 |  | 
|  | 82 | match = of_match_device(st_reset_of_match, dev); | 
|  | 83 | if (!match) | 
|  | 84 | return -ENODEV; | 
|  | 85 |  | 
|  | 86 | st_restart_syscfg = (struct reset_syscfg *)match->data; | 
|  | 87 |  | 
|  | 88 | st_restart_syscfg->regmap = | 
|  | 89 | syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | 
|  | 90 | if (IS_ERR(st_restart_syscfg->regmap)) { | 
|  | 91 | dev_err(dev, "No syscfg phandle specified\n"); | 
|  | 92 | return PTR_ERR(st_restart_syscfg->regmap); | 
|  | 93 | } | 
|  | 94 |  | 
|  | 95 | return register_restart_handler(&st_restart_nb); | 
|  | 96 | } | 
|  | 97 |  | 
|  | 98 | static struct platform_driver st_reset_driver = { | 
|  | 99 | .probe = st_reset_probe, | 
|  | 100 | .driver = { | 
|  | 101 | .name = "st_reset", | 
|  | 102 | .of_match_table = st_reset_of_match, | 
|  | 103 | }, | 
|  | 104 | }; | 
|  | 105 |  | 
|  | 106 | static int __init st_reset_init(void) | 
|  | 107 | { | 
|  | 108 | return platform_driver_register(&st_reset_driver); | 
|  | 109 | } | 
|  | 110 |  | 
|  | 111 | device_initcall(st_reset_init); | 
|  | 112 |  | 
|  | 113 | MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>"); | 
|  | 114 | MODULE_DESCRIPTION("STMicroelectronics Power off Restart driver"); | 
|  | 115 | MODULE_LICENSE("GPL v2"); |