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