int es705_uart_cmd(struct es705_priv *es705, u32 cmd, int sr, u32 *resp) { int err; u32 rv; dev_dbg(es705->dev, "%s(): cmd=0x%08x sr=%i\n", __func__, cmd, sr); cmd = cpu_to_be32(cmd); err = es705_uart_write(es705, &cmd, sizeof(cmd)); if (err < 0 || sr) goto es705_uart_cmd_exit; /* Maximum response time is 10ms */ usleep_range(10000, 10000); err = es705_uart_read(es705, &rv, sizeof(rv)); if (err > 0) { dev_dbg(es705->dev, "%s(): response=0x%08x\n", __func__, rv); *resp = be32_to_cpu(rv); } else if (err == 0) { dev_dbg(es705->dev, "%s(): No response\n", __func__); } else { dev_err(es705->dev, "%s(): UART read fail\n", __func__); } es705_uart_cmd_exit: return err; }
static int es705_uart_boot_finish(struct es705_priv *es705) { u32 sync_cmd; u32 sync_resp; char msg[4]; int rc; /* * Give the chip some time to become ready after firmware * download. (FW is still transferring) */ msleep(50); /* * Read 4 bytes of VS FW download status * TODO To avoid possible problem in the future * if FW goes to send less or more then 4 bytes * Need modify code to read UART until read * buffer is empty */ rc = es705_uart_read(es705, msg, 4); if (rc < 0) dev_err(es705->dev, "%s(): UART read fail\n", __func__); else dev_dbg(es705->dev, "%s(): read byte = 0x%02x%02x%02x%02x\n", __func__, msg[0], msg[1], msg[2], msg[3]); if (es705->es705_power_state == ES705_SET_POWER_STATE_VS_OVERLAY) { sync_cmd = (ES705_SYNC_CMD << 16) | ES705_SYNC_INTR_RISING_EDGE; dev_info(es705->dev, "%s(): FW type : VOICESENSE\n", __func__); } else { sync_cmd = (ES705_SYNC_CMD << 16) | ES705_SYNC_POLLING; dev_info(es705->dev, "%s(): FW type : STANDARD\n", __func__); } dev_dbg(es705->dev, "%s(): write ES705_SYNC_CMD = 0x%08x\n", __func__, sync_cmd); rc = es705_uart_cmd(es705, sync_cmd, 0, &sync_resp); if (rc < 0) { dev_err(es705->dev, "%s(): firmware load failed (no sync response)\n", __func__); goto es705_boot_finish_failed; } if (sync_cmd != sync_resp) { dev_err(es705->dev, "%s(): firmware load failed, invalid sync response 0x%08x\n", __func__, sync_resp); rc = -EIO; goto es705_boot_finish_failed; } dev_dbg(es705->dev, "%s(): firmware load success 0x%08x\n", __func__, sync_resp); es705_boot_finish_failed: return rc; }
int es705_uart_write_then_read(struct es705_priv *es705, const void *buf, int len, u32 *rspn, int match) { int rc; u32 response = 0; rc = es705_uart_write(es705, buf, len); if (rc > 0) { rc = es705_uart_read(es705, &response, len); response = le32_to_cpu(response); if (rc < 0) { dev_err(es705->dev, "%s(): UART read fail\n", __func__); } else if (match && *rspn != response) { dev_err(es705->dev, "%s(): unexpected response 0x%08x\n", __func__, be32_to_cpu(response)); rc = -EIO; } else { *rspn = response; } } return rc; }
int es705_uart_dev_wdb(struct es705_priv *es705, const void *buf, int len) { /* At this point the command has been determined and is not part * of the data in the buffer. Its just data. Note that we donot * evaluate the contents of the data. It is up to the higher layers * to insure the the codes mode of operation matchs what is being * sent. */ int ret; u32 resp; u8 *dptr; u32 cmd = ES705_WDB_CMD << 16; dev_dbg(es705->dev, "%s(): len = 0x%08x\n", __func__, len); dptr = (char *)buf; cmd = cmd | (len & 0xFFFF); dev_dbg(es705->dev, "%s(): cmd = 0x%08x\n", __func__, cmd); cmd = cpu_to_be32(cmd); ret = es705_uart_write_then_read(es705, &cmd, sizeof(cmd), &resp, 0); if (ret < 0) { dev_err(es705->dev, "%s(): cmd write err=%hu\n", __func__, ret); goto wdb_err; } be32_to_cpus(&resp); dev_dbg(es705->dev, "%s(): resp = 0x%08x\n", __func__, resp); if ((resp & 0xffff0000) != (ES705_WDB_CMD << 16)) { dev_err(es705->dev, "%s(): invalid write data block 0x%08x\n", __func__, resp); goto wdb_err; } /* The API requires that the subsequent writes are to be * a byte stream (one byte per transport transaction) */ ret = es705_uart_write(es705, dptr, len); if (ret < 0) { dev_err(es705->dev, "%s(): wdb error =%d\n", __func__, ret); goto wdb_err; } /* One last ACK read */ ret = es705_uart_read(es705, &resp, 4); if (ret < 0) { dev_err(es705->dev, "%s(): last ack %d\n", __func__, ret); goto wdb_err; } if (resp & 0xff000000) { dev_err(es705->dev, "%s(): write data block error 0x%0x\n", __func__, resp); goto wdb_err; } dev_dbg(es705->dev, "%s(): len = %d\n", __func__, len); goto exit; wdb_err: len = -EIO; exit: return len; }
int es705_uart_dev_rdb(struct es705_priv *es705, void *buf, int id) { u32 cmd; u32 resp; u8 *dptr; int ret; int size; int rdcnt = 0; dptr = (u8 *) buf; /* Read voice sense keyword data block request. */ cmd = (ES705_RDB_CMD << 16) | (id & 0xFFFF); cmd = cpu_to_be32(cmd); ret = es705_uart_write(es705, (char *)&cmd, 4); if (ret < 0) { dev_err(es705->dev, "%s(): RDB cmd write err = %d\n", __func__, ret); goto rdb_err; } /* Refer to "ES705 Advanced API Guide" for details of interface */ usleep_range(10000, 11000); ret = es705_uart_read(es705, (char *)&resp, 4); if (ret < 0) { dev_err(es705->dev, "%s(): error sending request = %d\n", __func__, ret); goto rdb_err; } be32_to_cpus(&resp); size = resp & 0xffff; dev_dbg(es705->dev, "%s(): resp=0x%08x size=%d\n", __func__, resp, size); if ((resp & 0xffff0000) != (ES705_RDB_CMD << 16)) { dev_err(es705->dev, "%s(): invalid read v-s data block response = 0x%08x\n", __func__, resp); goto rdb_err; } if (size == 0) { dev_err(es705->dev, "%s(): read request return size of 0\n", __func__); goto rdb_err; } if (size > PARSE_BUFFER_SIZE) size = PARSE_BUFFER_SIZE; for (rdcnt = 0; rdcnt < size; rdcnt++, dptr++) { ret = es705_uart_read(es705, dptr, 1); if (ret < 0) { dev_err(es705->dev, "%s(): data block ed error %d bytes ret = %d\n", __func__, rdcnt, ret); goto rdb_err; } } es705->rdb_read_count = size; ret = 0; goto exit; rdb_err: es705->rdb_read_count = 0; ret = -EIO; exit: return ret; }
int es705_uart_dev_rdb(struct es705_priv *es705, void *buf, int id) { u32 cmd; u32 resp; u8 *dptr; int ret; int size; int rdcnt = 0; #if defined(CONFIG_MQ100_SENSOR_HUB) u8 pad; /* Take Mutex for the duration of this UART transaction. */ mutex_lock(&es705_priv.uart_transaction_mutex); #endif dptr = (u8 *)buf; /* Read voice sense keyword data block request. */ cmd = (ES705_RDB_CMD << 16) | (id & 0xFFFF); cmd = cpu_to_be32(cmd); ret = es705_uart_write(es705, (char *)&cmd, 4); if (ret < 0) { dev_err(es705->dev, "%s(): RDB cmd write err = %d\n", __func__, ret); goto rdb_err; } /* Refer to "ES705 Advanced API Guide" for details of interface */ usleep_range(10000, 10000); ret = es705_uart_read(es705, (char *)&resp, 4); if (ret < 0) { dev_err(es705->dev, "%s(): error sending request = %d\n", __func__, ret); goto rdb_err; } be32_to_cpus(&resp); size = resp & 0xffff; dev_dbg(es705->dev, "%s(): resp=0x%08x size=%d\n", __func__, resp, size); if ((resp & 0xffff0000) != (ES705_RDB_CMD << 16)) { dev_err(es705->dev, "%s(): invalid read v-s data block response = 0x%08x\n", __func__, resp); goto rdb_err; } if (size == 0) { dev_err(es705->dev, "%s(): read request return size of 0\n", __func__); goto rdb_err; } if (size > PARSE_BUFFER_SIZE) size = PARSE_BUFFER_SIZE; for (rdcnt = 0; rdcnt < size; rdcnt++, dptr++) { ret = es705_uart_read(es705, dptr, 1); if (ret < 0) { dev_err(es705->dev, "%s(): data block ed error %d bytes ret = %d\n", __func__, rdcnt, ret); goto rdb_err; } } es705->rdb_read_count = size; #if defined(CONFIG_MQ100_SENSOR_HUB) size = PAD4(size); dev_dbg(es705->dev, "%s: Discarding %d pad bytes\n", __func__, size); ret = 0; while ((size > 0) && (ret >= 0)) { ret = es705_uart_read(es705, &pad, 1); size--; } #endif ret = 0; goto exit; rdb_err: es705->rdb_read_count = 0; ret = -EIO; exit: #if defined(CONFIG_MQ100_SENSOR_HUB) /* release UART transaction mutex */ mutex_unlock(&es705_priv.uart_transaction_mutex); #endif return ret; }