File Index
Files and directories
Sign in
FILE

acpi_tad.c

File preview with syntax highlighting.

linux-6.19.14/drivers/acpi/acpi_tad.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * ACPI Time and Alarm (TAD) Device Driver
  4 *
  5 * Copyright (C) 2018 Intel Corporation
  6 * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  7 *
  8 * This driver is based on Section 9.18 of the ACPI 6.2 specification revision.
  9 *
 10 * It only supports the system wakeup capabilities of the TAD.
 11 *
 12 * Provided are sysfs attributes, available under the TAD platform device,
 13 * allowing user space to manage the AC and DC wakeup timers of the TAD:
 14 * set and read their values, set and check their expire timer wake policies,
 15 * check and clear their status and check the capabilities of the TAD reported
 16 * by AML.  The DC timer attributes are only present if the TAD supports a
 17 * separate DC alarm timer.
 18 *
 19 * The wakeup events handling and power management of the TAD is expected to
 20 * be taken care of by the ACPI PM domain attached to its platform device.
 21 */
 22
 23#include <linux/acpi.h>
 24#include <linux/kernel.h>
 25#include <linux/module.h>
 26#include <linux/platform_device.h>
 27#include <linux/pm_runtime.h>
 28#include <linux/suspend.h>
 29
 30MODULE_DESCRIPTION("ACPI Time and Alarm (TAD) Device Driver");
 31MODULE_LICENSE("GPL v2");
 32MODULE_AUTHOR("Rafael J. Wysocki");
 33
 34/* ACPI TAD capability flags (ACPI 6.2, Section 9.18.2) */
 35#define ACPI_TAD_AC_WAKE	BIT(0)
 36#define ACPI_TAD_DC_WAKE	BIT(1)
 37#define ACPI_TAD_RT		BIT(2)
 38#define ACPI_TAD_RT_IN_MS	BIT(3)
 39#define ACPI_TAD_S4_S5__GWS	BIT(4)
 40#define ACPI_TAD_AC_S4_WAKE	BIT(5)
 41#define ACPI_TAD_AC_S5_WAKE	BIT(6)
 42#define ACPI_TAD_DC_S4_WAKE	BIT(7)
 43#define ACPI_TAD_DC_S5_WAKE	BIT(8)
 44
 45/* ACPI TAD alarm timer selection */
 46#define ACPI_TAD_AC_TIMER	(u32)0
 47#define ACPI_TAD_DC_TIMER	(u32)1
 48
 49/* Special value for disabled timer or expired timer wake policy. */
 50#define ACPI_TAD_WAKE_DISABLED	(~(u32)0)
 51
 52struct acpi_tad_driver_data {
 53	u32 capabilities;
 54};
 55
 56struct acpi_tad_rt {
 57	u16 year;  /* 1900 - 9999 */
 58	u8 month;  /* 1 - 12 */
 59	u8 day;    /* 1 - 31 */
 60	u8 hour;   /* 0 - 23 */
 61	u8 minute; /* 0 - 59 */
 62	u8 second; /* 0 - 59 */
 63	u8 valid;  /* 0 (failed) or 1 (success) for reads, 0 for writes */
 64	u16 msec;  /* 1 - 1000 */
 65	s16 tz;    /* -1440 to 1440 or 2047 (unspecified) */
 66	u8 daylight;
 67	u8 padding[3]; /* must be 0 */
 68} __packed;
 69
 70static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt)
 71{
 72	acpi_handle handle = ACPI_HANDLE(dev);
 73	union acpi_object args[] = {
 74		{ .type = ACPI_TYPE_BUFFER, },
 75	};
 76	struct acpi_object_list arg_list = {
 77		.pointer = args,
 78		.count = ARRAY_SIZE(args),
 79	};
 80	unsigned long long retval;
 81	acpi_status status;
 82
 83	if (rt->year < 1900 || rt->year > 9999 ||
 84	    rt->month < 1 || rt->month > 12 ||
 85	    rt->hour > 23 || rt->minute > 59 || rt->second > 59 ||
 86	    rt->tz < -1440 || (rt->tz > 1440 && rt->tz != 2047) ||
 87	    rt->daylight > 3)
 88		return -ERANGE;
 89
 90	args[0].buffer.pointer = (u8 *)rt;
 91	args[0].buffer.length = sizeof(*rt);
 92
 93	PM_RUNTIME_ACQUIRE(dev, pm);
 94	if (PM_RUNTIME_ACQUIRE_ERR(&pm))
 95		return -ENXIO;
 96
 97	status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval);
 98	if (ACPI_FAILURE(status) || retval)
 99		return -EIO;
