0001
0002
0003
0004
0005 #include <linux/completion.h>
0006 #include <linux/delay.h>
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/of.h>
0010 #include <linux/platform_data/cros_ec_commands.h>
0011 #include <linux/platform_data/cros_ec_proto.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/rpmsg.h>
0014 #include <linux/slab.h>
0015
0016 #include "cros_ec.h"
0017
0018 #define EC_MSG_TIMEOUT_MS 200
0019 #define HOST_COMMAND_MARK 1
0020 #define HOST_EVENT_MARK 2
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 struct cros_ec_rpmsg_response {
0031 u8 type;
0032 u8 data[] __aligned(4);
0033 };
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 struct cros_ec_rpmsg {
0046 struct rpmsg_device *rpdev;
0047 struct completion xfer_ack;
0048 struct work_struct host_event_work;
0049 struct rpmsg_endpoint *ept;
0050 bool has_pending_host_event;
0051 bool probe_done;
0052 };
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 static int cros_ec_cmd_xfer_rpmsg(struct cros_ec_device *ec_dev,
0066 struct cros_ec_command *ec_msg)
0067 {
0068 return -EINVAL;
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 static int cros_ec_pkt_xfer_rpmsg(struct cros_ec_device *ec_dev,
0080 struct cros_ec_command *ec_msg)
0081 {
0082 struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
0083 struct ec_host_response *response;
0084 unsigned long timeout;
0085 int len;
0086 int ret;
0087 u8 sum;
0088 int i;
0089
0090 ec_msg->result = 0;
0091 len = cros_ec_prepare_tx(ec_dev, ec_msg);
0092 if (len < 0)
0093 return len;
0094 dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
0095
0096 reinit_completion(&ec_rpmsg->xfer_ack);
0097 ret = rpmsg_send(ec_rpmsg->ept, ec_dev->dout, len);
0098 if (ret) {
0099 dev_err(ec_dev->dev, "rpmsg send failed\n");
0100 return ret;
0101 }
0102
0103 timeout = msecs_to_jiffies(EC_MSG_TIMEOUT_MS);
0104 ret = wait_for_completion_timeout(&ec_rpmsg->xfer_ack, timeout);
0105 if (!ret) {
0106 dev_err(ec_dev->dev, "rpmsg send timeout\n");
0107 return -EIO;
0108 }
0109
0110
0111 response = (struct ec_host_response *)ec_dev->din;
0112 ec_msg->result = response->result;
0113
0114 ret = cros_ec_check_result(ec_dev, ec_msg);
0115 if (ret)
0116 goto exit;
0117
0118 if (response->data_len > ec_msg->insize) {
0119 dev_err(ec_dev->dev, "packet too long (%d bytes, expected %d)",
0120 response->data_len, ec_msg->insize);
0121 ret = -EMSGSIZE;
0122 goto exit;
0123 }
0124
0125
0126 memcpy(ec_msg->data, ec_dev->din + sizeof(*response),
0127 response->data_len);
0128
0129 sum = 0;
0130 for (i = 0; i < sizeof(*response) + response->data_len; i++)
0131 sum += ec_dev->din[i];
0132
0133 if (sum) {
0134 dev_err(ec_dev->dev, "bad packet checksum, calculated %x\n",
0135 sum);
0136 ret = -EBADMSG;
0137 goto exit;
0138 }
0139
0140 ret = response->data_len;
0141 exit:
0142 if (ec_msg->command == EC_CMD_REBOOT_EC)
0143 msleep(EC_REBOOT_DELAY_MS);
0144
0145 return ret;
0146 }
0147
0148 static void
0149 cros_ec_rpmsg_host_event_function(struct work_struct *host_event_work)
0150 {
0151 struct cros_ec_rpmsg *ec_rpmsg = container_of(host_event_work,
0152 struct cros_ec_rpmsg,
0153 host_event_work);
0154
0155 cros_ec_irq_thread(0, dev_get_drvdata(&ec_rpmsg->rpdev->dev));
0156 }
0157
0158 static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
0159 int len, void *priv, u32 src)
0160 {
0161 struct cros_ec_device *ec_dev = dev_get_drvdata(&rpdev->dev);
0162 struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
0163 struct cros_ec_rpmsg_response *resp;
0164
0165 if (!len) {
0166 dev_warn(ec_dev->dev, "rpmsg received empty response");
0167 return -EINVAL;
0168 }
0169
0170 resp = data;
0171 len -= offsetof(struct cros_ec_rpmsg_response, data);
0172 if (resp->type == HOST_COMMAND_MARK) {
0173 if (len > ec_dev->din_size) {
0174 dev_warn(ec_dev->dev,
0175 "received length %d > din_size %d, truncating",
0176 len, ec_dev->din_size);
0177 len = ec_dev->din_size;
0178 }
0179
0180 memcpy(ec_dev->din, resp->data, len);
0181 complete(&ec_rpmsg->xfer_ack);
0182 } else if (resp->type == HOST_EVENT_MARK) {
0183
0184
0185
0186
0187 if (ec_rpmsg->probe_done)
0188 schedule_work(&ec_rpmsg->host_event_work);
0189 else
0190 ec_rpmsg->has_pending_host_event = true;
0191 } else {
0192 dev_warn(ec_dev->dev, "rpmsg received invalid type = %d",
0193 resp->type);
0194 return -EINVAL;
0195 }
0196
0197 return 0;
0198 }
0199
0200 static struct rpmsg_endpoint *
0201 cros_ec_rpmsg_create_ept(struct rpmsg_device *rpdev)
0202 {
0203 struct rpmsg_channel_info chinfo = {};
0204
0205 strscpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
0206 chinfo.src = rpdev->src;
0207 chinfo.dst = RPMSG_ADDR_ANY;
0208
0209 return rpmsg_create_ept(rpdev, cros_ec_rpmsg_callback, NULL, chinfo);
0210 }
0211
0212 static int cros_ec_rpmsg_probe(struct rpmsg_device *rpdev)
0213 {
0214 struct device *dev = &rpdev->dev;
0215 struct cros_ec_rpmsg *ec_rpmsg;
0216 struct cros_ec_device *ec_dev;
0217 int ret;
0218
0219 ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
0220 if (!ec_dev)
0221 return -ENOMEM;
0222
0223 ec_rpmsg = devm_kzalloc(dev, sizeof(*ec_rpmsg), GFP_KERNEL);
0224 if (!ec_rpmsg)
0225 return -ENOMEM;
0226
0227 ec_dev->dev = dev;
0228 ec_dev->priv = ec_rpmsg;
0229 ec_dev->cmd_xfer = cros_ec_cmd_xfer_rpmsg;
0230 ec_dev->pkt_xfer = cros_ec_pkt_xfer_rpmsg;
0231 ec_dev->phys_name = dev_name(&rpdev->dev);
0232 ec_dev->din_size = sizeof(struct ec_host_response) +
0233 sizeof(struct ec_response_get_protocol_info);
0234 ec_dev->dout_size = sizeof(struct ec_host_request);
0235 dev_set_drvdata(dev, ec_dev);
0236
0237 ec_rpmsg->rpdev = rpdev;
0238 init_completion(&ec_rpmsg->xfer_ack);
0239 INIT_WORK(&ec_rpmsg->host_event_work,
0240 cros_ec_rpmsg_host_event_function);
0241
0242 ec_rpmsg->ept = cros_ec_rpmsg_create_ept(rpdev);
0243 if (!ec_rpmsg->ept)
0244 return -ENOMEM;
0245
0246 ret = cros_ec_register(ec_dev);
0247 if (ret < 0) {
0248 rpmsg_destroy_ept(ec_rpmsg->ept);
0249 cancel_work_sync(&ec_rpmsg->host_event_work);
0250 return ret;
0251 }
0252
0253 ec_rpmsg->probe_done = true;
0254
0255 if (ec_rpmsg->has_pending_host_event)
0256 schedule_work(&ec_rpmsg->host_event_work);
0257
0258 return 0;
0259 }
0260
0261 static void cros_ec_rpmsg_remove(struct rpmsg_device *rpdev)
0262 {
0263 struct cros_ec_device *ec_dev = dev_get_drvdata(&rpdev->dev);
0264 struct cros_ec_rpmsg *ec_rpmsg = ec_dev->priv;
0265
0266 cros_ec_unregister(ec_dev);
0267 rpmsg_destroy_ept(ec_rpmsg->ept);
0268 cancel_work_sync(&ec_rpmsg->host_event_work);
0269 }
0270
0271 #ifdef CONFIG_PM_SLEEP
0272 static int cros_ec_rpmsg_suspend(struct device *dev)
0273 {
0274 struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
0275
0276 return cros_ec_suspend(ec_dev);
0277 }
0278
0279 static int cros_ec_rpmsg_resume(struct device *dev)
0280 {
0281 struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
0282
0283 return cros_ec_resume(ec_dev);
0284 }
0285 #endif
0286
0287 static SIMPLE_DEV_PM_OPS(cros_ec_rpmsg_pm_ops, cros_ec_rpmsg_suspend,
0288 cros_ec_rpmsg_resume);
0289
0290 static const struct of_device_id cros_ec_rpmsg_of_match[] = {
0291 { .compatible = "google,cros-ec-rpmsg", },
0292 { }
0293 };
0294 MODULE_DEVICE_TABLE(of, cros_ec_rpmsg_of_match);
0295
0296 static struct rpmsg_driver cros_ec_driver_rpmsg = {
0297 .drv = {
0298 .name = "cros-ec-rpmsg",
0299 .of_match_table = cros_ec_rpmsg_of_match,
0300 .pm = &cros_ec_rpmsg_pm_ops,
0301 },
0302 .probe = cros_ec_rpmsg_probe,
0303 .remove = cros_ec_rpmsg_remove,
0304 };
0305
0306 module_rpmsg_driver(cros_ec_driver_rpmsg);
0307
0308 MODULE_LICENSE("GPL v2");
0309 MODULE_DESCRIPTION("ChromeOS EC multi function device (rpmsg)");