tps65086-restart.c (2464B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2021 Emil Renner Berthing 4 */ 5 6#include <linux/mfd/tps65086.h> 7#include <linux/mod_devicetable.h> 8#include <linux/module.h> 9#include <linux/platform_device.h> 10#include <linux/reboot.h> 11 12struct tps65086_restart { 13 struct notifier_block handler; 14 struct device *dev; 15}; 16 17static int tps65086_restart_notify(struct notifier_block *this, 18 unsigned long mode, void *cmd) 19{ 20 struct tps65086_restart *tps65086_restart = 21 container_of(this, struct tps65086_restart, handler); 22 struct tps65086 *tps65086 = dev_get_drvdata(tps65086_restart->dev->parent); 23 int ret; 24 25 ret = regmap_write(tps65086->regmap, TPS65086_FORCESHUTDN, 1); 26 if (ret) { 27 dev_err(tps65086_restart->dev, "%s: error writing to tps65086 pmic: %d\n", 28 __func__, ret); 29 return NOTIFY_DONE; 30 } 31 32 /* give it a little time */ 33 mdelay(200); 34 35 WARN_ON(1); 36 37 return NOTIFY_DONE; 38} 39 40static int tps65086_restart_probe(struct platform_device *pdev) 41{ 42 struct tps65086_restart *tps65086_restart; 43 int ret; 44 45 tps65086_restart = devm_kzalloc(&pdev->dev, sizeof(*tps65086_restart), GFP_KERNEL); 46 if (!tps65086_restart) 47 return -ENOMEM; 48 49 platform_set_drvdata(pdev, tps65086_restart); 50 51 tps65086_restart->handler.notifier_call = tps65086_restart_notify; 52 tps65086_restart->handler.priority = 192; 53 tps65086_restart->dev = &pdev->dev; 54 55 ret = register_restart_handler(&tps65086_restart->handler); 56 if (ret) { 57 dev_err(&pdev->dev, "%s: cannot register restart handler: %d\n", 58 __func__, ret); 59 return -ENODEV; 60 } 61 62 return 0; 63} 64 65static int tps65086_restart_remove(struct platform_device *pdev) 66{ 67 struct tps65086_restart *tps65086_restart = platform_get_drvdata(pdev); 68 int ret; 69 70 ret = unregister_restart_handler(&tps65086_restart->handler); 71 if (ret) { 72 dev_err(&pdev->dev, "%s: cannot unregister restart handler: %d\n", 73 __func__, ret); 74 return -ENODEV; 75 } 76 77 return 0; 78} 79 80static const struct platform_device_id tps65086_restart_id_table[] = { 81 { "tps65086-reset", }, 82 { /* sentinel */ } 83}; 84MODULE_DEVICE_TABLE(platform, tps65086_restart_id_table); 85 86static struct platform_driver tps65086_restart_driver = { 87 .driver = { 88 .name = "tps65086-restart", 89 }, 90 .probe = tps65086_restart_probe, 91 .remove = tps65086_restart_remove, 92 .id_table = tps65086_restart_id_table, 93}; 94module_platform_driver(tps65086_restart_driver); 95 96MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>"); 97MODULE_DESCRIPTION("TPS65086 restart driver"); 98MODULE_LICENSE("GPL v2");