int es705_uart_fw_download(struct es705_priv *es705, int fw_type) { int rc; dev_info(es705_priv.dev, "%s(): ********* START %s FW Download\n", __func__, fw_type == VOICESENSE ? "VS" : "Standard"); rc = es705_uart_open(es705); if (rc) { dev_err(es705->dev, "%s(): uart open error\n", __func__); goto uart_open_error; } es705_set_tty_baud_rate(UART_DOWNLOAD_INITIAL_SYNC_BAUD_RATE_INDEX); rc = es705_uart_boot_setup(es705); if (rc < 0) { dev_err(es705->dev, "%s(): uart boot setup error\n", __func__); goto uart_download_error; } if (fw_type == VOICESENSE) rc = es705_uart_write(es705, (char *)es705->vs->data, es705->vs->size); else rc = es705_uart_write(es705, (char *)es705->standard->data, es705->standard->size); if (rc < 0) { dev_err(es705->dev, "%s(): uart %s image write fail\n", __func__, fw_type == VOICESENSE ? "vs" : "standard"); rc = -EIO; goto uart_download_error; } dev_info(es705->dev, "%s(): %s fw download done\n", __func__, fw_type == VOICESENSE ? "vs" : "standard"); rc = es705_uart_boot_finish(es705); if (rc < 0) dev_err(es705->dev, "%s(): uart boot finish error\n", __func__); uart_download_error: es705_uart_close(es705); uart_open_error: dev_info(es705_priv.dev, "%s(): ********* END %s FW Download\n", __func__, fw_type == VOICESENSE ? "VS" : "Standard"); return rc; }
int es705_uart_es705_wakeup(struct es705_priv *es705) { int rc; char wakeup_char = 'A'; dev_info(es705_priv.dev, "%s(): ********* START UART wakeup\n", __func__); rc = es705_uart_open(es705); if (rc) { dev_err(es705->dev, "%s(): uart open error\n", __func__); goto es705_uart_es705_wakeup_exit; } /* eS705 wakeup. Write wakeup character to UART */ rc = es705_uart_write(es705, &wakeup_char, sizeof(wakeup_char)); if (rc < 0) dev_err(es705->dev, "%s(): wakeup via uart FAIL\n", __func__); es705_uart_close(es705); es705_uart_es705_wakeup_exit: dev_info(es705_priv.dev, "%s(): ********* END UART wakeup\n", __func__); return rc; }
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; }
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; }