diff options
Diffstat (limited to 'drivers/platform/chrome/cros_ec_sysfs.c')
-rw-r--r-- | drivers/platform/chrome/cros_ec_sysfs.c | 178 |
1 files changed, 102 insertions, 76 deletions
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index fb62ab6cc659..f3baf9973989 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/printk.h> | 31 | #include <linux/printk.h> |
32 | #include <linux/slab.h> | ||
32 | #include <linux/stat.h> | 33 | #include <linux/stat.h> |
33 | #include <linux/types.h> | 34 | #include <linux/types.h> |
34 | #include <linux/uaccess.h> | 35 | #include <linux/uaccess.h> |
@@ -66,13 +67,19 @@ static ssize_t store_ec_reboot(struct device *dev, | |||
66 | {"hibernate", EC_REBOOT_HIBERNATE, 0}, | 67 | {"hibernate", EC_REBOOT_HIBERNATE, 0}, |
67 | {"at-shutdown", -1, EC_REBOOT_FLAG_ON_AP_SHUTDOWN}, | 68 | {"at-shutdown", -1, EC_REBOOT_FLAG_ON_AP_SHUTDOWN}, |
68 | }; | 69 | }; |
69 | struct cros_ec_command msg = { 0 }; | 70 | struct cros_ec_command *msg; |
70 | struct ec_params_reboot_ec *param = | 71 | struct ec_params_reboot_ec *param; |
71 | (struct ec_params_reboot_ec *)msg.outdata; | ||
72 | int got_cmd = 0, offset = 0; | 72 | int got_cmd = 0, offset = 0; |
73 | int i; | 73 | int i; |
74 | int ret; | 74 | int ret; |
75 | struct cros_ec_device *ec = dev_get_drvdata(dev); | 75 | struct cros_ec_dev *ec = container_of(dev, |
76 | struct cros_ec_dev, class_dev); | ||
77 | |||
78 | msg = kmalloc(sizeof(*msg) + sizeof(*param), GFP_KERNEL); | ||
79 | if (!msg) | ||
80 | return -ENOMEM; | ||
81 | |||
82 | param = (struct ec_params_reboot_ec *)msg->data; | ||
76 | 83 | ||
77 | param->flags = 0; | 84 | param->flags = 0; |
78 | while (1) { | 85 | while (1) { |
@@ -100,19 +107,26 @@ static ssize_t store_ec_reboot(struct device *dev, | |||
100 | offset++; | 107 | offset++; |
101 | } | 108 | } |
102 | 109 | ||
103 | if (!got_cmd) | 110 | if (!got_cmd) { |
104 | return -EINVAL; | 111 | count = -EINVAL; |
105 | 112 | goto exit; | |
106 | msg.command = EC_CMD_REBOOT_EC; | ||
107 | msg.outsize = sizeof(param); | ||
108 | ret = cros_ec_cmd_xfer(ec, &msg); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | if (msg.result != EC_RES_SUCCESS) { | ||
112 | dev_dbg(ec->dev, "EC result %d\n", msg.result); | ||
113 | return -EINVAL; | ||
114 | } | 113 | } |
115 | 114 | ||
115 | msg->version = 0; | ||
116 | msg->command = EC_CMD_REBOOT_EC + ec->cmd_offset; | ||
117 | msg->outsize = sizeof(*param); | ||
118 | msg->insize = 0; | ||
119 | ret = cros_ec_cmd_xfer(ec->ec_dev, msg); | ||
120 | if (ret < 0) { | ||
121 | count = ret; | ||
122 | goto exit; | ||
123 | } | ||
124 | if (msg->result != EC_RES_SUCCESS) { | ||
125 | dev_dbg(ec->dev, "EC result %d\n", msg->result); | ||
126 | count = -EINVAL; | ||
127 | } | ||
128 | exit: | ||
129 | kfree(msg); | ||
116 | return count; | 130 | return count; |
117 | } | 131 | } |
118 | 132 | ||
@@ -123,22 +137,33 @@ static ssize_t show_ec_version(struct device *dev, | |||
123 | struct ec_response_get_version *r_ver; | 137 | struct ec_response_get_version *r_ver; |
124 | struct ec_response_get_chip_info *r_chip; | 138 | struct ec_response_get_chip_info *r_chip; |
125 | struct ec_response_board_version *r_board; | 139 | struct ec_response_board_version *r_board; |
126 | struct cros_ec_command msg = { 0 }; | 140 | struct cros_ec_command *msg; |
127 | int ret; | 141 | int ret; |
128 | int count = 0; | 142 | int count = 0; |
129 | struct cros_ec_device *ec = dev_get_drvdata(dev); | 143 | struct cros_ec_dev *ec = container_of(dev, |
144 | struct cros_ec_dev, class_dev); | ||
145 | |||
146 | msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL); | ||
147 | if (!msg) | ||
148 | return -ENOMEM; | ||
130 | 149 | ||
131 | /* Get versions. RW may change. */ | 150 | /* Get versions. RW may change. */ |
132 | msg.command = EC_CMD_GET_VERSION; | 151 | msg->version = 0; |
133 | msg.insize = sizeof(*r_ver); | 152 | msg->command = EC_CMD_GET_VERSION + ec->cmd_offset; |
134 | ret = cros_ec_cmd_xfer(ec, &msg); | 153 | msg->insize = sizeof(*r_ver); |
135 | if (ret < 0) | 154 | msg->outsize = 0; |
136 | return ret; | 155 | ret = cros_ec_cmd_xfer(ec->ec_dev, msg); |
137 | if (msg.result != EC_RES_SUCCESS) | 156 | if (ret < 0) { |
138 | return scnprintf(buf, PAGE_SIZE, | 157 | count = ret; |
139 | "ERROR: EC returned %d\n", msg.result); | 158 | goto exit; |
159 | } | ||
160 | if (msg->result != EC_RES_SUCCESS) { | ||
161 | count = scnprintf(buf, PAGE_SIZE, | ||
162 | "ERROR: EC returned %d\n", msg->result); | ||
163 | goto exit; | ||
164 | } | ||
140 | 165 | ||
141 | r_ver = (struct ec_response_get_version *)msg.indata; | 166 | r_ver = (struct ec_response_get_version *)msg->data; |
142 | /* Strings should be null-terminated, but let's be sure. */ | 167 | /* Strings should be null-terminated, but let's be sure. */ |
143 | r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0'; | 168 | r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0'; |
144 | r_ver->version_string_rw[sizeof(r_ver->version_string_rw) - 1] = '\0'; | 169 | r_ver->version_string_rw[sizeof(r_ver->version_string_rw) - 1] = '\0'; |
@@ -152,33 +177,33 @@ static ssize_t show_ec_version(struct device *dev, | |||
152 | image_names[r_ver->current_image] : "?")); | 177 | image_names[r_ver->current_image] : "?")); |
153 | 178 | ||
154 | /* Get build info. */ | 179 | /* Get build info. */ |
155 | msg.command = EC_CMD_GET_BUILD_INFO; | 180 | msg->command = EC_CMD_GET_BUILD_INFO + ec->cmd_offset; |
156 | msg.insize = sizeof(msg.indata); | 181 | msg->insize = EC_HOST_PARAM_SIZE; |
157 | ret = cros_ec_cmd_xfer(ec, &msg); | 182 | ret = cros_ec_cmd_xfer(ec->ec_dev, msg); |
158 | if (ret < 0) | 183 | if (ret < 0) |
159 | count += scnprintf(buf + count, PAGE_SIZE - count, | 184 | count += scnprintf(buf + count, PAGE_SIZE - count, |
160 | "Build info: XFER ERROR %d\n", ret); | 185 | "Build info: XFER ERROR %d\n", ret); |
161 | else if (msg.result != EC_RES_SUCCESS) | 186 | else if (msg->result != EC_RES_SUCCESS) |
162 | count += scnprintf(buf + count, PAGE_SIZE - count, | 187 | count += scnprintf(buf + count, PAGE_SIZE - count, |
163 | "Build info: EC error %d\n", msg.result); | 188 | "Build info: EC error %d\n", msg->result); |
164 | else { | 189 | else { |
165 | msg.indata[sizeof(msg.indata) - 1] = '\0'; | 190 | msg->data[sizeof(msg->data) - 1] = '\0'; |
166 | count += scnprintf(buf + count, PAGE_SIZE - count, | 191 | count += scnprintf(buf + count, PAGE_SIZE - count, |
167 | "Build info: %s\n", msg.indata); | 192 | "Build info: %s\n", msg->data); |
168 | } | 193 | } |
169 | 194 | ||
170 | /* Get chip info. */ | 195 | /* Get chip info. */ |
171 | msg.command = EC_CMD_GET_CHIP_INFO; | 196 | msg->command = EC_CMD_GET_CHIP_INFO + ec->cmd_offset; |
172 | msg.insize = sizeof(*r_chip); | 197 | msg->insize = sizeof(*r_chip); |
173 | ret = cros_ec_cmd_xfer(ec, &msg); | 198 | ret = cros_ec_cmd_xfer(ec->ec_dev, msg); |
174 | if (ret < 0) | 199 | if (ret < 0) |
175 | count += scnprintf(buf + count, PAGE_SIZE - count, | 200 | count += scnprintf(buf + count, PAGE_SIZE - count, |
176 | "Chip info: XFER ERROR %d\n", ret); | 201 | "Chip info: XFER ERROR %d\n", ret); |
177 | else if (msg.result != EC_RES_SUCCESS) | 202 | else if (msg->result != EC_RES_SUCCESS) |
178 | count += scnprintf(buf + count, PAGE_SIZE - count, | 203 | count += scnprintf(buf + count, PAGE_SIZE - count, |
179 | "Chip info: EC error %d\n", msg.result); | 204 | "Chip info: EC error %d\n", msg->result); |
180 | else { | 205 | else { |
181 | r_chip = (struct ec_response_get_chip_info *)msg.indata; | 206 | r_chip = (struct ec_response_get_chip_info *)msg->data; |
182 | 207 | ||
183 | r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0'; | 208 | r_chip->vendor[sizeof(r_chip->vendor) - 1] = '\0'; |
184 | r_chip->name[sizeof(r_chip->name) - 1] = '\0'; | 209 | r_chip->name[sizeof(r_chip->name) - 1] = '\0'; |
@@ -192,23 +217,25 @@ static ssize_t show_ec_version(struct device *dev, | |||
192 | } | 217 | } |
193 | 218 | ||
194 | /* Get board version */ | 219 | /* Get board version */ |
195 | msg.command = EC_CMD_GET_BOARD_VERSION; | 220 | msg->command = EC_CMD_GET_BOARD_VERSION + ec->cmd_offset; |
196 | msg.insize = sizeof(*r_board); | 221 | msg->insize = sizeof(*r_board); |
197 | ret = cros_ec_cmd_xfer(ec, &msg); | 222 | ret = cros_ec_cmd_xfer(ec->ec_dev, msg); |
198 | if (ret < 0) | 223 | if (ret < 0) |
199 | count += scnprintf(buf + count, PAGE_SIZE - count, | 224 | count += scnprintf(buf + count, PAGE_SIZE - count, |
200 | "Board version: XFER ERROR %d\n", ret); | 225 | "Board version: XFER ERROR %d\n", ret); |
201 | else if (msg.result != EC_RES_SUCCESS) | 226 | else if (msg->result != EC_RES_SUCCESS) |
202 | count += scnprintf(buf + count, PAGE_SIZE - count, | 227 | count += scnprintf(buf + count, PAGE_SIZE - count, |
203 | "Board version: EC error %d\n", msg.result); | 228 | "Board version: EC error %d\n", msg->result); |
204 | else { | 229 | else { |
205 | r_board = (struct ec_response_board_version *)msg.indata; | 230 | r_board = (struct ec_response_board_version *)msg->data; |
206 | 231 | ||
207 | count += scnprintf(buf + count, PAGE_SIZE - count, | 232 | count += scnprintf(buf + count, PAGE_SIZE - count, |
208 | "Board version: %d\n", | 233 | "Board version: %d\n", |
209 | r_board->board_version); | 234 | r_board->board_version); |
210 | } | 235 | } |
211 | 236 | ||
237 | exit: | ||
238 | kfree(msg); | ||
212 | return count; | 239 | return count; |
213 | } | 240 | } |
214 | 241 | ||
@@ -216,27 +243,39 @@ static ssize_t show_ec_flashinfo(struct device *dev, | |||
216 | struct device_attribute *attr, char *buf) | 243 | struct device_attribute *attr, char *buf) |
217 | { | 244 | { |
218 | struct ec_response_flash_info *resp; | 245 | struct ec_response_flash_info *resp; |
219 | struct cros_ec_command msg = { 0 }; | 246 | struct cros_ec_command *msg; |
220 | int ret; | 247 | int ret; |
221 | struct cros_ec_device *ec = dev_get_drvdata(dev); | 248 | struct cros_ec_dev *ec = container_of(dev, |
249 | struct cros_ec_dev, class_dev); | ||
250 | |||
251 | msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL); | ||
252 | if (!msg) | ||
253 | return -ENOMEM; | ||
222 | 254 | ||
223 | /* The flash info shouldn't ever change, but ask each time anyway. */ | 255 | /* The flash info shouldn't ever change, but ask each time anyway. */ |
224 | msg.command = EC_CMD_FLASH_INFO; | 256 | msg->version = 0; |
225 | msg.insize = sizeof(*resp); | 257 | msg->command = EC_CMD_FLASH_INFO + ec->cmd_offset; |
226 | ret = cros_ec_cmd_xfer(ec, &msg); | 258 | msg->insize = sizeof(*resp); |
259 | msg->outsize = 0; | ||
260 | ret = cros_ec_cmd_xfer(ec->ec_dev, msg); | ||
227 | if (ret < 0) | 261 | if (ret < 0) |
228 | return ret; | 262 | goto exit; |
229 | if (msg.result != EC_RES_SUCCESS) | 263 | if (msg->result != EC_RES_SUCCESS) { |
230 | return scnprintf(buf, PAGE_SIZE, | 264 | ret = scnprintf(buf, PAGE_SIZE, |
231 | "ERROR: EC returned %d\n", msg.result); | 265 | "ERROR: EC returned %d\n", msg->result); |
232 | 266 | goto exit; | |
233 | resp = (struct ec_response_flash_info *)msg.indata; | 267 | } |
234 | 268 | ||
235 | return scnprintf(buf, PAGE_SIZE, | 269 | resp = (struct ec_response_flash_info *)msg->data; |
236 | "FlashSize %d\nWriteSize %d\n" | 270 | |
237 | "EraseSize %d\nProtectSize %d\n", | 271 | ret = scnprintf(buf, PAGE_SIZE, |
238 | resp->flash_size, resp->write_block_size, | 272 | "FlashSize %d\nWriteSize %d\n" |
239 | resp->erase_block_size, resp->protect_block_size); | 273 | "EraseSize %d\nProtectSize %d\n", |
274 | resp->flash_size, resp->write_block_size, | ||
275 | resp->erase_block_size, resp->protect_block_size); | ||
276 | exit: | ||
277 | kfree(msg); | ||
278 | return ret; | ||
240 | } | 279 | } |
241 | 280 | ||
242 | /* Module initialization */ | 281 | /* Module initialization */ |
@@ -252,20 +291,7 @@ static struct attribute *__ec_attrs[] = { | |||
252 | NULL, | 291 | NULL, |
253 | }; | 292 | }; |
254 | 293 | ||
255 | static struct attribute_group ec_attr_group = { | 294 | struct attribute_group cros_ec_attr_group = { |
256 | .attrs = __ec_attrs, | 295 | .attrs = __ec_attrs, |
257 | }; | 296 | }; |
258 | 297 | ||
259 | void ec_dev_sysfs_init(struct cros_ec_device *ec) | ||
260 | { | ||
261 | int error; | ||
262 | |||
263 | error = sysfs_create_group(&ec->vdev->kobj, &ec_attr_group); | ||
264 | if (error) | ||
265 | pr_warn("failed to create group: %d\n", error); | ||
266 | } | ||
267 | |||
268 | void ec_dev_sysfs_remove(struct cros_ec_device *ec) | ||
269 | { | ||
270 | sysfs_remove_group(&ec->vdev->kobj, &ec_attr_group); | ||
271 | } | ||