acpi_tad.c (c13aca79ff3c4af5fd31a5b2743a90eba6e36a26) | acpi_tad.c (3230b2b3c1ab5a0d3f99d5850bfdc4bf48d11cdd) |
---|---|
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. --- 38 unchanged lines hidden (view full) --- 47 48/* Special value for disabled timer or expired timer wake policy. */ 49#define ACPI_TAD_WAKE_DISABLED (~(u32)0) 50 51struct acpi_tad_driver_data { 52 u32 capabilities; 53}; 54 | 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. --- 38 unchanged lines hidden (view full) --- 47 48/* Special value for disabled timer or expired timer wake policy. */ 49#define ACPI_TAD_WAKE_DISABLED (~(u32)0) 50 51struct acpi_tad_driver_data { 52 u32 capabilities; 53}; 54 |
55struct acpi_tad_rt { 56 u16 year; /* 1900 - 9999 */ 57 u8 month; /* 1 - 12 */ 58 u8 day; /* 1 - 31 */ 59 u8 hour; /* 0 - 23 */ 60 u8 minute; /* 0 - 59 */ 61 u8 second; /* 0 - 59 */ 62 u8 valid; /* 0 (failed) or 1 (success) for reads, 0 for writes */ 63 u16 msec; /* 1 - 1000 */ 64 s16 tz; /* -1440 to 1440 or 2047 (unspecified) */ 65 u8 daylight; 66 u8 padding[3]; /* must be 0 */ 67} __packed; 68 69static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt) 70{ 71 acpi_handle handle = ACPI_HANDLE(dev); 72 union acpi_object args[] = { 73 { .type = ACPI_TYPE_BUFFER, }, 74 }; 75 struct acpi_object_list arg_list = { 76 .pointer = args, 77 .count = ARRAY_SIZE(args), 78 }; 79 unsigned long long retval; 80 acpi_status status; 81 82 if (rt->year < 1900 || rt->year > 9999 || 83 rt->month < 1 || rt->month > 12 || 84 rt->hour > 23 || rt->minute > 59 || rt->second > 59 || 85 rt->tz < -1440 || (rt->tz > 1440 && rt->tz != 2047) || 86 rt->daylight > 3) 87 return -ERANGE; 88 89 args[0].buffer.pointer = (u8 *)rt; 90 args[0].buffer.length = sizeof(*rt); 91 92 pm_runtime_get_sync(dev); 93 94 status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval); 95 96 pm_runtime_put_sync(dev); 97 98 if (ACPI_FAILURE(status) || retval) 99 return -EIO; 100 101 return 0; 102} 103 104static int acpi_tad_get_real_time(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 pm_runtime_get_sync(dev); 114 115 status = acpi_evaluate_object(handle, "_GRT", NULL, &output); 116 117 pm_runtime_put_sync(dev); 118 119 if (ACPI_FAILURE(status)) 120 goto out_free; 121 122 out_obj = output.pointer; 123 if (out_obj->type != ACPI_TYPE_BUFFER) 124 goto out_free; 125 126 if (out_obj->buffer.length != sizeof(*rt)) 127 goto out_free; 128 129 data = (struct acpi_tad_rt *)(out_obj->buffer.pointer); 130 if (!data->valid) 131 goto out_free; 132 133 memcpy(rt, data, sizeof(*rt)); 134 ret = 0; 135 136out_free: 137 ACPI_FREE(output.pointer); 138 return ret; 139} 140 141static char *acpi_tad_rt_next_field(char *s, int *val) 142{ 143 char *p; 144 145 p = strchr(s, ':'); 146 if (!p) 147 return NULL; 148 149 *p = '\0'; 150 if (kstrtoint(s, 10, val)) 151 return NULL; 152 153 return p + 1; 154} 155 156static ssize_t time_store(struct device *dev, struct device_attribute *attr, 157 const char *buf, size_t count) 158{ 159 struct acpi_tad_rt rt; 160 char *str, *s; 161 int val, ret = -ENODATA; 162 163 str = kmemdup_nul(buf, count, GFP_KERNEL); 164 if (!str) 165 return -ENOMEM; 166 167 s = acpi_tad_rt_next_field(str, &val); 168 if (!s) 169 goto out_free; 170 171 rt.year = val; 172 173 s = acpi_tad_rt_next_field(s, &val); 174 if (!s) 175 goto out_free; 176 177 rt.month = val; 178 179 s = acpi_tad_rt_next_field(s, &val); 180 if (!s) 181 goto out_free; 182 183 rt.day = val; 184 185 s = acpi_tad_rt_next_field(s, &val); 186 if (!s) 187 goto out_free; 188 189 rt.hour = val; 190 191 s = acpi_tad_rt_next_field(s, &val); 192 if (!s) 193 goto out_free; 194 195 rt.minute = val; 196 197 s = acpi_tad_rt_next_field(s, &val); 198 if (!s) 199 goto out_free; 200 201 rt.second = val; 202 203 s = acpi_tad_rt_next_field(s, &val); 204 if (!s) 205 goto out_free; 206 207 rt.tz = val; 208 209 if (kstrtoint(s, 10, &val)) 210 goto out_free; 211 212 rt.daylight = val; 213 214 rt.valid = 0; 215 rt.msec = 0; 216 memset(rt.padding, 0, 3); 217 218 ret = acpi_tad_set_real_time(dev, &rt); 219 220out_free: 221 kfree(str); 222 return ret ? ret : count; 223} 224 225static ssize_t time_show(struct device *dev, struct device_attribute *attr, 226 char *buf) 227{ 228 struct acpi_tad_rt rt; 229 int ret; 230 231 ret = acpi_tad_get_real_time(dev, &rt); 232 if (ret) 233 return ret; 234 235 return sprintf(buf, "%u:%u:%u:%u:%u:%u:%d:%u\n", 236 rt.year, rt.month, rt.day, rt.hour, rt.minute, rt.second, 237 rt.tz, rt.daylight); 238} 239 240static DEVICE_ATTR(time, S_IRUSR | S_IWUSR, time_show, time_store); 241 242static struct attribute *acpi_tad_time_attrs[] = { 243 &dev_attr_time.attr, 244 NULL, 245}; 246static const struct attribute_group acpi_tad_time_attr_group = { 247 .attrs = acpi_tad_time_attrs, 248}; 249 |
|
55static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id, 56 u32 value) 57{ 58 acpi_handle handle = ACPI_HANDLE(dev); 59 union acpi_object args[] = { 60 { .type = ACPI_TYPE_INTEGER, }, 61 { .type = ACPI_TYPE_INTEGER, }, 62 }; --- 380 unchanged lines hidden (view full) --- 443 goto fail; 444 445 if (caps & ACPI_TAD_DC_WAKE) { 446 ret = sysfs_create_group(&dev->kobj, &acpi_tad_dc_attr_group); 447 if (ret) 448 goto fail; 449 } 450 | 250static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id, 251 u32 value) 252{ 253 acpi_handle handle = ACPI_HANDLE(dev); 254 union acpi_object args[] = { 255 { .type = ACPI_TYPE_INTEGER, }, 256 { .type = ACPI_TYPE_INTEGER, }, 257 }; --- 380 unchanged lines hidden (view full) --- 638 goto fail; 639 640 if (caps & ACPI_TAD_DC_WAKE) { 641 ret = sysfs_create_group(&dev->kobj, &acpi_tad_dc_attr_group); 642 if (ret) 643 goto fail; 644 } 645 |
646 if (caps & ACPI_TAD_RT) { 647 ret = sysfs_create_group(&dev->kobj, &acpi_tad_time_attr_group); 648 if (ret) 649 goto fail; 650 } 651 |
|
451 return 0; 452 453fail: 454 acpi_tad_remove(pdev); 455 return ret; 456} 457 458static const struct acpi_device_id acpi_tad_ids[] = { --- 15 unchanged lines hidden --- | 652 return 0; 653 654fail: 655 acpi_tad_remove(pdev); 656 return ret; 657} 658 659static const struct acpi_device_id acpi_tad_ids[] = { --- 15 unchanged lines hidden --- |