45db69dc00ab2f20422093e590f8c91168cb5265
[cascardo/linux.git] / drivers / platform / chromeos_ec-fw.c
1 /*
2  *  Copyright (C) 2012 Google, Inc
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *
19  * Expose the ChromeOS EC firmware information.
20  */
21
22 #include <linux/module.h>
23 #include <linux/mfd/chromeos_ec.h>
24 #include <linux/mfd/chromeos_ec_commands.h>
25 #include <linux/platform_device.h>
26 #include <linux/chromeos_platform.h>
27
28 static ssize_t ec_fw_version_show(struct device *dev,
29                                   struct device_attribute *attr, char *buf)
30 {
31         struct chromeos_ec_device *ec = dev_get_drvdata(dev);
32         struct ec_response_get_version info;
33         const char * const copy_name[] = {"?", "RO", "RW"};
34         int ret;
35
36         ret = ec->command_recv(ec, EC_CMD_GET_VERSION, &info,
37                                sizeof(struct ec_response_get_version));
38         if (ret < 0)
39                 return ret;
40
41         if (info.current_image > EC_IMAGE_RW)
42                 info.current_image = EC_IMAGE_UNKNOWN;
43
44         return scnprintf(buf, PAGE_SIZE, "Current: %s\nRO: %s\nRW: %s\n",
45                          copy_name[info.current_image], info.version_string_ro,
46                          info.version_string_rw);
47 }
48
49 static ssize_t ec_build_info_show(struct device *dev,
50                                   struct device_attribute *attr, char *buf)
51 {
52         struct chromeos_ec_device *ec = dev_get_drvdata(dev);
53         char info[EC_HOST_PARAM_SIZE];
54         int ret;
55
56         ret = ec->command_recv(ec, EC_CMD_GET_BUILD_INFO, info, sizeof(info));
57         if (ret < 0)
58                 return ret;
59
60         return scnprintf(buf, PAGE_SIZE, "%s\n", info);
61 }
62
63 static ssize_t ec_chip_info_show(struct device *dev,
64                                  struct device_attribute *attr, char *buf)
65 {
66         struct chromeos_ec_device *ec = dev_get_drvdata(dev);
67         struct ec_response_get_chip_info info;
68         int ret;
69
70         ret = ec->command_recv(ec, EC_CMD_GET_CHIP_INFO, &info,
71                                sizeof(struct ec_response_get_chip_info));
72         if (ret < 0)
73                 return ret;
74
75         return scnprintf(buf, PAGE_SIZE, "%s %s %s\n",
76                          info.vendor, info.name, info.revision);
77 }
78
79 static ssize_t ec_dev_usb_store(struct device *dev,
80                                 struct device_attribute *attr,
81                                 const char *buf, size_t count)
82 {
83         int err;
84         err = chromeos_set_dev_usb();
85         if (err)
86                 return err;
87         return count;
88 }
89
90 static DEVICE_ATTR(fw_version, S_IRUGO, ec_fw_version_show, NULL);
91 static DEVICE_ATTR(build_info, S_IRUGO, ec_build_info_show, NULL);
92 static DEVICE_ATTR(chip_info, S_IRUGO, ec_chip_info_show, NULL);
93 static DEVICE_ATTR(dev_usb, S_IWUGO, NULL, ec_dev_usb_store);
94
95 static struct attribute *ec_fw_attrs[] = {
96         &dev_attr_fw_version.attr,
97         &dev_attr_build_info.attr,
98         &dev_attr_chip_info.attr,
99         NULL
100 };
101
102 static const struct attribute_group ec_fw_attr_group = {
103         .attrs = ec_fw_attrs,
104 };
105
106 static int __devinit ec_fw_probe(struct platform_device *pdev)
107 {
108         struct chromeos_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
109         struct device *dev = ec->dev;
110         int err;
111
112         err = sysfs_create_group(&dev->kobj, &ec_fw_attr_group);
113         if (err) {
114                 dev_warn(dev, "error creating sysfs entries.\n");
115                 return err;
116         }
117
118         dev_dbg(dev, "Chrome EC Firmware Information\n");
119
120         return 0;
121 }
122
123 static int __devexit ec_fw_remove(struct platform_device *pdev)
124 {
125         struct chromeos_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
126
127         sysfs_remove_group(&ec->dev->kobj, &ec_fw_attr_group);
128
129         return 0;
130 }
131
132 static struct platform_driver ec_fw_driver = {
133         .probe = ec_fw_probe,
134         .remove = __devexit_p(ec_fw_remove),
135         .driver = {
136                 .name = "cros_ec-fw",
137         },
138 };
139
140 module_platform_driver(ec_fw_driver);
141
142 MODULE_LICENSE("GPL");
143 MODULE_DESCRIPTION("ChromeOS EC firmware");
144 MODULE_ALIAS("platform:cros_ec-fw");