static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command, u32 *response) { int ret; struct { struct cros_ec_command msg; struct ec_response_rtc data; } __packed msg; memset(&msg, 0, sizeof(msg)); msg.msg.command = command; msg.msg.insize = sizeof(msg.data); ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); if (ret < 0) { dev_err(cros_ec->dev, "error getting %s from EC: %d\n", command == EC_CMD_RTC_GET_VALUE ? "time" : "alarm", ret); return ret; } *response = msg.data.time; return 0; }
static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) { struct cros_ec_cec *cros_ec_cec = adap->priv; struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; struct { struct cros_ec_command msg; struct ec_params_cec_set data; } __packed msg = {}; int ret; msg.msg.command = EC_CMD_CEC_SET; msg.msg.outsize = sizeof(msg.data); msg.data.cmd = CEC_CMD_ENABLE; msg.data.val = enable; ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); if (ret < 0) { dev_err(cros_ec->dev, "error %sabling CEC on EC: %d\n", (enable ? "en" : "dis"), ret); return ret; } return 0; }
static struct ec_response_pd_log *ec_get_log_entry(struct logger_data *logger) { struct cros_ec_dev *ec_dev = logger->ec_dev; struct cros_ec_command *msg; int ret; msg = (struct cros_ec_command *)logger->ec_buffer; msg->command = ec_dev->cmd_offset + EC_CMD_PD_GET_LOG_ENTRY; msg->insize = CROS_USBPD_LOG_RESP_SIZE; ret = cros_ec_cmd_xfer_status(ec_dev->ec_dev, msg); if (ret < 0) return ERR_PTR(ret); return (struct ec_response_pd_log *)msg->data; }
int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state, u16 opt_length) { int ret; if (opt_length) state->msg->insize = min(opt_length, state->ec->max_response); else state->msg->insize = state->ec->max_response; memcpy(state->msg->data, &state->param, sizeof(state->param)); ret = cros_ec_cmd_xfer_status(state->ec, state->msg); if (ret < 0) return -EIO; if (ret && state->resp != (struct ec_response_motion_sense *)state->msg->data) memcpy(state->resp, state->msg->data, ret); return 0; }
static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command, u32 param) { int ret = 0; struct { struct cros_ec_command msg; struct ec_response_rtc data; } __packed msg; memset(&msg, 0, sizeof(msg)); msg.msg.command = command; msg.msg.outsize = sizeof(msg.data); msg.data.time = param; ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); if (ret < 0) { dev_err(cros_ec->dev, "error setting %s on EC: %d\n", command == EC_CMD_RTC_SET_VALUE ? "time" : "alarm", ret); return ret; } return 0; }
static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) { struct cros_ec_cec *cros_ec_cec = adap->priv; struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; struct { struct cros_ec_command msg; struct ec_params_cec_set data; } __packed msg = {}; int ret; msg.msg.command = EC_CMD_CEC_SET; msg.msg.outsize = sizeof(msg.data); msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS; msg.data.val = logical_addr; ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); if (ret < 0) { dev_err(cros_ec->dev, "error setting CEC logical address on EC: %d\n", ret); return ret; } return 0; }
static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *cec_msg) { struct cros_ec_cec *cros_ec_cec = adap->priv; struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; struct { struct cros_ec_command msg; struct ec_params_cec_write data; } __packed msg = {}; int ret; msg.msg.command = EC_CMD_CEC_WRITE_MSG; msg.msg.outsize = cec_msg->len; memcpy(msg.data.msg, cec_msg->msg, cec_msg->len); ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); if (ret < 0) { dev_err(cros_ec->dev, "error writing CEC msg on EC: %d\n", ret); return ret; } return 0; }
static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) { int ret; struct cros_ec_command msg = { .version = 0, .command = EC_CMD_MKBP_STATE, .outdata = NULL, .outsize = 0, .indata = kb_state, .insize = ckdev->cols, }; ret = cros_ec_cmd_xfer_status(ckdev->ec, &msg); return ret; } static irqreturn_t cros_ec_keyb_irq(int irq, void *data) { struct cros_ec_keyb *ckdev = data; struct cros_ec_device *ec = ckdev->ec; int ret; uint8_t kb_state[ckdev->cols]; if (device_may_wakeup(ec->dev)) pm_wakeup_event(ec->dev, 0); ret = cros_ec_keyb_get_state(ckdev, kb_state); if (ret >= 0) cros_ec_keyb_process(ckdev, kb_state, ret); else dev_err(ec->dev, "failed to get keyboard state: %d\n", ret); return IRQ_HANDLED; } static int cros_ec_keyb_open(struct input_dev *dev) { struct cros_ec_keyb *ckdev = input_get_drvdata(dev); struct cros_ec_device *ec = ckdev->ec; return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "cros_ec_keyb", ckdev); } static void cros_ec_keyb_close(struct input_dev *dev) { struct cros_ec_keyb *ckdev = input_get_drvdata(dev); struct cros_ec_device *ec = ckdev->ec; free_irq(ec->irq, ckdev); } static int cros_ec_keyb_probe(struct platform_device *pdev) { struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); struct device *dev = ec->dev; struct cros_ec_keyb *ckdev; struct input_dev *idev; struct device_node *np; int err; np = pdev->dev.of_node; if (!np) return -ENODEV; ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL); if (!ckdev) return -ENOMEM; err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows, &ckdev->cols); if (err) return err; ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL); if (!ckdev->old_kb_state) return -ENOMEM; idev = devm_input_allocate_device(&pdev->dev); if (!idev) return -ENOMEM; if (!ec->irq) { dev_err(dev, "no EC IRQ specified\n"); return -EINVAL; } ckdev->ec = ec; ckdev->dev = dev; dev_set_drvdata(&pdev->dev, ckdev); idev->name = CROS_EC_DEV_NAME; idev->phys = ec->phys_name; __set_bit(EV_REP, idev->evbit); idev->id.bustype = BUS_VIRTUAL; idev->id.version = 1; idev->id.product = 0; idev->dev.parent = &pdev->dev; idev->open = cros_ec_keyb_open; idev->close = cros_ec_keyb_close; ckdev->ghost_filter = of_property_read_bool(np, "google,needs-ghost-filter"); err = matrix_keypad_build_keymap(NULL, NULL, ckdev->rows, ckdev->cols, NULL, idev); if (err) { dev_err(dev, "cannot build key matrix\n"); return err; } ckdev->row_shift = get_count_order(ckdev->cols); input_set_capability(idev, EV_MSC, MSC_SCAN); input_set_drvdata(idev, ckdev); ckdev->idev = idev; err = input_register_device(ckdev->idev); if (err) { dev_err(dev, "cannot register input device\n"); return err; } return 0; } #ifdef CONFIG_PM_SLEEP /* Clear any keys in the buffer */ static void cros_ec_keyb_clear_keyboard(struct cros_ec_keyb *ckdev) { uint8_t old_state[ckdev->cols]; uint8_t new_state[ckdev->cols]; unsigned long duration; int i, ret; /* * Keep reading until we see that the scan state does not change. * That indicates that we are done. * * Assume that the EC keyscan buffer is at most 32 deep. */ duration = jiffies; ret = cros_ec_keyb_get_state(ckdev, new_state); for (i = 1; !ret && i < 32; i++) { memcpy(old_state, new_state, sizeof(old_state)); ret = cros_ec_keyb_get_state(ckdev, new_state); if (0 == memcmp(old_state, new_state, sizeof(old_state))) break; } duration = jiffies - duration; dev_info(ckdev->dev, "Discarded %d keyscan(s) in %dus\n", i, jiffies_to_usecs(duration)); }