Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/platforms/85xx/sgy_cts1000.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Servergy CTS-1000 Setup
4
*
5
* Maintained by Ben Collins <[email protected]>
6
*
7
* Copyright 2012 by Servergy, Inc.
8
*/
9
10
#define pr_fmt(fmt) "gpio-halt: " fmt
11
12
#include <linux/err.h>
13
#include <linux/platform_device.h>
14
#include <linux/device.h>
15
#include <linux/gpio/consumer.h>
16
#include <linux/module.h>
17
#include <linux/of_irq.h>
18
#include <linux/workqueue.h>
19
#include <linux/reboot.h>
20
#include <linux/interrupt.h>
21
22
#include <asm/machdep.h>
23
24
static struct gpio_desc *halt_gpio;
25
static int halt_irq;
26
27
static const struct of_device_id child_match[] = {
28
{
29
.compatible = "sgy,gpio-halt",
30
},
31
{},
32
};
33
34
static void gpio_halt_wfn(struct work_struct *work)
35
{
36
/* Likely wont return */
37
orderly_poweroff(true);
38
}
39
static DECLARE_WORK(gpio_halt_wq, gpio_halt_wfn);
40
41
static void __noreturn gpio_halt_cb(void)
42
{
43
pr_info("triggering GPIO.\n");
44
45
/* Probably wont return */
46
gpiod_set_value(halt_gpio, 1);
47
48
panic("Halt failed\n");
49
}
50
51
/* This IRQ means someone pressed the power button and it is waiting for us
52
* to handle the shutdown/poweroff. */
53
static irqreturn_t gpio_halt_irq(int irq, void *__data)
54
{
55
struct platform_device *pdev = __data;
56
57
dev_info(&pdev->dev, "scheduling shutdown due to power button IRQ\n");
58
schedule_work(&gpio_halt_wq);
59
60
return IRQ_HANDLED;
61
};
62
63
static int __gpio_halt_probe(struct platform_device *pdev,
64
struct device_node *halt_node)
65
{
66
int err;
67
68
halt_gpio = fwnode_gpiod_get_index(of_fwnode_handle(halt_node),
69
NULL, 0, GPIOD_OUT_LOW, "gpio-halt");
70
err = PTR_ERR_OR_ZERO(halt_gpio);
71
if (err) {
72
dev_err(&pdev->dev, "failed to request halt GPIO: %d\n", err);
73
return err;
74
}
75
76
/* Now get the IRQ which tells us when the power button is hit */
77
halt_irq = irq_of_parse_and_map(halt_node, 0);
78
err = request_irq(halt_irq, gpio_halt_irq,
79
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
80
"gpio-halt", pdev);
81
if (err) {
82
dev_err(&pdev->dev, "failed to request IRQ %d: %d\n",
83
halt_irq, err);
84
gpiod_put(halt_gpio);
85
halt_gpio = NULL;
86
return err;
87
}
88
89
/* Register our halt function */
90
ppc_md.halt = gpio_halt_cb;
91
pm_power_off = gpio_halt_cb;
92
93
dev_info(&pdev->dev, "registered halt GPIO, irq: %d\n", halt_irq);
94
95
return 0;
96
}
97
98
static int gpio_halt_probe(struct platform_device *pdev)
99
{
100
struct device_node *halt_node;
101
int ret;
102
103
if (!pdev->dev.of_node)
104
return -ENODEV;
105
106
/* If there's no matching child, this isn't really an error */
107
halt_node = of_find_matching_node(pdev->dev.of_node, child_match);
108
if (!halt_node)
109
return -ENODEV;
110
111
ret = __gpio_halt_probe(pdev, halt_node);
112
of_node_put(halt_node);
113
114
return ret;
115
}
116
117
static void gpio_halt_remove(struct platform_device *pdev)
118
{
119
free_irq(halt_irq, pdev);
120
cancel_work_sync(&gpio_halt_wq);
121
122
ppc_md.halt = NULL;
123
pm_power_off = NULL;
124
125
gpiod_put(halt_gpio);
126
halt_gpio = NULL;
127
}
128
129
static const struct of_device_id gpio_halt_match[] = {
130
/* We match on the gpio bus itself and scan the children since they
131
* wont be matched against us. We know the bus wont match until it
132
* has been registered too. */
133
{
134
.compatible = "fsl,qoriq-gpio",
135
},
136
{},
137
};
138
MODULE_DEVICE_TABLE(of, gpio_halt_match);
139
140
static struct platform_driver gpio_halt_driver = {
141
.driver = {
142
.name = "gpio-halt",
143
.of_match_table = gpio_halt_match,
144
},
145
.probe = gpio_halt_probe,
146
.remove = gpio_halt_remove,
147
};
148
149
module_platform_driver(gpio_halt_driver);
150
151
MODULE_DESCRIPTION("Driver to support GPIO triggered system halt for Servergy CTS-1000 Systems.");
152
MODULE_VERSION("1.0");
153
MODULE_AUTHOR("Ben Collins <[email protected]>");
154
MODULE_LICENSE("GPL");
155
156