int get_lid_switch(void) { #if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) u8 ec_switches; mec_io_bytes(0, EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES, 1, &ec_switches, NULL); return !!(ec_switches & EC_SWITCH_LID_OPEN); #else /* Default to force open. */ return 1; #endif }
/* * Write bytes to a given LPC-mapped address. * * @port: Base write address * @length: Number of bytes to write * @msg: Write data buffer * @csum: Optional parameter, sums data written */ static void write_bytes(u16 port, unsigned int length, u8 *msg, u8 *csum) { int i; #if CONFIG_EC_GOOGLE_CHROMEEC_MEC /* Access desired range though EMI interface */ if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) { mec_io_bytes(1, port, length, msg, csum); return; } #endif for (i = 0; i < length; ++i) { outb(msg[i], port + i); if (csum) *csum += msg[i]; } }
/* * Read bytes from a given LPC-mapped address. * * @port: Base read address * @length: Number of bytes to read * @dest: Destination buffer * @csum: Optional parameter, sums data read */ static void read_bytes(u16 port, unsigned int length, u8 *dest, u8 *csum) { int i; #if CONFIG_EC_GOOGLE_CHROMEEC_MEC /* Access desired range though EMI interface */ if (port >= MEC_EMI_RANGE_START && port <= MEC_EMI_RANGE_END) { mec_io_bytes(0, port, length, dest, csum); return; } #endif for (i = 0; i < length; ++i) { dest[i] = inb(port + i); if (csum) *csum += dest[i]; } }
int get_recovery_mode_switch(void) { #if IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) u8 ec_switches; u32 ec_events; mec_io_bytes(0, EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SWITCHES, 1, &ec_switches, NULL); /* If a switch is set, we don't need to look at events. */ if (ec_switches & (EC_SWITCH_DEDICATED_RECOVERY)) return 1; /* Else check if the EC has posted the keyboard recovery event. */ ec_events = google_chromeec_get_events_b(); return !!(ec_events & EC_HOST_EVENT_MASK(EC_HOST_EVENT_KEYBOARD_RECOVERY)); #else return 0; #endif }
static int wilco_ec_transfer(struct wilco_ec_message *msg) { struct wilco_ec_request rq; struct wilco_ec_response rs; uint8_t checksum; size_t skip_size; /* Prepare request packet */ wilco_ec_prepare(msg, &rq); /* Write request header */ mec_io_bytes(MEC_IO_WRITE, CONFIG_EC_BASE_PACKET, 0, &rq, sizeof(rq)); /* Write request data */ mec_io_bytes(MEC_IO_WRITE, CONFIG_EC_BASE_PACKET, sizeof(rq), msg->data, msg->request_size); /* Start the command */ outb(EC_MAILBOX_START_COMMAND, CONFIG_EC_BASE_HOST_COMMAND); /* Wait for it to complete */ if (wilco_ec_response_timed_out()) { printk(BIOS_ERR, "%s: response timed out\n", __func__); return -1; } /* Some commands will put the EC into a state where it cannot respond */ if (msg->type == WILCO_EC_MSG_NO_RESPONSE) { printk(BIOS_DEBUG, "%s: EC does not respond to this command\n", __func__); return 0; } /* Check result */ msg->result = inb(CONFIG_EC_BASE_HOST_DATA); if (msg->result != 0) { printk(BIOS_ERR, "%s: bad response: 0x%02x\n", __func__, msg->result); return -1; } /* Read back response */ checksum = mec_io_bytes(MEC_IO_READ, CONFIG_EC_BASE_PACKET, 0, &rs, sizeof(rs)); if (checksum) { printk(BIOS_ERR, "%s: bad checksum %02x\n", __func__, checksum); return -1; } msg->result = rs.result; /* EC always returns EC_MAILBOX_DATA_SIZE bytes */ if (rs.data_size > EC_MAILBOX_DATA_SIZE) { printk(BIOS_ERR, "%s: packet too long (%d bytes, expected %d)", __func__, rs.data_size, EC_MAILBOX_DATA_SIZE); return -1; } /* Skip response data bytes as requested */ skip_size = (msg->type == WILCO_EC_MSG_DEFAULT) ? 1 : 0; if (msg->response_size > rs.data_size - skip_size) { printk(BIOS_ERR, "%s: data too short (%lu bytes, expected %zu)", __func__, rs.data_size - skip_size, msg->response_size); return -1; } memcpy(msg->data, rs.data + skip_size, msg->response_size); /* Return actual amount of data received */ return msg->response_size; }