CHROMIUM: chromeos_acpi: Enable USB wake from S3
[cascardo/linux.git] / drivers / platform / x86 / chromeos_acpi.c
1  /*
2  *  chromeos_acpi.c - ChromeOS specific ACPI support
3  *
4  *
5  * Copyright (C) 2011 The Chromium OS Authors
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * This driver attaches to the ChromeOS ACPI device and the exports the values
22  * reported by the ACPI in a sysfs directory
23  * (/sys/devices/platform/chromeos_acpi).
24  *
25  * The first version of the driver provides only static information; the
26  * values reported by the driver are the snapshot reported by the ACPI at
27  * driver installation time.
28  *
29  * All values are presented in the string form (numbers as decimal values) and
30  * can be accessed as the contents of the appropriate read only files in the
31  * sysfs directory tree originating in /sys/devices/platform/chromeos_acpi.
32  */
33
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/nvram.h>
37 #include <linux/platform_device.h>
38 #include <linux/acpi.h>
39
40 #include "../chromeos.h"
41
42 #define CHNV_DEBUG_RESET_FLAG   0x40         /* flag for S3 reboot */
43 #define CHNV_RECOVERY_FLAG      0x80         /* flag for recovery reboot */
44
45 #define CHSW_RECOVERY_FW        0x00000002   /* recovery button depressed */
46 #define CHSW_RECOVERY_EC        0x00000004   /* recovery button depressed */
47 #define CHSW_DEVELOPER_MODE     0x00000020   /* developer switch set */
48 #define CHSW_WP                 0x00000200   /* write-protect (optional) */
49
50 /*
51  * Structure containing one ACPI exported integer along with the validity
52  * flag.
53  */
54 struct chromeos_acpi_datum {
55         unsigned cad_value;
56         bool     cad_is_set;
57 };
58
59 /*
60  * Structure containing the set of ACPI exported integers required by chromeos
61  * wrapper.
62  */
63 struct chromeos_acpi_if {
64         struct chromeos_acpi_datum      switch_state;
65
66         /* chnv is a single byte offset in nvram. exported by older firmware */
67         struct chromeos_acpi_datum      chnv;
68
69         /* vbnv is an address range in nvram, exported by newer firmware */
70         struct chromeos_acpi_datum      nv_base;
71         struct chromeos_acpi_datum      nv_size;
72 };
73
74 #define MY_LOGPREFIX "chromeos_acpi: "
75 #define MY_ERR KERN_ERR MY_LOGPREFIX
76 #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
77 #define MY_INFO KERN_INFO MY_LOGPREFIX
78
79 /* ACPI method name for MLST; the response for this method is a
80  * package of strings listing the methods which should be reflected in
81  * sysfs. */
82 #define MLST_METHOD "MLST"
83
84 static const struct acpi_device_id chromeos_device_ids[] = {
85         {"GGL0001", 0}, /* Google's own */
86         {"", 0},
87 };
88
89 MODULE_DEVICE_TABLE(acpi, chromeos_device_ids);
90
91 static int chromeos_device_add(struct acpi_device *device);
92 static int chromeos_device_remove(struct acpi_device *device, int type);
93
94 static struct chromeos_acpi_if chromeos_acpi_if_data;
95 static struct acpi_driver chromeos_acpi_driver = {
96         .name = "ChromeOS Device",
97         .class = "ChromeOS",
98         .ids = chromeos_device_ids,
99         .ops = {
100                 .add = chromeos_device_add,
101                 .remove = chromeos_device_remove,
102                 },
103         .owner = THIS_MODULE,
104 };
105
106 /* The default list of methods the chromeos ACPI device is supposed to export,
107  * if the MLST method is not present or is poorly formed.  The MLST method
108  * itself is included, to aid in debugging. */
109 static char *default_methods[] = {
110         "CHSW", "HWID", "BINF", "GPIO", "CHNV", "FWID", "FRID", MLST_METHOD
111 };
112
113 /*
114  * Representation of a single sys fs attribute. In addition to the standard
115  * device_attribute structure has a link field, allowing to create a list of
116  * these structures (to keep track for de-allocation when removing the driver)
117  * and a pointer to the actual attribute value, reported when accessing the
118  * appropriate sys fs file
119  */
120 struct acpi_attribute {
121         struct device_attribute dev_attr;
122         struct acpi_attribute *next_acpi_attr;
123         char *value;
124 };
125
126 /*
127  * Representation of a sys fs attribute group (a sub directory in the device's
128  * sys fs directory). In addition to the standard structure has a link to
129  * allow to keep track of the allocated structures.
130  */
131 struct acpi_attribute_group {
132         struct attribute_group ag;
133         struct acpi_attribute_group *next_acpi_attr_group;
134 };
135
136 /*
137  * ChromeOS ACPI device wrapper adds links pointing at lists of allocated
138  * attributes and attribute groups.
139  */
140 struct chromeos_acpi_dev {
141         struct platform_device *p_dev;
142         struct acpi_attribute *attributes;
143         struct acpi_attribute_group *groups;
144 };
145
146 static struct chromeos_acpi_dev chromeos_acpi = { };
147
148 static bool chromeos_on_legacy_firmware(void)
149 {
150         /*
151          * Presense of the CHNV ACPI element implies running on a legacy
152          * firmware
153          */
154         return chromeos_acpi_if_data.chnv.cad_is_set;
155 }
156
157 /*
158  * This function operates on legacy BIOSes which do not export VBNV element
159  * through ACPI. These BIOSes use a fixed location in NVRAM to contain a
160  * bitmask of known flags.
161  *
162  * @flag - the bitmask to set, it is the responsibility of the caller to set
163  *         the proper bits.
164  *
165  * returns 0 on success (is running in legacy mode and chnv is initialized) or
166  *         -1 otherwise.
167  */
168 static int chromeos_set_nvram_flag(u8 flag)
169 {
170         u8 cur;
171         unsigned index = chromeos_acpi_if_data.chnv.cad_value;
172
173         if (!chromeos_on_legacy_firmware())
174                 return -ENODEV;
175
176         cur = nvram_read_byte(index);
177
178         if ((cur & flag) != flag)
179                 nvram_write_byte(cur | flag, index);
180         return 0;
181 }
182
183 int chromeos_legacy_set_need_recovery(void)
184 {
185         return chromeos_set_nvram_flag(CHNV_RECOVERY_FLAG);
186 }
187
188 /*
189  * Read the nvram buffer contents into the user provided space.
190  *
191  * retrun number of bytes copied, or -1 on any error.
192  */
193 static ssize_t chromeos_vbc_nvram_read(void *buf, size_t count)
194 {
195
196         int base, size, i;
197
198         if (!chromeos_acpi_if_data.nv_base.cad_is_set ||
199             !chromeos_acpi_if_data.nv_size.cad_is_set) {
200                 printk(MY_ERR "%s: NVRAM not configured!\n", __func__);
201                 return -ENODEV;
202         }
203
204         base = chromeos_acpi_if_data.nv_base.cad_value;
205         size = chromeos_acpi_if_data.nv_size.cad_value;
206
207         if (count < size) {
208                 pr_err("%s: not enough room to read nvram (%zd < %d)\n",
209                        __func__, count, size);
210                 return -EINVAL;
211         }
212
213         for (i = 0; i < size; i++)
214                 ((u8 *)buf)[i] = nvram_read_byte(base++);
215
216         return size;
217 }
218
219 static ssize_t chromeos_vbc_nvram_write(const void *buf, size_t count)
220 {
221         unsigned base, size, i;
222
223         if (!chromeos_acpi_if_data.nv_base.cad_is_set ||
224             !chromeos_acpi_if_data.nv_size.cad_is_set) {
225                 printk(MY_ERR "%s: NVRAM not configured!\n", __func__);
226                 return -ENODEV;
227         }
228
229         size = chromeos_acpi_if_data.nv_size.cad_value;
230         base = chromeos_acpi_if_data.nv_base.cad_value;
231
232         if (count != size) {
233                 printk(MY_ERR "%s: wrong buffer size (%zd != %d)!\n", __func__,
234                        count, size);
235                 return -EINVAL;
236         }
237
238         for (i = 0; i < size; i++) {
239                 u8 c;
240
241                 c = nvram_read_byte(base + i);
242                 if (c == ((u8 *)buf)[i])
243                         continue;
244                 nvram_write_byte(((u8 *)buf)[i], base + i);
245         }
246         return size;
247 }
248
249 /*
250  * To show attribute value just access the container structure's `value'
251  * field.
252  */
253 static ssize_t show_acpi_attribute(struct device *dev,
254                                    struct device_attribute *attr, char *buf)
255 {
256         struct acpi_attribute *paa;
257
258         paa = container_of(attr, struct acpi_attribute, dev_attr);
259         return snprintf(buf, PAGE_SIZE, paa->value);
260 }
261
262 /*
263  * create_sysfs_attribute() create and initialize an ACPI sys fs attribute
264  *                          structure.
265  * @value: attribute value
266  * @name: base attribute name
267  * @count: total number of instances of this attribute
268  * @instance: instance number of this particular attribute
269  *
270  * This function allocates and initializes the structure containing all
271  * information necessary to add a sys fs attribute. In case the attribute has
272  * just a single instance, the attribute file name is equal to the @name
273  * parameter . In case the attribute has several instances, the attribute
274  * file name is @name.@instance.
275  *
276  * Returns: a pointer to the allocated and initialized structure, or null if
277  * allocation failed.
278  *
279  * As a side effect, the allocated structure is added to the list in the
280  * chromeos_acpi structure. Note that the actual attribute creation is not
281  * attempted yet, in case of creation error the structure would not have an
282  * actual attribute associated with it, so when de-installing the driver this
283  * structure would be used to try to remove an attribute which does not exist.
284  * This is considered acceptable, as there is no reason for sys fs attribute
285  * creation failure.
286  */
287 static struct acpi_attribute *create_sysfs_attribute(char *value, char *name,
288                                                      int count, int instance)
289 {
290         struct acpi_attribute *paa;
291         int total_size, room_left;
292         int value_len = strlen(value);
293
294         if (!value_len)
295                 return NULL;
296
297         value_len++; /* include the terminating zero */
298
299         /*
300          * total allocation size includes (all strings with including
301          * terminating zeros):
302          *
303          * - value string
304          * - attribute structure size
305          * - name string
306          * - suffix string (in case there are multiple instances)
307          * - dot separating the instance suffix
308          */
309
310         total_size = value_len + sizeof(struct acpi_attribute) +
311                         strlen(name) + 1;
312
313         if (count != 1) {
314                 if (count >= 1000) {
315                         printk(MY_ERR "%s: too many (%d) instances of %s\n",
316                                __func__, count, name);
317                         return NULL;
318                 }
319                 /* allow up to three digits and the dot */
320                 total_size += 4;
321         }
322
323         paa = kzalloc(total_size, GFP_KERNEL);
324         if (!paa) {
325                 printk(MY_ERR "out of memory in %s!\n", __func__);
326                 return NULL;
327         }
328
329         sysfs_attr_init(&paa->dev_attr.attr);
330         paa->dev_attr.attr.mode = 0444;  /* read only */
331         paa->dev_attr.show = show_acpi_attribute;
332         paa->value = (char *)(paa + 1);
333         strcpy(paa->value, value);
334         paa->dev_attr.attr.name = paa->value + value_len;
335
336         room_left = total_size - value_len -
337                         offsetof(struct acpi_attribute, value);
338
339         if (count == 1) {
340                 snprintf((char *)paa->dev_attr.attr.name, room_left, name);
341         } else {
342                 snprintf((char *)paa->dev_attr.attr.name, room_left,
343                          "%s.%d", name, instance);
344         }
345
346         paa->next_acpi_attr = chromeos_acpi.attributes;
347         chromeos_acpi.attributes = paa;
348
349         return paa;
350 }
351
352 /*
353  * add_sysfs_attribute() create and initialize an ACPI sys fs attribute
354  *                          structure and create the attribute.
355  * @value: attribute value
356  * @name: base attribute name
357  * @count: total number of instances of this attribute
358  * @instance: instance number of this particular attribute
359  */
360
361 static void add_sysfs_attribute(char *value, char *name,
362                                 int count, int instance)
363 {
364         struct acpi_attribute *paa =
365             create_sysfs_attribute(value, name, count, instance);
366
367         if (!paa)
368                 return;
369
370         if (device_create_file(&chromeos_acpi.p_dev->dev, &paa->dev_attr))
371                 printk(MY_ERR "failed to create attribute for %s\n", name);
372 }
373
374 /*
375  * handle_nested_acpi_package() create sysfs group including attributes
376  *                              representing a nested ACPI package.
377  *
378  * @po: package contents as returned by ACPI
379  * @pm: name of the group
380  * @total: number of instances of this package
381  * @instance: instance number of this particular group
382  *
383  * The created group is called @pm in case there is a single instance, or
384  * @pm.@instance otherwise.
385  *
386  * All group and attribute storage allocations are included in the lists for
387  * tracking of allocated memory.
388  */
389 static void handle_nested_acpi_package(union acpi_object *po, char *pm,
390                                        int total, int instance)
391 {
392         int i, size, count, j;
393         struct acpi_attribute_group *aag;
394
395         count = po->package.count;
396
397         size = strlen(pm) + 1 + sizeof(struct acpi_attribute_group) +
398             sizeof(struct attribute *) * (count + 1);
399
400         if (total != 1) {
401                 if (total >= 1000) {
402                         printk(MY_ERR "%s: too many (%d) instances of %s\n",
403                                __func__, total, pm);
404                         return;
405                 }
406                 /* allow up to three digits and the dot */
407                 size += 4;
408         }
409
410         aag = kzalloc(size, GFP_KERNEL);
411         if (!aag) {
412                 printk(MY_ERR "out of memory in %s!\n", __func__);
413                 return;
414         }
415
416         aag->next_acpi_attr_group = chromeos_acpi.groups;
417         chromeos_acpi.groups = aag->next_acpi_attr_group;
418         aag->ag.attrs = (struct attribute **)(aag + 1);
419         aag->ag.name = (const char *)&aag->ag.attrs[count + 1];
420
421         /* room left in the buffer */
422         size = size - (aag->ag.name - (char *)aag);
423
424         if (total != 1)
425                 snprintf((char *)aag->ag.name, size, "%s.%d", pm, instance);
426         else
427                 snprintf((char *)aag->ag.name, size, "%s", pm);
428
429         j = 0;                  /* attribute index */
430         for (i = 0; i < count; i++) {
431                 union acpi_object *element = po->package.elements + i;
432                 int copy_size = 0;
433                 char attr_value[40];    /* 40 chars be enough for names */
434                 struct acpi_attribute *paa;
435
436                 switch (element->type) {
437                 case ACPI_TYPE_INTEGER:
438                         copy_size = snprintf(attr_value, sizeof(attr_value),
439                                              "%d", (int)element->integer.value);
440                         paa = create_sysfs_attribute(attr_value, pm, count, i);
441                         break;
442
443                 case ACPI_TYPE_STRING:
444                         copy_size = min(element->string.length,
445                                         (u32)(sizeof(attr_value)) - 1);
446                         memcpy(attr_value, element->string.pointer, copy_size);
447                         attr_value[copy_size] = '\0';
448                         paa = create_sysfs_attribute(attr_value, pm, count, i);
449                         break;
450
451                 default:
452                         printk(MY_ERR "ignoring nested type %d\n",
453                                element->type);
454                         continue;
455                 }
456                 aag->ag.attrs[j++] = &paa->dev_attr.attr;
457         }
458
459         if (sysfs_create_group(&chromeos_acpi.p_dev->dev.kobj, &aag->ag))
460                 printk(MY_ERR "failed to create group %s.%d\n", pm, instance);
461 }
462
463 /*
464  * maybe_export_acpi_int() export a single int value when required
465  *
466  * @pm: name of the package
467  * @index: index of the element of the package
468  * @value: value of the element
469  */
470 static void maybe_export_acpi_int(const char *pm, int index, unsigned value)
471 {
472         int i;
473         struct chromeos_acpi_exported_ints {
474                 const char *acpi_name;
475                 int acpi_index;
476                 struct chromeos_acpi_datum *cad;
477         } exported_ints[] = {
478                 { "VBNV", 0, &chromeos_acpi_if_data.nv_base },
479                 { "VBNV", 1, &chromeos_acpi_if_data.nv_size },
480                 { "CHSW", 0, &chromeos_acpi_if_data.switch_state },
481                 { "CHNV", 0, &chromeos_acpi_if_data.chnv }
482         };
483
484         for (i = 0; i < ARRAY_SIZE(exported_ints); i++) {
485                 struct chromeos_acpi_exported_ints *exported_int;
486
487                 exported_int = exported_ints + i;
488
489                 if (!strncmp(pm, exported_int->acpi_name, 4) &&
490                     (exported_int->acpi_index == index)) {
491                         printk(MY_NOTICE "registering %s %d\n", pm, index);
492                         exported_int->cad->cad_value = value;
493                         exported_int->cad->cad_is_set = true;
494                         return;
495                 }
496         }
497 }
498
499 /*
500  * acpi_buffer_to_string() convert contents of an ACPI buffer element into a
501  *              hex string truncating it if necessary to fit into one page.
502  *
503  * @element: an acpi element known to contain an ACPI buffer.
504  *
505  * Returns: pointer to an ASCII string containing the buffer representation
506  *          (whatever fit into PAGE_SIZE). The caller is responsible for
507  *          freeing the memory.
508  */
509 static char *acpi_buffer_to_string(union acpi_object *element)
510 {
511         char *base, *p;
512         int i;
513         unsigned room_left;
514         /* Include this many characters per line */
515         unsigned char_per_line = 16;
516         unsigned blob_size;
517         unsigned string_buffer_size;
518
519         /*
520          * As of now the VDAT structure can supply as much as 3700 bytes. When
521          * expressed as a hex dump it becomes 3700 * 3 + 3700/16 + .. which
522          * clearly exceeds the maximum allowed sys fs buffer size of one page
523          * (4k).
524          *
525          * What this means is that we can't keep the entire blob in one sysfs
526          * file. Currently verified boot (the consumer of the VDAT contents)
527          * does not care about the most of the data, so as a quick fix we will
528          * truncate it here. Once the blob data beyond the 4K boundary is
529          * required this approach will have to be reworked.
530          *
531          * TODO(vbendeb): Split the data into multiple VDAT instances, each
532          * not exceeding 4K or consider exporting as a binary using
533          * sysfs_create_bin_file().
534          */
535
536         /*
537          * X, the maximum number of bytes which will fit into a sysfs file
538          * (one memory page) can be derived from the following equation (where
539          * N is number of bytes included in every hex string):
540          *
541          * 3X + X/N + 4 <= PAGE_SIZE.
542          *
543          * Solving this for X gives the following
544          */
545         blob_size = ((PAGE_SIZE - 4) * char_per_line) / (char_per_line * 3 + 1);
546
547         if (element->buffer.length > blob_size)
548                 printk(MY_INFO "truncating buffer from %d to %d\n",
549                        element->buffer.length, blob_size);
550         else
551                 blob_size = element->buffer.length;
552
553         string_buffer_size =
554                 /* three characters to display one byte */
555                 blob_size * 3 +
556                 /* one newline per line, all rounded up, plus
557                  * extra newline in the end, plus terminating
558                  * zero, hence + 4
559                  */
560                 blob_size/char_per_line + 4;
561
562         p = kzalloc(string_buffer_size, GFP_KERNEL);
563         if (!p) {
564                 printk(MY_ERR "out of memory in %s!\n", __func__);
565                 return NULL;
566         }
567
568         base = p;
569         room_left = string_buffer_size;
570         for (i = 0; i < blob_size; i++) {
571                 int printed;
572                 printed = snprintf(p, room_left, " %2.2x",
573                                    element->buffer.pointer[i]);
574                 room_left -= printed;
575                 p += printed;
576                 if (((i + 1) % char_per_line) == 0) {
577                         if (!room_left)
578                                 break;
579                         room_left--;
580                         *p++ = '\n';
581                 }
582         }
583         if (room_left < 2) {
584                 printk(MY_ERR "%s: no room in the buffer!\n", __func__);
585                 *p = '\0';
586         } else {
587                 *p++ = '\n';
588                 *p++ = '\0';
589         }
590         return base;
591 }
592
593 /*
594  * handle_acpi_package() create sysfs group including attributes
595  *                       representing an ACPI package.
596  *
597  * @po: package contents as returned by ACPI
598  * @pm: name of the group
599  *
600  * Scalar objects included in the package get sys fs attributes created for
601  * them. Nested packages are passed to a function creating a sys fs group per
602  * package.
603  */
604 static void handle_acpi_package(union acpi_object *po, char *pm)
605 {
606         int j;
607         int count = po->package.count;
608         for (j = 0; j < count; j++) {
609                 union acpi_object *element = po->package.elements + j;
610                 int copy_size = 0;
611                 char attr_value[256];   /* strings could be this long */
612
613                 switch (element->type) {
614                 case ACPI_TYPE_INTEGER:
615                         copy_size = snprintf(attr_value, sizeof(attr_value),
616                                              "%d", (int)element->integer.value);
617                         add_sysfs_attribute(attr_value, pm, count, j);
618                         maybe_export_acpi_int(pm, j, (unsigned)
619                                               element->integer.value);
620                         break;
621
622                 case ACPI_TYPE_STRING:
623                         copy_size = min(element->string.length,
624                                         (u32)(sizeof(attr_value)) - 1);
625                         memcpy(attr_value, element->string.pointer, copy_size);
626                         attr_value[copy_size] = '\0';
627                         add_sysfs_attribute(attr_value, pm, count, j);
628                         break;
629
630                 case ACPI_TYPE_BUFFER: {
631                         char *buf_str;
632                         buf_str = acpi_buffer_to_string(element);
633                         if (buf_str) {
634                                 add_sysfs_attribute(buf_str, pm, count, j);
635                                 kfree(buf_str);
636                         }
637                         break;
638                 }
639                 case ACPI_TYPE_PACKAGE:
640                         handle_nested_acpi_package(element, pm, count, j);
641                         break;
642
643                 default:
644                         printk(MY_ERR "ignoring type %d (%s)\n",
645                                element->type, pm);
646                         break;
647                 }
648         }
649 }
650
651
652 /*
653  * add_acpi_method() evaluate an ACPI method and create sysfs attributes.
654  *
655  * @device: ACPI device
656  * @pm: name of the method to evaluate
657  */
658 static void add_acpi_method(struct acpi_device *device, char *pm)
659 {
660         acpi_status status;
661         struct acpi_buffer output;
662         union acpi_object *po;
663
664         output.length = ACPI_ALLOCATE_BUFFER;
665         output.pointer = NULL;
666
667         status = acpi_evaluate_object(device->handle, pm, NULL, &output);
668
669         if (!ACPI_SUCCESS(status)) {
670                 printk(MY_ERR "failed to retrieve %s (%d)\n", pm, status);
671                 return;
672         }
673
674         po = output.pointer;
675
676         if (po->type != ACPI_TYPE_PACKAGE)
677                 printk(MY_ERR "%s is not a package, ignored\n", pm);
678         else
679                 handle_acpi_package(po, pm);
680         kfree(output.pointer);
681 }
682
683 /*
684  * chromeos_process_mlst() Evaluate the MLST method and add methods listed
685  *                         in the response.
686  *
687  * @device: ACPI device
688  *
689  * Returns: 0 if successful, non-zero if error.
690  */
691 static int chromeos_process_mlst(struct acpi_device *device)
692 {
693         acpi_status status;
694         struct acpi_buffer output;
695         union acpi_object *po;
696         int j;
697
698         output.length = ACPI_ALLOCATE_BUFFER;
699         output.pointer = NULL;
700
701         status = acpi_evaluate_object(device->handle, MLST_METHOD, NULL,
702                                       &output);
703         if (!ACPI_SUCCESS(status)) {
704                 pr_debug(MY_LOGPREFIX "failed to retrieve MLST (%d)\n",
705                          status);
706                 return 1;
707         }
708
709         po = output.pointer;
710         if (po->type != ACPI_TYPE_PACKAGE) {
711                 printk(MY_ERR MLST_METHOD "is not a package, ignored\n");
712                 kfree(output.pointer);
713                 return -EINVAL;
714         }
715
716         for (j = 0; j < po->package.count; j++) {
717                 union acpi_object *element = po->package.elements + j;
718                 int copy_size = 0;
719                 char method[ACPI_NAME_SIZE + 1];
720
721                 if (element->type == ACPI_TYPE_STRING) {
722                         copy_size = min(element->string.length,
723                                         (u32)ACPI_NAME_SIZE);
724                         memcpy(method, element->string.pointer, copy_size);
725                         method[copy_size] = '\0';
726                         add_acpi_method(device, method);
727                 } else {
728                         pr_debug(MY_LOGPREFIX "ignoring type %d\n",
729                                  element->type);
730                 }
731         }
732
733         kfree(output.pointer);
734         return 0;
735 }
736
737 static int chromeos_device_add(struct acpi_device *device)
738 {
739         int i;
740
741         /* Attempt to add methods by querying the device's MLST method
742          * for the list of methods. */
743         if (!chromeos_process_mlst(device))
744                 return 0;
745
746         printk(MY_INFO "falling back to default list of methods\n");
747         for (i = 0; i < ARRAY_SIZE(default_methods); i++)
748                 add_acpi_method(device, default_methods[i]);
749         return 0;
750 }
751
752 static int chromeos_device_remove(struct acpi_device *device, int type)
753 {
754         return 0;
755 }
756
757 static struct chromeos_vbc chromeos_vbc_nvram = {
758         .name = "chromeos_vbc_nvram",
759         .read = chromeos_vbc_nvram_read,
760         .write = chromeos_vbc_nvram_write,
761 };
762
763 static int __init chromeos_acpi_init(void)
764 {
765         int ret = 0;
766         acpi_status status;
767
768         if (acpi_disabled)
769                 return -ENODEV;
770
771         ret = chromeos_vbc_register(&chromeos_vbc_nvram);
772         if (ret)
773                 return ret;
774
775         chromeos_acpi.p_dev = platform_device_register_simple("chromeos_acpi",
776                                                               -1, NULL, 0);
777         if (IS_ERR(chromeos_acpi.p_dev)) {
778                 printk(MY_ERR "unable to register platform device\n");
779                 return PTR_ERR(chromeos_acpi.p_dev);
780         }
781
782         ret = acpi_bus_register_driver(&chromeos_acpi_driver);
783         if (ret < 0) {
784                 printk(MY_ERR "failed to register driver (%d)\n", ret);
785                 platform_device_unregister(chromeos_acpi.p_dev);
786                 chromeos_acpi.p_dev = NULL;
787                 return ret;
788         }
789         printk(MY_INFO "installed%s\n",
790                chromeos_on_legacy_firmware() ? " (legacy mode)" : "");
791
792         printk(MY_INFO "chromeos_acpi: enabling S3 USB wake\n");
793         status = acpi_evaluate_object(NULL, "\\S3UE", NULL, NULL);
794         if (!ACPI_SUCCESS(status))
795                 printk(MY_INFO "chromeos_acpi: failed to enable S3 USB wake\n");
796
797         return 0;
798 }
799
800 subsys_initcall(chromeos_acpi_init);