^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * LTC2952 (PowerPath) driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2014, Xsens Technologies BV <info@xsens.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Maintainer: René Moll <linux@r-moll.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * ----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * - Description
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * ----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This driver is to be used with an external PowerPath Controller (LTC2952).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Its function is to determine when a external shut down is triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * and react by properly shutting down the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This driver expects a device tree with a ltc2952 entry for pin mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * ----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * - GPIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * ----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * The following GPIOs are used:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * - trigger (input)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * A level change indicates the shut-down trigger. If it's state reverts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * within the time-out defined by trigger_delay, the shut down is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * executed. If no pin is assigned to this input, the driver will start the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * watchdog toggle immediately. The chip will only power off the system if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * it is requested to do so through the kill line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - watchdog (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Once a shut down is triggered, the driver will toggle this signal,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * with an internal (wde_interval) to stall the hardware shut down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * - kill (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * The last action during shut down is triggering this signalling, such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * that the PowerPath Control will power down the hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * ----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * - Interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * ----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * The driver requires a non-shared, edge-triggered interrupt on the trigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * GPIO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/kmod.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/reboot.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct ltc2952_poweroff {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct hrtimer timer_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct hrtimer timer_wde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) ktime_t trigger_delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ktime_t wde_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct gpio_desc *gpio_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct gpio_desc *gpio_watchdog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct gpio_desc *gpio_kill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) bool kernel_panic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct notifier_block panic_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define to_ltc2952(p, m) container_of(p, struct ltc2952_poweroff, m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * This global variable is only needed for pm_power_off. We should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * remove it entirely once we don't need the global state anymore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static struct ltc2952_poweroff *ltc2952_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * ltc2952_poweroff_timer_wde - Timer callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Toggles the watchdog reset signal each wde_interval
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @timer: corresponding timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Returns HRTIMER_RESTART for an infinite loop which will only stop when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * machine actually shuts down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static enum hrtimer_restart ltc2952_poweroff_timer_wde(struct hrtimer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ktime_t now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct ltc2952_poweroff *data = to_ltc2952(timer, timer_wde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (data->kernel_panic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return HRTIMER_NORESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) state = gpiod_get_value(data->gpio_watchdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) gpiod_set_value(data->gpio_watchdog, !state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) now = hrtimer_cb_get_time(timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) hrtimer_forward(timer, now, data->wde_interval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return HRTIMER_RESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static void ltc2952_poweroff_start_wde(struct ltc2952_poweroff *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) hrtimer_start(&data->timer_wde, data->wde_interval, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static enum hrtimer_restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ltc2952_poweroff_timer_trigger(struct hrtimer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct ltc2952_poweroff *data = to_ltc2952(timer, timer_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ltc2952_poweroff_start_wde(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) dev_info(data->dev, "executing shutdown\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) orderly_poweroff(true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return HRTIMER_NORESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * ltc2952_poweroff_handler - Interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Triggered each time the trigger signal changes state and (de)activates a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * time-out (timer_trigger). Once the time-out is actually reached the shut
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * down is executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * @irq: IRQ number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * @dev_id: pointer to the main data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static irqreturn_t ltc2952_poweroff_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct ltc2952_poweroff *data = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (data->kernel_panic || hrtimer_active(&data->timer_wde)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* shutdown is already triggered, nothing to do any more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (gpiod_get_value(data->gpio_trigger)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) hrtimer_start(&data->timer_trigger, data->trigger_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) hrtimer_cancel(&data->timer_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static void ltc2952_poweroff_kill(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) gpiod_set_value(ltc2952_data->gpio_kill, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static void ltc2952_poweroff_default(struct ltc2952_poweroff *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) data->wde_interval = 300L * NSEC_PER_MSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) data->trigger_delay = ktime_set(2, 500L * NSEC_PER_MSEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) hrtimer_init(&data->timer_trigger, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) data->timer_trigger.function = ltc2952_poweroff_timer_trigger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) hrtimer_init(&data->timer_wde, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) data->timer_wde.function = ltc2952_poweroff_timer_wde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static int ltc2952_poweroff_init(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct ltc2952_poweroff *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ltc2952_poweroff_default(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) data->gpio_watchdog = devm_gpiod_get(&pdev->dev, "watchdog",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (IS_ERR(data->gpio_watchdog)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ret = PTR_ERR(data->gpio_watchdog);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) dev_err(&pdev->dev, "unable to claim gpio \"watchdog\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) data->gpio_kill = devm_gpiod_get(&pdev->dev, "kill", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (IS_ERR(data->gpio_kill)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ret = PTR_ERR(data->gpio_kill);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) dev_err(&pdev->dev, "unable to claim gpio \"kill\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) data->gpio_trigger = devm_gpiod_get_optional(&pdev->dev, "trigger",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (IS_ERR(data->gpio_trigger)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * It's not a problem if the trigger gpio isn't available, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * it is worth a warning if its use was defined in the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) dev_err(&pdev->dev, "unable to claim gpio \"trigger\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) data->gpio_trigger = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (devm_request_irq(&pdev->dev, gpiod_to_irq(data->gpio_trigger),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ltc2952_poweroff_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "ltc2952-poweroff",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Some things may have happened:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * - No trigger input was defined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * - Claiming the GPIO failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * - We could not map to an IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * - We couldn't register an interrupt handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * None of these really are problems, but all of them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * disqualify the push button from controlling the power.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * It is therefore important to note that if the ltc2952
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * detects a button press for long enough, it will still start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * its own powerdown window and cut the power on us if we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * start the watchdog trigger.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (data->gpio_trigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) "unable to configure the trigger interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) devm_gpiod_put(&pdev->dev, data->gpio_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) data->gpio_trigger = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) dev_info(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) "power down trigger input will not be used\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ltc2952_poweroff_start_wde(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int ltc2952_poweroff_notify_panic(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned long code, void *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) struct ltc2952_poweroff *data = to_ltc2952(nb, panic_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) data->kernel_panic = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return NOTIFY_DONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int ltc2952_poweroff_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct ltc2952_poweroff *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (pm_power_off) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) dev_err(&pdev->dev, "pm_power_off already registered");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) data->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = ltc2952_poweroff_init(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* TODO: remove ltc2952_data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ltc2952_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pm_power_off = ltc2952_poweroff_kill;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) data->panic_notifier.notifier_call = ltc2952_poweroff_notify_panic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) atomic_notifier_chain_register(&panic_notifier_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) &data->panic_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) dev_info(&pdev->dev, "probe successful\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static int ltc2952_poweroff_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct ltc2952_poweroff *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) pm_power_off = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) hrtimer_cancel(&data->timer_trigger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) hrtimer_cancel(&data->timer_wde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) atomic_notifier_chain_unregister(&panic_notifier_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) &data->panic_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static const struct of_device_id of_ltc2952_poweroff_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { .compatible = "lltc,ltc2952"},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) MODULE_DEVICE_TABLE(of, of_ltc2952_poweroff_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static struct platform_driver ltc2952_poweroff_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .probe = ltc2952_poweroff_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .remove = ltc2952_poweroff_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .name = "ltc2952-poweroff",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .of_match_table = of_ltc2952_poweroff_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) module_platform_driver(ltc2952_poweroff_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) MODULE_AUTHOR("René Moll <rene.moll@xsens.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) MODULE_DESCRIPTION("LTC PowerPath power-off driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) MODULE_LICENSE("GPL v2");