1a838dcc2SGuneshwor Singh /* 2a838dcc2SGuneshwor Singh * cnl-sst-dsp.c - CNL SST library generic function 3a838dcc2SGuneshwor Singh * 4a838dcc2SGuneshwor Singh * Copyright (C) 2016-17, Intel Corporation. 5a838dcc2SGuneshwor Singh * Author: Guneshwor Singh <guneshwor.o.singh@intel.com> 6a838dcc2SGuneshwor Singh * 7a838dcc2SGuneshwor Singh * Modified from: 8a838dcc2SGuneshwor Singh * SKL SST library generic function 9a838dcc2SGuneshwor Singh * Copyright (C) 2014-15, Intel Corporation. 10a838dcc2SGuneshwor Singh * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11a838dcc2SGuneshwor Singh * 12a838dcc2SGuneshwor Singh * This program is free software; you can redistribute it and/or modify 13a838dcc2SGuneshwor Singh * it under the terms of the GNU General Public License as version 2, as 14a838dcc2SGuneshwor Singh * published by the Free Software Foundation. 15a838dcc2SGuneshwor Singh * 16a838dcc2SGuneshwor Singh * This program is distributed in the hope that it will be useful, but 17a838dcc2SGuneshwor Singh * WITHOUT ANY WARRANTY; without even the implied warranty of 18a838dcc2SGuneshwor Singh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19a838dcc2SGuneshwor Singh * General Public License for more details. 20a838dcc2SGuneshwor Singh * 21a838dcc2SGuneshwor Singh * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22a838dcc2SGuneshwor Singh */ 23a838dcc2SGuneshwor Singh #include <linux/device.h> 24a838dcc2SGuneshwor Singh #include "../common/sst-dsp.h" 25a838dcc2SGuneshwor Singh #include "../common/sst-ipc.h" 26a838dcc2SGuneshwor Singh #include "../common/sst-dsp-priv.h" 27a838dcc2SGuneshwor Singh #include "cnl-sst-dsp.h" 28a838dcc2SGuneshwor Singh 29a838dcc2SGuneshwor Singh /* various timeout values */ 30a838dcc2SGuneshwor Singh #define CNL_DSP_PU_TO 50 31a838dcc2SGuneshwor Singh #define CNL_DSP_PD_TO 50 32a838dcc2SGuneshwor Singh #define CNL_DSP_RESET_TO 50 33a838dcc2SGuneshwor Singh 34a838dcc2SGuneshwor Singh static int 35a838dcc2SGuneshwor Singh cnl_dsp_core_set_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 36a838dcc2SGuneshwor Singh { 37a838dcc2SGuneshwor Singh /* update bits */ 38a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, 39a838dcc2SGuneshwor Singh CNL_ADSP_REG_ADSPCS, CNL_ADSPCS_CRST(core_mask), 40a838dcc2SGuneshwor Singh CNL_ADSPCS_CRST(core_mask)); 41a838dcc2SGuneshwor Singh 42a838dcc2SGuneshwor Singh /* poll with timeout to check if operation successful */ 43a838dcc2SGuneshwor Singh return sst_dsp_register_poll(ctx, 44a838dcc2SGuneshwor Singh CNL_ADSP_REG_ADSPCS, 45a838dcc2SGuneshwor Singh CNL_ADSPCS_CRST(core_mask), 46a838dcc2SGuneshwor Singh CNL_ADSPCS_CRST(core_mask), 47a838dcc2SGuneshwor Singh CNL_DSP_RESET_TO, 48a838dcc2SGuneshwor Singh "Set reset"); 49a838dcc2SGuneshwor Singh } 50a838dcc2SGuneshwor Singh 51a838dcc2SGuneshwor Singh static int 52a838dcc2SGuneshwor Singh cnl_dsp_core_unset_reset_state(struct sst_dsp *ctx, unsigned int core_mask) 53a838dcc2SGuneshwor Singh { 54a838dcc2SGuneshwor Singh /* update bits */ 55a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, 56a838dcc2SGuneshwor Singh CNL_ADSPCS_CRST(core_mask), 0); 57a838dcc2SGuneshwor Singh 58a838dcc2SGuneshwor Singh /* poll with timeout to check if operation successful */ 59a838dcc2SGuneshwor Singh return sst_dsp_register_poll(ctx, 60a838dcc2SGuneshwor Singh CNL_ADSP_REG_ADSPCS, 61a838dcc2SGuneshwor Singh CNL_ADSPCS_CRST(core_mask), 62a838dcc2SGuneshwor Singh 0, 63a838dcc2SGuneshwor Singh CNL_DSP_RESET_TO, 64a838dcc2SGuneshwor Singh "Unset reset"); 65a838dcc2SGuneshwor Singh } 66a838dcc2SGuneshwor Singh 67a838dcc2SGuneshwor Singh static bool is_cnl_dsp_core_enable(struct sst_dsp *ctx, unsigned int core_mask) 68a838dcc2SGuneshwor Singh { 69a838dcc2SGuneshwor Singh int val; 70a838dcc2SGuneshwor Singh bool is_enable; 71a838dcc2SGuneshwor Singh 72a838dcc2SGuneshwor Singh val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPCS); 73a838dcc2SGuneshwor Singh 74a838dcc2SGuneshwor Singh is_enable = (val & CNL_ADSPCS_CPA(core_mask)) && 75a838dcc2SGuneshwor Singh (val & CNL_ADSPCS_SPA(core_mask)) && 76a838dcc2SGuneshwor Singh !(val & CNL_ADSPCS_CRST(core_mask)) && 77a838dcc2SGuneshwor Singh !(val & CNL_ADSPCS_CSTALL(core_mask)); 78a838dcc2SGuneshwor Singh 79a838dcc2SGuneshwor Singh dev_dbg(ctx->dev, "DSP core(s) enabled? %d: core_mask %#x\n", 80a838dcc2SGuneshwor Singh is_enable, core_mask); 81a838dcc2SGuneshwor Singh 82a838dcc2SGuneshwor Singh return is_enable; 83a838dcc2SGuneshwor Singh } 84a838dcc2SGuneshwor Singh 85a838dcc2SGuneshwor Singh static int cnl_dsp_reset_core(struct sst_dsp *ctx, unsigned int core_mask) 86a838dcc2SGuneshwor Singh { 87a838dcc2SGuneshwor Singh /* stall core */ 88a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, 89a838dcc2SGuneshwor Singh CNL_ADSPCS_CSTALL(core_mask), 90a838dcc2SGuneshwor Singh CNL_ADSPCS_CSTALL(core_mask)); 91a838dcc2SGuneshwor Singh 92a838dcc2SGuneshwor Singh /* set reset state */ 93a838dcc2SGuneshwor Singh return cnl_dsp_core_set_reset_state(ctx, core_mask); 94a838dcc2SGuneshwor Singh } 95a838dcc2SGuneshwor Singh 96a838dcc2SGuneshwor Singh static int cnl_dsp_start_core(struct sst_dsp *ctx, unsigned int core_mask) 97a838dcc2SGuneshwor Singh { 98a838dcc2SGuneshwor Singh int ret; 99a838dcc2SGuneshwor Singh 100a838dcc2SGuneshwor Singh /* unset reset state */ 101a838dcc2SGuneshwor Singh ret = cnl_dsp_core_unset_reset_state(ctx, core_mask); 102a838dcc2SGuneshwor Singh if (ret < 0) 103a838dcc2SGuneshwor Singh return ret; 104a838dcc2SGuneshwor Singh 105a838dcc2SGuneshwor Singh /* run core */ 106a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, 107a838dcc2SGuneshwor Singh CNL_ADSPCS_CSTALL(core_mask), 0); 108a838dcc2SGuneshwor Singh 109a838dcc2SGuneshwor Singh if (!is_cnl_dsp_core_enable(ctx, core_mask)) { 110a838dcc2SGuneshwor Singh cnl_dsp_reset_core(ctx, core_mask); 111a838dcc2SGuneshwor Singh dev_err(ctx->dev, "DSP core mask %#x enable failed\n", 112a838dcc2SGuneshwor Singh core_mask); 113a838dcc2SGuneshwor Singh ret = -EIO; 114a838dcc2SGuneshwor Singh } 115a838dcc2SGuneshwor Singh 116a838dcc2SGuneshwor Singh return ret; 117a838dcc2SGuneshwor Singh } 118a838dcc2SGuneshwor Singh 119a838dcc2SGuneshwor Singh static int cnl_dsp_core_power_up(struct sst_dsp *ctx, unsigned int core_mask) 120a838dcc2SGuneshwor Singh { 121a838dcc2SGuneshwor Singh /* update bits */ 122a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, 123a838dcc2SGuneshwor Singh CNL_ADSPCS_SPA(core_mask), 124a838dcc2SGuneshwor Singh CNL_ADSPCS_SPA(core_mask)); 125a838dcc2SGuneshwor Singh 126a838dcc2SGuneshwor Singh /* poll with timeout to check if operation successful */ 127a838dcc2SGuneshwor Singh return sst_dsp_register_poll(ctx, CNL_ADSP_REG_ADSPCS, 128a838dcc2SGuneshwor Singh CNL_ADSPCS_CPA(core_mask), 129a838dcc2SGuneshwor Singh CNL_ADSPCS_CPA(core_mask), 130a838dcc2SGuneshwor Singh CNL_DSP_PU_TO, 131a838dcc2SGuneshwor Singh "Power up"); 132a838dcc2SGuneshwor Singh } 133a838dcc2SGuneshwor Singh 134a838dcc2SGuneshwor Singh static int cnl_dsp_core_power_down(struct sst_dsp *ctx, unsigned int core_mask) 135a838dcc2SGuneshwor Singh { 136a838dcc2SGuneshwor Singh /* update bits */ 137a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPCS, 138a838dcc2SGuneshwor Singh CNL_ADSPCS_SPA(core_mask), 0); 139a838dcc2SGuneshwor Singh 140a838dcc2SGuneshwor Singh /* poll with timeout to check if operation successful */ 141a838dcc2SGuneshwor Singh return sst_dsp_register_poll(ctx, 142a838dcc2SGuneshwor Singh CNL_ADSP_REG_ADSPCS, 143a838dcc2SGuneshwor Singh CNL_ADSPCS_CPA(core_mask), 144a838dcc2SGuneshwor Singh 0, 145a838dcc2SGuneshwor Singh CNL_DSP_PD_TO, 146a838dcc2SGuneshwor Singh "Power down"); 147a838dcc2SGuneshwor Singh } 148a838dcc2SGuneshwor Singh 149a838dcc2SGuneshwor Singh int cnl_dsp_enable_core(struct sst_dsp *ctx, unsigned int core_mask) 150a838dcc2SGuneshwor Singh { 151a838dcc2SGuneshwor Singh int ret; 152a838dcc2SGuneshwor Singh 153a838dcc2SGuneshwor Singh /* power up */ 154a838dcc2SGuneshwor Singh ret = cnl_dsp_core_power_up(ctx, core_mask); 155a838dcc2SGuneshwor Singh if (ret < 0) { 156a838dcc2SGuneshwor Singh dev_dbg(ctx->dev, "DSP core mask %#x power up failed", 157a838dcc2SGuneshwor Singh core_mask); 158a838dcc2SGuneshwor Singh return ret; 159a838dcc2SGuneshwor Singh } 160a838dcc2SGuneshwor Singh 161a838dcc2SGuneshwor Singh return cnl_dsp_start_core(ctx, core_mask); 162a838dcc2SGuneshwor Singh } 163a838dcc2SGuneshwor Singh 164a838dcc2SGuneshwor Singh int cnl_dsp_disable_core(struct sst_dsp *ctx, unsigned int core_mask) 165a838dcc2SGuneshwor Singh { 166a838dcc2SGuneshwor Singh int ret; 167a838dcc2SGuneshwor Singh 168a838dcc2SGuneshwor Singh ret = cnl_dsp_reset_core(ctx, core_mask); 169a838dcc2SGuneshwor Singh if (ret < 0) { 170a838dcc2SGuneshwor Singh dev_err(ctx->dev, "DSP core mask %#x reset failed\n", 171a838dcc2SGuneshwor Singh core_mask); 172a838dcc2SGuneshwor Singh return ret; 173a838dcc2SGuneshwor Singh } 174a838dcc2SGuneshwor Singh 175a838dcc2SGuneshwor Singh /* power down core*/ 176a838dcc2SGuneshwor Singh ret = cnl_dsp_core_power_down(ctx, core_mask); 177a838dcc2SGuneshwor Singh if (ret < 0) { 178a838dcc2SGuneshwor Singh dev_err(ctx->dev, "DSP core mask %#x power down failed\n", 179a838dcc2SGuneshwor Singh core_mask); 180a838dcc2SGuneshwor Singh return ret; 181a838dcc2SGuneshwor Singh } 182a838dcc2SGuneshwor Singh 183a838dcc2SGuneshwor Singh if (is_cnl_dsp_core_enable(ctx, core_mask)) { 184a838dcc2SGuneshwor Singh dev_err(ctx->dev, "DSP core mask %#x disable failed\n", 185a838dcc2SGuneshwor Singh core_mask); 186a838dcc2SGuneshwor Singh ret = -EIO; 187a838dcc2SGuneshwor Singh } 188a838dcc2SGuneshwor Singh 189a838dcc2SGuneshwor Singh return ret; 190a838dcc2SGuneshwor Singh } 191a838dcc2SGuneshwor Singh 192a838dcc2SGuneshwor Singh irqreturn_t cnl_dsp_sst_interrupt(int irq, void *dev_id) 193a838dcc2SGuneshwor Singh { 194a838dcc2SGuneshwor Singh struct sst_dsp *ctx = dev_id; 195a838dcc2SGuneshwor Singh u32 val; 196a838dcc2SGuneshwor Singh irqreturn_t ret = IRQ_NONE; 197a838dcc2SGuneshwor Singh 198a838dcc2SGuneshwor Singh spin_lock(&ctx->spinlock); 199a838dcc2SGuneshwor Singh 200a838dcc2SGuneshwor Singh val = sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS); 201a838dcc2SGuneshwor Singh ctx->intr_status = val; 202a838dcc2SGuneshwor Singh 203a838dcc2SGuneshwor Singh if (val == 0xffffffff) { 204a838dcc2SGuneshwor Singh spin_unlock(&ctx->spinlock); 205a838dcc2SGuneshwor Singh return IRQ_NONE; 206a838dcc2SGuneshwor Singh } 207a838dcc2SGuneshwor Singh 208a838dcc2SGuneshwor Singh if (val & CNL_ADSPIS_IPC) { 209a838dcc2SGuneshwor Singh cnl_ipc_int_disable(ctx); 210a838dcc2SGuneshwor Singh ret = IRQ_WAKE_THREAD; 211a838dcc2SGuneshwor Singh } 212a838dcc2SGuneshwor Singh 213a838dcc2SGuneshwor Singh spin_unlock(&ctx->spinlock); 214a838dcc2SGuneshwor Singh 215a838dcc2SGuneshwor Singh return ret; 216a838dcc2SGuneshwor Singh } 217a838dcc2SGuneshwor Singh 218a838dcc2SGuneshwor Singh void cnl_dsp_free(struct sst_dsp *dsp) 219a838dcc2SGuneshwor Singh { 220a838dcc2SGuneshwor Singh cnl_ipc_int_disable(dsp); 221a838dcc2SGuneshwor Singh 222a838dcc2SGuneshwor Singh free_irq(dsp->irq, dsp); 223a838dcc2SGuneshwor Singh cnl_ipc_op_int_disable(dsp); 224a838dcc2SGuneshwor Singh cnl_dsp_disable_core(dsp, SKL_DSP_CORE0_MASK); 225a838dcc2SGuneshwor Singh } 226a838dcc2SGuneshwor Singh EXPORT_SYMBOL_GPL(cnl_dsp_free); 227a838dcc2SGuneshwor Singh 228a838dcc2SGuneshwor Singh void cnl_ipc_int_enable(struct sst_dsp *ctx) 229a838dcc2SGuneshwor Singh { 230a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_ADSPIC, 231a838dcc2SGuneshwor Singh CNL_ADSPIC_IPC, CNL_ADSPIC_IPC); 232a838dcc2SGuneshwor Singh } 233a838dcc2SGuneshwor Singh 234a838dcc2SGuneshwor Singh void cnl_ipc_int_disable(struct sst_dsp *ctx) 235a838dcc2SGuneshwor Singh { 236a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits_unlocked(ctx, CNL_ADSP_REG_ADSPIC, 237a838dcc2SGuneshwor Singh CNL_ADSPIC_IPC, 0); 238a838dcc2SGuneshwor Singh } 239a838dcc2SGuneshwor Singh 240a838dcc2SGuneshwor Singh void cnl_ipc_op_int_enable(struct sst_dsp *ctx) 241a838dcc2SGuneshwor Singh { 242a838dcc2SGuneshwor Singh /* enable IPC DONE interrupt */ 243a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, 244a838dcc2SGuneshwor Singh CNL_ADSP_REG_HIPCCTL_DONE, 245a838dcc2SGuneshwor Singh CNL_ADSP_REG_HIPCCTL_DONE); 246a838dcc2SGuneshwor Singh 247a838dcc2SGuneshwor Singh /* enable IPC BUSY interrupt */ 248a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, 249a838dcc2SGuneshwor Singh CNL_ADSP_REG_HIPCCTL_BUSY, 250a838dcc2SGuneshwor Singh CNL_ADSP_REG_HIPCCTL_BUSY); 251a838dcc2SGuneshwor Singh } 252a838dcc2SGuneshwor Singh 253a838dcc2SGuneshwor Singh void cnl_ipc_op_int_disable(struct sst_dsp *ctx) 254a838dcc2SGuneshwor Singh { 255a838dcc2SGuneshwor Singh /* disable IPC DONE interrupt */ 256a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, 257a838dcc2SGuneshwor Singh CNL_ADSP_REG_HIPCCTL_DONE, 0); 258a838dcc2SGuneshwor Singh 259a838dcc2SGuneshwor Singh /* disable IPC BUSY interrupt */ 260a838dcc2SGuneshwor Singh sst_dsp_shim_update_bits(ctx, CNL_ADSP_REG_HIPCCTL, 261a838dcc2SGuneshwor Singh CNL_ADSP_REG_HIPCCTL_BUSY, 0); 262a838dcc2SGuneshwor Singh } 263a838dcc2SGuneshwor Singh 264a838dcc2SGuneshwor Singh bool cnl_ipc_int_status(struct sst_dsp *ctx) 265a838dcc2SGuneshwor Singh { 266a838dcc2SGuneshwor Singh return sst_dsp_shim_read_unlocked(ctx, CNL_ADSP_REG_ADSPIS) & 267a838dcc2SGuneshwor Singh CNL_ADSPIS_IPC; 268a838dcc2SGuneshwor Singh } 269a838dcc2SGuneshwor Singh 270a838dcc2SGuneshwor Singh void cnl_ipc_free(struct sst_generic_ipc *ipc) 271a838dcc2SGuneshwor Singh { 272a838dcc2SGuneshwor Singh cnl_ipc_op_int_disable(ipc->dsp); 273a838dcc2SGuneshwor Singh sst_ipc_fini(ipc); 274a838dcc2SGuneshwor Singh } 275