static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec, struct cros_ec_command *msg) { struct ec_host_request *request; struct ec_host_response response; u8 sum; int ret = 0; u8 *dout; ret = cros_ec_prepare_tx(ec, msg); /* Write buffer */ cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout); request = (struct ec_host_request *)ec->dout; /* Here we go */ sum = EC_COMMAND_PROTOCOL_3; cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum); if (ec_response_timed_out()) { dev_warn(ec->dev, "EC responsed timed out\n"); ret = -EIO; goto done; } /* Check result */ msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum); ret = cros_ec_check_result(ec, msg); if (ret) goto done; /* Read back response */ dout = (u8 *)&response; sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response), dout); msg->result = response.result; if (response.data_len > msg->insize) { dev_err(ec->dev, "packet too long (%d bytes, expected %d)", response.data_len, msg->insize); ret = -EMSGSIZE; goto done; } /* Read response and process checksum */ sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(response), response.data_len, msg->data); if (sum) { dev_err(ec->dev, "bad packet checksum %02x\n", response.checksum); ret = -EBADMSG; goto done; } /* Return actual amount of data received */ ret = response.data_len; done: return ret; }
static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec, struct cros_ec_command *msg) { struct ec_lpc_host_args args; int csum; int i; int ret = 0; if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE || msg->insize > EC_PROTO2_MAX_PARAM_SIZE) { dev_err(ec->dev, "invalid buffer sizes (out %d, in %d)\n", msg->outsize, msg->insize); return -EINVAL; } /* Now actually send the command to the EC and get the result */ args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; args.command_version = msg->version; args.data_size = msg->outsize; /* Initialize checksum */ csum = msg->command + args.flags + args.command_version + args.data_size; /* Copy data and update checksum */ for (i = 0; i < msg->outsize; i++) { outb(msg->outdata[i], EC_LPC_ADDR_HOST_PARAM + i); csum += msg->outdata[i]; } /* Finalize checksum and write args */ args.checksum = csum & 0xFF; outb(args.flags, EC_LPC_ADDR_HOST_ARGS); outb(args.command_version, EC_LPC_ADDR_HOST_ARGS + 1); outb(args.data_size, EC_LPC_ADDR_HOST_ARGS + 2); outb(args.checksum, EC_LPC_ADDR_HOST_ARGS + 3); /* Here we go */ outb(msg->command, EC_LPC_ADDR_HOST_CMD); if (ec_response_timed_out()) { dev_warn(ec->dev, "EC responsed timed out\n"); ret = -EIO; goto done; } /* Check result */ msg->result = inb(EC_LPC_ADDR_HOST_DATA); switch (msg->result) { case EC_RES_SUCCESS: break; case EC_RES_IN_PROGRESS: ret = -EAGAIN; dev_dbg(ec->dev, "command 0x%02x in progress\n", msg->command); goto done; default: dev_dbg(ec->dev, "command 0x%02x returned %d\n", msg->command, msg->result); } /* Read back args */ args.flags = inb(EC_LPC_ADDR_HOST_ARGS); args.command_version = inb(EC_LPC_ADDR_HOST_ARGS + 1); args.data_size = inb(EC_LPC_ADDR_HOST_ARGS + 2); args.checksum = inb(EC_LPC_ADDR_HOST_ARGS + 3); if (args.data_size > msg->insize) { dev_err(ec->dev, "packet too long (%d bytes, expected %d)", args.data_size, msg->insize); ret = -ENOSPC; goto done; } /* Start calculating response checksum */ csum = msg->command + args.flags + args.command_version + args.data_size; /* Read response and update checksum */ for (i = 0; i < args.data_size; i++) { msg->indata[i] = inb(EC_LPC_ADDR_HOST_PARAM + i); csum += msg->indata[i]; } /* Verify checksum */ if (args.checksum != (csum & 0xFF)) { dev_err(ec->dev, "bad packet checksum, expected %02x, got %02x\n", args.checksum, csum & 0xFF); ret = -EBADMSG; goto done; } /* Return actual amount of data received */ ret = args.data_size; done: return ret; }
static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec, struct cros_ec_command *msg) { struct ec_lpc_host_args args; u8 sum; int ret = 0; if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE || msg->insize > EC_PROTO2_MAX_PARAM_SIZE) { dev_err(ec->dev, "invalid buffer sizes (out %d, in %d)\n", msg->outsize, msg->insize); return -EINVAL; } /* Now actually send the command to the EC and get the result */ args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; args.command_version = msg->version; args.data_size = msg->outsize; /* Initialize checksum */ sum = msg->command + args.flags + args.command_version + args.data_size; /* Copy data and update checksum */ sum += cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PARAM, msg->outsize, msg->data); /* Finalize checksum and write args */ args.checksum = sum; cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args); /* Here we go */ sum = msg->command; cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum); if (ec_response_timed_out()) { dev_warn(ec->dev, "EC responsed timed out\n"); ret = -EIO; goto done; } /* Check result */ msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum); ret = cros_ec_check_result(ec, msg); if (ret) goto done; /* Read back args */ cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args); if (args.data_size > msg->insize) { dev_err(ec->dev, "packet too long (%d bytes, expected %d)", args.data_size, msg->insize); ret = -ENOSPC; goto done; } /* Start calculating response checksum */ sum = msg->command + args.flags + args.command_version + args.data_size; /* Read response and update checksum */ sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PARAM, args.data_size, msg->data); /* Verify checksum */ if (args.checksum != sum) { dev_err(ec->dev, "bad packet checksum, expected %02x, got %02x\n", args.checksum, sum); ret = -EBADMSG; goto done; } /* Return actual amount of data received */ ret = args.data_size; done: return ret; }