int escore_vs_load(struct escore_priv *escore) { struct escore_voice_sense *voice_sense = (struct escore_voice_sense *) escore->voice_sense; int rc = 0; int write_size = ES_VS_FW_CHUNK; int data_remaining = voice_sense->vs->size; u32 sync_cmd = (ES_EVENT_RESPONSE_CMD << 16) | ES_SYNC_INTR_RISING_EDGE; u32 resp; BUG_ON(voice_sense->vs->size == 0); if (!escore->boot_ops.setup || !escore->boot_ops.finish) { dev_err(escore->dev, "%s(): boot setup or finish function undefined\n", __func__); rc = -EIO; goto escore_vs_fw_download_failed; } rc = escore->boot_ops.setup(escore); if (rc) { dev_err(escore->dev, "%s(): fw download start error\n", __func__); goto escore_vs_fw_download_failed; } dev_dbg(escore->dev, "%s(): write vs firmware image\n", __func__); while (data_remaining) { rc = escore->bus.ops.high_bw_write(escore, ((char *)voice_sense->vs->data) + (voice_sense->vs->size - data_remaining), write_size); data_remaining -= write_size; dev_dbg(escore->dev, "data_remaining = %d, write_size = %d\n", data_remaining, write_size); if (rc) { dev_err(escore->dev, "%s(): vs firmware image write error\n", __func__); rc = -EIO; goto escore_vs_fw_download_failed; } else if (data_remaining < write_size) { write_size = data_remaining; } usleep_range(2000, 2000); } escore->mode = VOICESENSE; if (((struct escore_voice_sense *)escore->voice_sense)->vs_irq != true) escore_vs_init_intr(escore); rc = escore->boot_ops.finish(escore); if (rc) { dev_err(escore->dev, "%s() vs fw download finish error\n", __func__); goto escore_vs_fw_download_failed; } else { /* Enable Voice Sense Event INTR to Host */ rc = escore_cmd(escore, sync_cmd, &resp); if (rc) dev_err(escore->dev, "%s(): escore_cmd fail %d\n", __func__, rc); if (resp != sync_cmd) { dev_err(escore->dev, "%s(): Enable VS Event INTR fail\n", __func__); goto escore_vs_fw_download_failed; } } dev_dbg(escore->dev, "%s(): fw download done\n", __func__); escore_vs_fw_download_failed: return rc; }
int escore_vs_load(struct escore_priv *escore) { struct escore_voice_sense *voice_sense = (struct escore_voice_sense *) escore->voice_sense; u32 cmd, resp; int rc = 0; BUG_ON(voice_sense->vs->size == 0); escore->mode = VOICESENSE_PENDING; if (!escore->boot_ops.setup || !escore->boot_ops.finish) { dev_err(escore->dev, "%s(): boot setup or finish function undefined\n", __func__); rc = -EIO; goto escore_vs_uart_open_failed; } if (escore->bus.ops.high_bw_open) { rc = escore->bus.ops.high_bw_open(escore); if (rc) { dev_err(escore->dev, "%s(): high_bw_open failed %d\n", __func__, rc); goto escore_vs_uart_open_failed; } } rc = escore->boot_ops.setup(escore); if (rc) { dev_err(escore->dev, "%s(): fw download start error\n", __func__); goto escore_vs_fw_download_failed; } rc = escore_is_sleep_aborted(escore); if (rc == -EABORT) { /* after boot setup, firmware download is initiated and can be * aborted by sending abort keyword. This abort word is located * in the firmware binary image, comprised of the 4 bytes * starting at binary offset 0x000C. So host has to write * at least 16 byte so that abort code is known to chip. * Firmware abort sequence is mentioned in BUG #20899 */ rc = escore->bus.ops.high_bw_write(escore, ((char *)voice_sense->vs->data) , 20); if (rc) { dev_err(escore->dev, "%s(): vs firmware data write error\n", __func__); rc = -EIO; goto escore_vs_fw_download_failed; } /* Write abort keyword */ cmd = *(u32 *)(voice_sense->vs->data + 0x000c); rc = escore->bus.ops.high_bw_write(escore, &cmd , 4); if (rc) { dev_err(escore->dev, "%s(): abort word write error\n", __func__); rc = -EIO; goto escore_vs_fw_download_failed; } if (escore->high_bw_intf == ES_UART_INTF) { if (escore->boot_ops.escore_abort_config) escore->boot_ops.escore_abort_config(escore); } cmd = ES_SET_POWER_STATE_CMD << 16 | ES_SET_POWER_STATE_NORMAL; rc = escore->bus.ops.high_bw_cmd(escore, cmd , &resp); if (rc) { dev_err(escore->dev, "%s(): power state cmd error\n", __func__); rc = -EIO; goto escore_vs_fw_download_failed; } rc = -EABORT; goto escore_sleep_aborted; } dev_dbg(escore->dev, "%s(): write vs firmware image\n", __func__); rc = escore->bus.ops.high_bw_write(escore, ((char *)voice_sense->vs->data) , voice_sense->vs->size); if (rc) { dev_err(escore->dev, "%s(): vs firmware image write error\n", __func__); rc = -EIO; goto escore_vs_fw_download_failed; } rc = escore_is_sleep_aborted(escore); if (rc == -EABORT) goto escore_sleep_aborted; escore->mode = VOICESENSE; if (((struct escore_voice_sense *)escore->voice_sense)->vs_irq != true) escore_vs_init_intr(escore); rc = escore->boot_ops.finish(escore); if (rc) { dev_err(escore->dev, "%s() vs fw download finish error\n", __func__); goto escore_vs_fw_download_failed; } /* Set smooth mute to 0 */ cmd = ES_SET_SMOOTH_MUTE << 16 | ES_SMOOTH_MUTE_ZERO; rc = escore->bus.ops.cmd(escore, cmd, &resp); if (rc) { dev_err(escore->dev, "%s(): escore_cmd(%08x) fail %d\n", __func__, cmd, rc); goto escore_vs_fw_download_failed; } #ifdef CONFIG_ARCH_EXYNOS cmd = 0x805200f3; // DHWPT: Port-A connected to Port-D rc = escore->bus.ops.cmd(escore, cmd, &resp); if (rc) { dev_err(escore->dev, "%s(): escore_cmd(%08x) fail %d\n", __func__, cmd, rc); goto escore_vs_fw_download_failed; } #endif rc = escore_is_sleep_aborted(escore); if (rc == -EABORT) goto escore_sleep_aborted; rc = escore_reconfig_intr(escore); if (rc) { dev_err(escore->dev, "%s() config resume failed after VS load rc = %d\n", __func__, rc); goto escore_vs_fw_download_failed; } dev_dbg(escore->dev, "%s(): fw download done\n", __func__); escore_sleep_aborted: escore_vs_fw_download_failed: if (escore->bus.ops.high_bw_close) { rc = escore->bus.ops.high_bw_close(escore); if (rc) { dev_err(escore->dev, "%s(): high_bw_close failed %d\n", __func__, rc); } } escore_vs_uart_open_failed: return rc; }