40d9466af129318bb7fc16ff0263e2f4bc53851c
[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
27 static ssize_t ec_fw_version_show(struct device *dev,
28                                   struct device_attribute *attr, char *buf)
29 {
30         struct chromeos_ec_device *ec = dev_get_drvdata(dev);
31         struct ec_response_get_version info;
32         const char * const copy_name[] = {"?", "RO", "RW"};
33         int ret;
34
35         ret = ec->command_recv(ec, EC_CMD_GET_VERSION, &info,
36                                sizeof(struct ec_response_get_version));
37         if (ret < 0)
38                 return ret;
39
40         if (info.current_image > EC_IMAGE_RW)
41                 info.current_image = EC_IMAGE_UNKNOWN;
42
43         return scnprintf(buf, PAGE_SIZE, "Current: %s\nRO: %s\nRW: %s\n",
44                          copy_name[info.current_image], info.version_string_ro,
45                          info.version_string_rw);
46 }
47
48 static ssize_t ec_build_info_show(struct device *dev,
49                                   struct device_attribute *attr, char *buf)
50 {
51         struct chromeos_ec_device *ec = dev_get_drvdata(dev);
52         char info[EC_HOST_PARAM_SIZE];
53         int ret;
54
55         ret = ec->command_recv(ec, EC_CMD_GET_BUILD_INFO, info, sizeof(info));
56         if (ret < 0)
57                 return ret;
58
59         return scnprintf(buf, PAGE_SIZE, "%s\n", info);
60 }
61
62 static ssize_t ec_chip_info_show(struct device *dev,
63                                  struct device_attribute *attr, char *buf)
64 {
65         struct chromeos_ec_device *ec = dev_get_drvdata(dev);
66         struct ec_response_get_chip_info info;
67         int ret;
68
69         ret = ec->command_recv(ec, EC_CMD_GET_CHIP_INFO, &info,
70                                sizeof(struct ec_response_get_chip_info));
71         if (ret < 0)
72                 return ret;
73
74         return scnprintf(buf, PAGE_SIZE, "%s %s %s\n",
75                          info.vendor, info.name, info.revision);
76 }
77
78 static ssize_t ec_dev_usb_store(struct device *dev,
79                                 struct device_attribute *attr,
80                                 const char *buf, size_t count)
81 {
82         int err;
83         err = chromeos_set_dev_usb();
84         if (err)
85                 return err;
86         return count;
87 }
88
89 static DEVICE_ATTR(fw_version, S_IRUGO, ec_fw_version_show, NULL);
90 static DEVICE_ATTR(build_info, S_IRUGO, ec_build_info_show, NULL);
91 static DEVICE_ATTR(chip_info, S_IRUGO, ec_chip_info_show, NULL);
92 static DEVICE_ATTR(dev_usb, S_IWUGO, NULL, ec_dev_usb_store);
93
94 static struct attribute *ec_fw_attrs[] = {
95         &dev_attr_fw_version.attr,
96         &dev_attr_build_info.attr,
97         &dev_attr_chip_info.attr,
98         NULL
99 };
100
101 static const struct attribute_group ec_fw_attr_group = {
102         .attrs = ec_fw_attrs,
103 };
104
105 static int __devinit ec_fw_probe(struct platform_device *pdev)
106 {
107         struct chromeos_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
108         struct device *dev = ec->dev;
109         int err;
110
111         err = sysfs_create_group(&dev->kobj, &ec_fw_attr_group);
112         if (err) {
113                 dev_warn(dev, "error creating sysfs entries.\n");
114                 return err;
115         }
116
117         dev_dbg(dev, "Chrome EC Firmware Information\n");
118
119         return 0;
120 }
121
122 static int __devexit ec_fw_remove(struct platform_device *pdev)
123 {
124         struct chromeos_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
125
126         sysfs_remove_group(&ec->dev->kobj, &ec_fw_attr_group);
127
128         return 0;
129 }
130
131 static struct platform_driver ec_fw_driver = {
132         .probe = ec_fw_probe,
133         .remove = __devexit_p(ec_fw_remove),
134         .driver = {
135                 .name = "cros_ec-fw",
136         },
137 };
138
139 module_platform_driver(ec_fw_driver);
140
141 MODULE_LICENSE("GPL");
142 MODULE_DESCRIPTION("ChromeOS EC firmware");
143 MODULE_ALIAS("platform:cros_ec-fw");