Lines Matching +full:uart +full:- +full:attached
1 // SPDX-License-Identifier: GPL-2.0-only
3 * UART interface for ChromeOS Embedded Controller
5 * Copyright 2020-2022 Google LLC.
23 * EC sends contiguous bytes of response packet on UART AP RX.
40 * struct response_info - Encapsulate EC response related
51 * @status: Re-init to 0 before sending a cmd. Updated to 1 when
67 * struct cros_ec_uart - information about a uart-connected EC
69 * @serdev: serdev uart device we are connected to.
70 * @baudrate: UART baudrate of attached EC device.
71 * @flowcontrol: UART flowcontrol of attached device.
89 struct cros_ec_uart *ec_uart = ec_dev->priv; in cros_ec_uart_rx_bytes()
90 struct response_info *resp = &ec_uart->response; in cros_ec_uart_rx_bytes()
93 if (!resp->data) { in cros_ec_uart_rx_bytes()
95 dev_warn(ec_dev->dev, "Bytes received out of band, dropping them.\n"); in cros_ec_uart_rx_bytes()
100 * Check if incoming bytes + resp->size is greater than allocated in cros_ec_uart_rx_bytes()
104 if (resp->size + count > resp->max_size) { in cros_ec_uart_rx_bytes()
105 resp->status = -EMSGSIZE; in cros_ec_uart_rx_bytes()
106 wake_up(&resp->wait_queue); in cros_ec_uart_rx_bytes()
110 memcpy(resp->data + resp->size, data, count); in cros_ec_uart_rx_bytes()
112 resp->size += count; in cros_ec_uart_rx_bytes()
115 if (resp->size >= sizeof(*host_response) && resp->exp_len == 0) { in cros_ec_uart_rx_bytes()
116 host_response = (struct ec_host_response *)resp->data; in cros_ec_uart_rx_bytes()
117 resp->exp_len = host_response->data_len + sizeof(*host_response); in cros_ec_uart_rx_bytes()
121 if (resp->size >= sizeof(*host_response) && resp->size == resp->exp_len) { in cros_ec_uart_rx_bytes()
122 resp->status = 1; in cros_ec_uart_rx_bytes()
123 wake_up(&resp->wait_queue); in cros_ec_uart_rx_bytes()
132 struct cros_ec_uart *ec_uart = ec_dev->priv; in cros_ec_uart_pkt_xfer()
133 struct serdev_device *serdev = ec_uart->serdev; in cros_ec_uart_pkt_xfer()
134 struct response_info *resp = &ec_uart->response; in cros_ec_uart_pkt_xfer()
141 dev_dbg(ec_dev->dev, "Prepared len=%d\n", len); in cros_ec_uart_pkt_xfer()
144 resp->data = ec_dev->din; in cros_ec_uart_pkt_xfer()
145 resp->max_size = ec_dev->din_size; in cros_ec_uart_pkt_xfer()
146 resp->size = 0; in cros_ec_uart_pkt_xfer()
147 resp->exp_len = 0; in cros_ec_uart_pkt_xfer()
148 resp->status = 0; in cros_ec_uart_pkt_xfer()
150 ret = serdev_device_write_buf(serdev, ec_dev->dout, len); in cros_ec_uart_pkt_xfer()
152 dev_err(ec_dev->dev, "Unable to write data\n"); in cros_ec_uart_pkt_xfer()
154 ret = -EIO; in cros_ec_uart_pkt_xfer()
158 ret = wait_event_timeout(resp->wait_queue, resp->status, in cros_ec_uart_pkt_xfer()
161 dev_warn(ec_dev->dev, "Timed out waiting for response.\n"); in cros_ec_uart_pkt_xfer()
162 ret = -ETIMEDOUT; in cros_ec_uart_pkt_xfer()
166 if (resp->status < 0) { in cros_ec_uart_pkt_xfer()
167 ret = resp->status; in cros_ec_uart_pkt_xfer()
168 dev_warn(ec_dev->dev, "Error response received: %d\n", ret); in cros_ec_uart_pkt_xfer()
172 host_response = (struct ec_host_response *)ec_dev->din; in cros_ec_uart_pkt_xfer()
173 ec_msg->result = host_response->result; in cros_ec_uart_pkt_xfer()
175 if (host_response->data_len > ec_msg->insize) { in cros_ec_uart_pkt_xfer()
176 dev_err(ec_dev->dev, "Resp too long (%d bytes, expected %d)\n", in cros_ec_uart_pkt_xfer()
177 host_response->data_len, ec_msg->insize); in cros_ec_uart_pkt_xfer()
178 ret = -ENOSPC; in cros_ec_uart_pkt_xfer()
184 for (i = 0; i < sizeof(*host_response) + host_response->data_len; i++) in cros_ec_uart_pkt_xfer()
185 sum += ec_dev->din[i]; in cros_ec_uart_pkt_xfer()
188 dev_err(ec_dev->dev, "Bad packet checksum calculated %x\n", sum); in cros_ec_uart_pkt_xfer()
189 ret = -EBADMSG; in cros_ec_uart_pkt_xfer()
193 memcpy(ec_msg->data, ec_dev->din + sizeof(*host_response), host_response->data_len); in cros_ec_uart_pkt_xfer()
195 ret = host_response->data_len; in cros_ec_uart_pkt_xfer()
199 resp->data = NULL; in cros_ec_uart_pkt_xfer()
201 if (ec_msg->command == EC_CMD_REBOOT_EC) in cros_ec_uart_pkt_xfer()
210 struct acpi_resource_uart_serialbus *sb = &ares->data.uart_serial_bus; in cros_ec_uart_resource()
212 if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS && in cros_ec_uart_resource()
213 sb->type == ACPI_RESOURCE_SERIAL_TYPE_UART) { in cros_ec_uart_resource()
214 ec_uart->baudrate = sb->default_baud_rate; in cros_ec_uart_resource()
215 dev_dbg(&ec_uart->serdev->dev, "Baudrate %d\n", ec_uart->baudrate); in cros_ec_uart_resource()
217 ec_uart->flowcontrol = sb->flow_control; in cros_ec_uart_resource()
218 dev_dbg(&ec_uart->serdev->dev, "Flow control %d\n", ec_uart->flowcontrol); in cros_ec_uart_resource()
228 struct acpi_device *adev = ACPI_COMPANION(&ec_uart->serdev->dev); in cros_ec_uart_acpi_probe()
241 ec_uart->irq = ret; in cros_ec_uart_acpi_probe()
242 dev_dbg(&ec_uart->serdev->dev, "IRQ number %d\n", ec_uart->irq); in cros_ec_uart_acpi_probe()
253 struct device *dev = &serdev->dev; in cros_ec_uart_probe()
260 return -ENOMEM; in cros_ec_uart_probe()
264 return -ENOMEM; in cros_ec_uart_probe()
267 init_waitqueue_head(&ec_uart->response.wait_queue); in cros_ec_uart_probe()
269 ec_uart->serdev = serdev; in cros_ec_uart_probe()
278 ec_dev->phys_name = dev_name(dev); in cros_ec_uart_probe()
279 ec_dev->dev = dev; in cros_ec_uart_probe()
280 ec_dev->priv = ec_uart; in cros_ec_uart_probe()
281 ec_dev->irq = ec_uart->irq; in cros_ec_uart_probe()
282 ec_dev->cmd_xfer = NULL; in cros_ec_uart_probe()
283 ec_dev->pkt_xfer = cros_ec_uart_pkt_xfer; in cros_ec_uart_probe()
284 ec_dev->din_size = sizeof(struct ec_host_response) + in cros_ec_uart_probe()
286 ec_dev->dout_size = sizeof(struct ec_host_request) + sizeof(struct ec_params_rwsig_action); in cros_ec_uart_probe()
292 dev_err(dev, "Unable to open UART device"); in cros_ec_uart_probe()
296 ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate); in cros_ec_uart_probe()
302 serdev_device_set_flow_control(serdev, ec_uart->flowcontrol); in cros_ec_uart_probe()
332 { .compatible = "google,cros-ec-uart" },
348 .name = "cros-ec-uart",
360 MODULE_DESCRIPTION("UART interface for ChromeOS Embedded Controller");