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