xref: /linux/drivers/platform/x86/intel/rst.c (revision a67c554dbc0fdd7e3c5909cb9f0fff41c51b2e9d)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  Copyright 2013 Matthew Garrett <mjg59@srcf.ucam.org>
4  */
5 
6 #include <linux/acpi.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/slab.h>
10 
11 MODULE_DESCRIPTION("Intel Rapid Start Technology Driver");
12 MODULE_LICENSE("GPL");
13 
14 static ssize_t irst_show_wakeup_events(struct device *dev,
15 				       struct device_attribute *attr,
16 				       char *buf)
17 {
18 	struct acpi_device *acpi;
19 	unsigned long long value;
20 	acpi_status status;
21 
22 	acpi = to_acpi_device(dev);
23 
24 	status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value);
25 	if (ACPI_FAILURE(status))
26 		return -EINVAL;
27 
28 	return sprintf(buf, "%lld\n", value);
29 }
30 
31 static ssize_t irst_store_wakeup_events(struct device *dev,
32 					struct device_attribute *attr,
33 					const char *buf, size_t count)
34 {
35 	struct acpi_device *acpi;
36 	acpi_status status;
37 	unsigned long value;
38 	int error;
39 
40 	acpi = to_acpi_device(dev);
41 
42 	error = kstrtoul(buf, 0, &value);
43 	if (error)
44 		return error;
45 
46 	status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
47 	if (ACPI_FAILURE(status))
48 		return -EINVAL;
49 
50 	return count;
51 }
52 
53 static struct device_attribute irst_wakeup_attr = {
54 	.attr = { .name = "wakeup_events", .mode = 0600 },
55 	.show = irst_show_wakeup_events,
56 	.store = irst_store_wakeup_events
57 };
58 
59 static ssize_t irst_show_wakeup_time(struct device *dev,
60 				     struct device_attribute *attr, char *buf)
61 {
62 	struct acpi_device *acpi;
63 	unsigned long long value;
64 	acpi_status status;
65 
66 	acpi = to_acpi_device(dev);
67 
68 	status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value);
69 	if (ACPI_FAILURE(status))
70 		return -EINVAL;
71 
72 	return sprintf(buf, "%lld\n", value);
73 }
74 
75 static ssize_t irst_store_wakeup_time(struct device *dev,
76 				      struct device_attribute *attr,
77 				      const char *buf, size_t count)
78 {
79 	struct acpi_device *acpi;
80 	acpi_status status;
81 	unsigned long value;
82 	int error;
83 
84 	acpi = to_acpi_device(dev);
85 
86 	error = kstrtoul(buf, 0, &value);
87 	if (error)
88 		return error;
89 
90 	status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
91 	if (ACPI_FAILURE(status))
92 		return -EINVAL;
93 
94 	return count;
95 }
96 
97 static struct device_attribute irst_timeout_attr = {
98 	.attr = { .name = "wakeup_time", .mode = 0600 },
99 	.show = irst_show_wakeup_time,
100 	.store = irst_store_wakeup_time
101 };
102 
103 static int irst_probe(struct platform_device *pdev)
104 {
105 	struct acpi_device *acpi;
106 	int error;
107 
108 	acpi = ACPI_COMPANION(&pdev->dev);
109 	if (!acpi)
110 		return -ENODEV;
111 
112 	error = device_create_file(&acpi->dev, &irst_timeout_attr);
113 	if (unlikely(error))
114 		return error;
115 
116 	error = device_create_file(&acpi->dev, &irst_wakeup_attr);
117 	if (unlikely(error))
118 		device_remove_file(&acpi->dev, &irst_timeout_attr);
119 
120 	return error;
121 }
122 
123 static void irst_remove(struct platform_device *pdev)
124 {
125 	struct acpi_device *acpi = ACPI_COMPANION(&pdev->dev);
126 
127 	device_remove_file(&acpi->dev, &irst_wakeup_attr);
128 	device_remove_file(&acpi->dev, &irst_timeout_attr);
129 }
130 
131 static const struct acpi_device_id irst_ids[] = {
132 	{"INT3392", 0},
133 	{"", 0}
134 };
135 
136 static struct platform_driver irst_driver = {
137 	.probe = irst_probe,
138 	.remove = irst_remove,
139 	.driver = {
140 		.name = "intel_rapid_start",
141 		.acpi_match_table = irst_ids,
142 	},
143 };
144 
145 module_platform_driver(irst_driver);
146 
147 MODULE_DEVICE_TABLE(acpi, irst_ids);
148