100
101	return 0;
102}
103
104static int acpi_tad_evaluate_grt(struct device *dev, struct acpi_tad_rt *rt)
105{
106	acpi_handle handle = ACPI_HANDLE(dev);
107	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER };
108	union acpi_object *out_obj;
109	struct acpi_tad_rt *data;
110	acpi_status status;
111	int ret = -EIO;
112
113	status = acpi_evaluate_object(handle, "_GRT", NULL, &output);
114	if (ACPI_FAILURE(status))
115		goto out_free;
116
117	out_obj = output.pointer;
118	if (out_obj->type != ACPI_TYPE_BUFFER)
119		goto out_free;
120
121	if (out_obj->buffer.length != sizeof(*rt))
122		goto out_free;
123
124	data = (struct acpi_tad_rt *)(out_obj->buffer.pointer);
125	if (!data->valid)
126		goto out_free;
127
128	memcpy(rt, data, sizeof(*rt));
129	ret = 0;
130
131out_free:
132	ACPI_FREE(output.pointer);
133	return ret;
134}
135
136static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
137{
138	int ret;
139
140	PM_RUNTIME_ACQUIRE(dev, pm);
141	if (PM_RUNTIME_ACQUIRE_ERR(&pm))
142		return -ENXIO;
143
144	ret = acpi_tad_evaluate_grt(dev, rt);
145	if (ret)
146		return ret;
147
148	return 0;
149}
150
151static char *acpi_tad_rt_next_field(char *s, int *val)
152{
153	char *p;
154
155	p = strchr(s, ':');
156	if (!p)
157		return NULL;
158
159	*p = '\0';
160	if (kstrtoint(s, 10, val))
161		return NULL;
162
163	return p + 1;
164}
165
166static ssize_t time_store(struct device *dev, struct device_attribute *attr,
167			  const char *buf, size_t count)
168{
169	struct acpi_tad_rt rt;
170	char *str, *s;
171	int val, ret = -ENODATA;
172
173	str = kmemdup_nul(buf, count, GFP_KERNEL);
174	if (!str)
175		return -ENOMEM;
176
177	s = acpi_tad_rt_next_field(str, &val);
178	if (!s)
179		goto out_free;
180
181	rt.year = val;
182
183	s = acpi_tad_rt_next_field(s, &val);
184	if (!s)
185		goto out_free;
186
187	rt.month = val;
188
189	s = acpi_tad_rt_next_field(s, &val);
190	if (!s)
191		goto out_free;
192
193	rt.day = val;
194
195	s = acpi_tad_rt_next_field(s, &val);
196	if (!s)
197		goto out_free;
198
199	rt.hour = val;
200
201	s = acpi_tad_rt_next_field(s, &val);
202	if (!s)
203		goto out_free;
204
205	rt.minute = val;
206
207	s = acpi_tad_rt_next_field(s, &val);
208	if (!s)
209		goto out_free;
210
211	rt.second = val;
212
213	s = acpi_tad_rt_next_field(s, &val);
214	if (!s)
215		goto out_free;
216
217	rt.tz = val;
218
219	if (kstrtoint(s, 10, &val))
220		goto out_free;
221
222	rt.daylight = val;
223
224	rt.valid = 0;
225	rt.msec = 0;
226	memset(rt.padding, 0, 3);
227
228	ret = acpi_tad_set_real_time(dev, &rt);
229
230out_free:
231	kfree(str);
232	return ret ? ret : count;
233}
234
235static ssize_t time_show(struct device *dev, struct device_attribute *attr,
236			 char *buf)
237{
238	struct acpi_tad_rt rt;
239	int ret;
240
241	ret = acpi_tad_get_real_time(dev, &rt);
242	if (ret)
243		return ret;
244
245	return sysfs_emit(buf, "%u:%u:%u:%u:%u:%u:%d:%u\n",
246		       rt.year, rt.month, rt.day, rt.hour, rt.minute, rt.second,
247		       rt.tz, rt.daylight);
248}
249
250static DEVICE_ATTR_RW(time);
251
252static struct attribute *acpi_tad_time_attrs[] = {
253	&dev_attr_time.attr,
254	NULL,
255};
256static const struct attribute_group acpi_tad_time_attr_group = {
257	.attrs	= acpi_tad_time_attrs,
258};
259
260static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id,
261			     u32 value)
262{
263	acpi_handle handle = ACPI_HANDLE(dev);
264	union acpi_object args[] = {
265		{ .type = ACPI_TYPE_INTEGER, },
266		{ .type = ACPI_TYPE_INTEGER, },
267	};
268	struct acpi_object_list arg_list = {
269		.pointer = args,
270		.count = ARRAY_SIZE(args),
271	};
272	unsigned long long retval;
273	acpi_status status;
274
275	args[0].integer.value = timer_id;
276	args[1].integer.value = value;
277
278	PM_RUNTIME_ACQUIRE(dev, pm);
279	if (PM_RUNTIME_ACQUIRE_ERR(&pm))
280		return -ENXIO;
281
282	status = acpi_evaluate_integer(handle, method, &arg_list, &retval);
283	if (ACPI_FAILURE(status) || retval)
284		return -EIO;
285
286	return 0;
287}
288
289static int acpi_tad_wake_write(struct device *dev, const char *buf, char *method,
290			       u32 timer_id, const char *specval)
291{
292	u32 value;
293
294	if (sysfs_streq(buf, specval)) {
295		value = ACPI_TAD_WAKE_DISABLED;
296	} else {
297		int ret = kstrtou32(buf, 0, &value);
298
299		if (ret)
300			return ret;
301
302		if (value == ACPI_TAD_WAKE_DISABLED)
303			return -EINVAL;
304	}
305
306	return acpi_tad_wake_set(dev, method, timer_id, value);
307}
308
309static ssize_t acpi_tad_wake_read(struct device *dev, char *buf, char *method,
310				  u32 timer_id, const char *specval)
311{
312	acpi_handle handle = ACPI_HANDLE(dev);
313	union acpi_object args[] = {
314		{ .type = ACPI_TYPE_INTEGER, },
315	};
316	struct acpi_object_list arg_list = {
317		.pointer = args,
318		.count = ARRAY_SIZE(args),
319	};
320	unsigned long long retval;
321	acpi_status status;
322
323	args[0].integer.value = timer_id;
324
325	PM_RUNTIME_ACQUIRE(dev, pm);
326	if (PM_RUNTIME_ACQUIRE_ERR(&pm))
327		return -ENXIO;
328
329	status = acpi_evaluate_integer(handle, method, &arg_list, &retval);
330	if (ACPI_FAILURE(status))
331		return -EIO;
332
333	if ((u32)retval == ACPI_TAD_WAKE_DISABLED)
334		return sprintf(buf, "%s\n", specval);
335
336	return sprintf(buf, "%u\n", (u32)retval);
337}
338
339static const char *alarm_specval = "disabled";
340
341static int acpi_tad_alarm_write(struct device *dev, const char *buf,
342				u32 timer_id)
343{
344	return acpi_tad_wake_write(dev, buf, "_STV", timer_id, alarm_specval);
345}
346
347static ssize_t acpi_tad_alarm_read(struct device *dev, char *buf, u32 timer_id)
348{
349	return acpi_tad_wake_read(dev, buf, "_TIV", timer_id, alarm_specval);
350}
351
352static const char *policy_specval = "never";
353
354static int acpi_tad_policy_write(struct device *dev, const char *buf,
355				 u32 timer_id)
356{
357	return acpi_tad_wake_write(dev, buf, "_STP", timer_id, policy_specval);
358}
359
360static ssize_t acpi_tad_policy_read(struct device *dev, char *buf, u32 timer_id)
361{
362	return acpi_tad_wake_read(dev, buf, "_TIP", timer_id, policy_specval);
363}
364
365static int acpi_tad_clear_status(struct device *dev, u32 timer_id)
366{
367	acpi_handle handle = ACPI_HANDLE(dev);
368	union acpi_object args[] = {
369		{ .type = ACPI_TYPE_INTEGER, },
370	};
371	struct acpi_object_list arg_list = {
372		.pointer = args,
373		.count = ARRAY_SIZE(args),
374	};
375	unsigned long long retval;
376	acpi_status status;
377
378	args[0].integer.value = timer_id;
379
380	PM_RUNTIME_ACQUIRE(dev, pm);
381	if (PM_RUNTIME_ACQUIRE_ERR(&pm))
382		return -ENXIO;
383
384	status = acpi_evaluate_integer(handle, "_CWS", &arg_list, &retval);
385	if (ACPI_FAILURE(status) || retval)
386		return -EIO;
387
388	return 0;
389}
390
391static int acpi_tad_status_write(struct device *dev, const char *buf, u32 timer_id)
392{
393	int ret, value;
394
395	ret = kstrtoint(buf, 0, &value);
396	if (ret)
397		return ret;
398
399	if (value)
400		return -EINVAL;
401
402	return acpi_tad_clear_status(dev, timer_id);
403}
404
405static ssize_t acpi_tad_status_read(struct device *dev, char *buf, u32 timer_id)
406{
407	acpi_handle handle = ACPI_HANDLE(dev);
408	union acpi_object args[] = {
409		{ .type = ACPI_TYPE_INTEGER, },
410	};
411	struct acpi_object_list arg_list = {
412		.pointer = args,
413		.count = ARRAY_SIZE(args),
414	};
415	unsigned long long retval;
416	acpi_status status;
417
418	args[0].integer.value = timer_id;
419
420	PM_RUNTIME_ACQUIRE(dev, pm);
421	if (PM_RUNTIME_ACQUIRE_ERR(&pm))
422		return -ENXIO;
423
424	status = acpi_evaluate_integer(handle, "_GWS", &arg_list, &retval);
425	if (ACPI_FAILURE(status))
426		return -EIO;
427
428	return sprintf(buf, "0x%02X\n", (u32)retval);
429}
430
431static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
432			 char *buf)
433{
434	struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
435
436	return sysfs_emit(buf, "0x%02X\n", dd->capabilities);
437}
438
439static DEVICE_ATTR_RO(caps);
440
441static ssize_t ac_alarm_store(struct device *dev, struct device_attribute *attr,
442			      const char *buf, size_t count)
443{
444	int ret = acpi_tad_alarm_write(dev, buf, ACPI_TAD_AC_TIMER);
445
446	return ret ? ret : count;
447}
448
449static ssize_t ac_alarm_show(struct device *dev, struct device_attribute *attr,
450			     char *buf)
451{
452	return acpi_tad_alarm_read(dev, buf, ACPI_TAD_AC_TIMER);
453}
454
455static DEVICE_ATTR_RW(ac_alarm);
456
457static ssize_t ac_policy_store(struct device *dev, struct device_attribute *attr,
458			       const char *buf, size_t count)
459{
460	int ret = acpi_tad_policy_write(dev, buf, ACPI_TAD_AC_TIMER);
461
462	return ret ? ret : count;
463}
464
465static ssize_t ac_policy_show(struct device *dev, struct device_attribute *attr,
466			      char *buf)
467{
468	return acpi_tad_policy_read(dev, buf, ACPI_TAD_AC_TIMER);
469}
470
471static DEVICE_ATTR_RW(ac_policy);
472
473static ssize_t ac_status_store(struct device *dev, struct device_attribute *attr,
474			       const char *buf, size_t count)
475{
476	int ret = acpi_tad_status_write(dev, buf, ACPI_TAD_AC_TIMER);
477
478	return ret ? ret : count;
479}
480
481static ssize_t ac_status_show(struct device *dev, struct device_attribute *attr,
482			      char *buf)
483{
484	return acpi_tad_status_read(dev, buf, ACPI_TAD_AC_TIMER);
485}
486
487static DEVICE_ATTR_RW(ac_status);
488
489static struct attribute *acpi_tad_attrs[] = {
490	&dev_attr_caps.attr,
491	&dev_attr_ac_alarm.attr,
492	&dev_attr_ac_policy.attr,
493	&dev_attr_ac_status.attr,
494	NULL,
495};
496static const struct attribute_group acpi_tad_attr_group = {
497	.attrs	= acpi_tad_attrs,
498};
499
500static ssize_t dc_alarm_store(struct device *dev, struct device_attribute *attr,
501			      const char *buf, size_t count)
502{
503	int ret = acpi_tad_alarm_write(dev, buf, ACPI_TAD_DC_TIMER);
504
505	return ret ? ret : count;
506}
507
508static ssize_t dc_alarm_show(struct device *dev, struct device_attribute *attr,
509			     char *buf)
510{
511	return acpi_tad_alarm_read(dev, buf, ACPI_TAD_DC_TIMER);
512}
513
514static DEVICE_ATTR_RW(dc_alarm);
515
516static ssize_t dc_policy_store(struct device *dev, struct device_attribute *attr,
517			       const char *buf, size_t count)
518{
519	int ret = acpi_tad_policy_write(dev, buf, ACPI_TAD_DC_TIMER);
520
521	return ret ? ret : count;
522}
523
524static ssize_t dc_policy_show(struct device *dev, struct device_attribute *attr,
525			      char *buf)
526{
527	return acpi_tad_policy_read(dev, buf, ACPI_TAD_DC_TIMER);
528}
529
530static DEVICE_ATTR_RW(dc_policy);
531
532static ssize_t dc_status_store(struct device *dev, struct device_attribute *attr,
533			       const char *buf, size_t count)
534{
535	int ret = acpi_tad_status_write(dev, buf, ACPI_TAD_DC_TIMER);
536
537	return ret ? ret : count;
538}
539
540static ssize_t dc_status_show(struct device *dev, struct device_attribute *attr,
541			      char *buf)
542{
543	return acpi_tad_status_read(dev, buf, ACPI_TAD_DC_TIMER);
544}
545
546static DEVICE_ATTR_RW(dc_status);
547
548static struct attribute *acpi_tad_dc_attrs[] = {
549	&dev_attr_dc_alarm.attr,
550	&dev_attr_dc_policy.attr,
551	&dev_attr_dc_status.attr,
552	NULL,
553};
554static const struct attribute_group acpi_tad_dc_attr_group = {
555	.attrs	= acpi_tad_dc_attrs,
556};
557
558static int acpi_tad_disable_timer(struct device *dev, u32 timer_id)
559{
560	return acpi_tad_wake_set(dev, "_STV", timer_id, ACPI_TAD_WAKE_DISABLED);
561}
562
563static void acpi_tad_remove(struct platform_device *pdev)
564{
565	struct device *dev = &pdev->dev;
566	acpi_handle handle = ACPI_HANDLE(dev);
567	struct acpi_tad_driver_data *dd = dev_get_drvdata(dev);
568
569	device_init_wakeup(dev, false);
570
571	if (dd->capabilities & ACPI_TAD_RT)
572		sysfs_remove_group(&dev->kobj, &acpi_tad_time_attr_group);
573
574	if (dd->capabilities & ACPI_TAD_DC_WAKE)
575		sysfs_remove_group(&dev->kobj, &acpi_tad_dc_attr_group);
576
577	sysfs_remove_group(&dev->kobj, &acpi_tad_attr_group);
578
579	scoped_guard(pm_runtime_noresume, dev) {
580		acpi_tad_disable_timer(dev, ACPI_TAD_AC_TIMER);
581		acpi_tad_clear_status(dev, ACPI_TAD_AC_TIMER);
582		if (dd->capabilities & ACPI_TAD_DC_WAKE) {
583			acpi_tad_disable_timer(dev, ACPI_TAD_DC_TIMER);
584			acpi_tad_clear_status(dev, ACPI_TAD_DC_TIMER);
585		}
586	}
587
588	pm_runtime_suspend(dev);
589	pm_runtime_disable(dev);
590	acpi_remove_cmos_rtc_space_handler(handle);
591}
592
593static int acpi_tad_probe(struct platform_device *pdev)
594{
595	struct device *dev = &pdev->dev;
596	acpi_handle handle = ACPI_HANDLE(dev);
597	struct acpi_tad_driver_data *dd;
598	acpi_status status;
599	unsigned long long caps;
600	int ret;
601
602	ret = acpi_install_cmos_rtc_space_handler(handle);
603	if (ret < 0) {
604		dev_info(dev, "Unable to install space handler\n");
605		return -ENODEV;
606	}
607	/*
608	 * Initialization failure messages are mostly about firmware issues, so
609	 * print them at the "info" level.
610	 */
611	status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps);
612	if (ACPI_FAILURE(status)) {
613		dev_info(dev, "Unable to get capabilities\n");
614		ret = -ENODEV;
615		goto remove_handler;
616	}
617
618	if (!(caps & ACPI_TAD_AC_WAKE)) {
619		dev_info(dev, "Unsupported capabilities\n");
620		ret = -ENODEV;
621		goto remove_handler;
622	}
623
624	if (!acpi_has_method(handle, "_PRW")) {
625		dev_info(dev, "Missing _PRW\n");
626		ret = -ENODEV;
627		goto remove_handler;
628	}
629
630	dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
631	if (!dd) {
632		ret = -ENOMEM;
633		goto remove_handler;
634	}
635
636	dd->capabilities = caps;
637	dev_set_drvdata(dev, dd);
638
639	/*
640	 * Assume that the ACPI PM domain has been attached to the device and
641	 * simply enable system wakeup and runtime PM and put the device into
642	 * runtime suspend.  Everything else should be taken care of by the ACPI
643	 * PM domain callbacks.
644	 */
645	device_init_wakeup(dev, true);
646	dev_pm_set_driver_flags(dev, DPM_FLAG_SMART_SUSPEND |
647				     DPM_FLAG_MAY_SKIP_RESUME);
648	/*
649	 * The platform bus type layer tells the ACPI PM domain powers up the
650	 * device, so set the runtime PM status of it to "active".
651	 */
652	pm_runtime_set_active(dev);
653	pm_runtime_enable(dev);
654	pm_runtime_suspend(dev);
655
656	ret = sysfs_create_group(&dev->kobj, &acpi_tad_attr_group);
657	if (ret)
658		goto fail;
659
660	if (caps & ACPI_TAD_DC_WAKE) {
661		ret = sysfs_create_group(&dev->kobj, &acpi_tad_dc_attr_group);
662		if (ret)
663			goto fail;
664	}
665
666	if (caps & ACPI_TAD_RT) {
667		ret = sysfs_create_group(&dev->kobj, &acpi_tad_time_attr_group);
668		if (ret)
669			goto fail;
670	}
671
672	return 0;
673
674fail:
675	acpi_tad_remove(pdev);
676	/* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */
677	return ret;
678
679remove_handler:
680	acpi_remove_cmos_rtc_space_handler(handle);
681	return ret;
682}
683
684static const struct acpi_device_id acpi_tad_ids[] = {
685	{"ACPI000E", 0},
686	{}
687};
688
689static struct platform_driver acpi_tad_driver = {
690	.driver = {
691		.name = "acpi-tad",
692		.acpi_match_table = acpi_tad_ids,
693	},
694	.probe = acpi_tad_probe,
695	.remove = acpi_tad_remove,
696};
697MODULE_DEVICE_TABLE(acpi, acpi_tad_ids);
698
699module_platform_driver(acpi_tad_driver);
~/ Read-only file preview.