Lines Matching +full:ipc +full:- +full:3

1 // SPDX-License-Identifier: GPL-2.0-only
3 * skl-sst-ipc.c - Intel skl IPC Support
5 * Copyright (C) 2014-15, Intel Corporation.
9 #include "../common/sst-dsp.h"
10 #include "../common/sst-dsp-priv.h"
12 #include "skl-sst-dsp.h"
13 #include "skl-sst-ipc.h"
19 /* Global Message - Generic */
24 /* Global Message - Reply */
26 #define IPC_GLB_REPLY_STATUS_MASK ((0x1 << IPC_GLB_REPLY_STATUS_SHIFT) - 1)
177 /* Set D0ix IPC extension register */
222 IPC_GLB_REPLY_BUSY = 3,
252 IPC_MAX_STATUS = ((1<<IPC_IXC_STATUS_BITS)-1)
259 IPC_GLB_NOTIFY_END_STREAM = 3,
272 IPC_MOD_LARGE_CONFIG_GET = 3,
284 memcpy(msg->tx.data, tx_data, tx_size); in skl_ipc_tx_data_copy()
296 static void skl_ipc_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg) in skl_ipc_tx_msg() argument
298 struct skl_ipc_header *header = (struct skl_ipc_header *)(&msg->tx.header); in skl_ipc_tx_msg()
300 if (msg->tx.size) in skl_ipc_tx_msg()
301 sst_dsp_outbox_write(ipc->dsp, msg->tx.data, msg->tx.size); in skl_ipc_tx_msg()
302 sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCIE, in skl_ipc_tx_msg()
303 header->extension); in skl_ipc_tx_msg()
304 sst_dsp_shim_write_unlocked(ipc->dsp, SKL_ADSP_REG_HIPCI, in skl_ipc_tx_msg()
305 header->primary | SKL_ADSP_REG_HIPCI_BUSY); in skl_ipc_tx_msg()
313 if (!dsp->fw_ops.set_state_D0i0) in skl_ipc_check_D0i0()
318 ret = dsp->fw_ops.set_state_D0i0(dsp); in skl_ipc_check_D0i0()
320 ret = dsp->fw_ops.set_state_D0i3(dsp); in skl_ipc_check_D0i0()
325 static struct ipc_message *skl_ipc_reply_get_msg(struct sst_generic_ipc *ipc, in skl_ipc_reply_get_msg() argument
331 if (list_empty(&ipc->rx_list)) { in skl_ipc_reply_get_msg()
332 dev_err(ipc->dev, "ipc: rx list is empty but received 0x%x\n", in skl_ipc_reply_get_msg()
333 header->primary); in skl_ipc_reply_get_msg()
337 msg = list_first_entry(&ipc->rx_list, struct ipc_message, list); in skl_ipc_reply_get_msg()
339 list_del(&msg->list); in skl_ipc_reply_get_msg()
345 int skl_ipc_process_notification(struct sst_generic_ipc *ipc, in skl_ipc_process_notification() argument
348 struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); in skl_ipc_process_notification()
354 dev_err(ipc->dev, "FW Underrun %x\n", header.primary); in skl_ipc_process_notification()
358 dev_err(ipc->dev, "MCPS Budget Violation: %x\n", in skl_ipc_process_notification()
363 skl->boot_complete = true; in skl_ipc_process_notification()
364 wake_up(&skl->boot_wait); in skl_ipc_process_notification()
368 dev_dbg(ipc->dev, "***** Phrase Detected **********\n"); in skl_ipc_process_notification()
376 skl->enable_miscbdcge(ipc->dev, false); in skl_ipc_process_notification()
377 skl->miscbdcg_disabled = true; in skl_ipc_process_notification()
381 dev_err(ipc->dev, "ipc: Unhandled error msg=%x\n", in skl_ipc_process_notification()
397 {"DSP out of memory", IPC_GLB_REPLY_OUT_OF_MEMORY, -ENOMEM},
398 {"DSP busy", IPC_GLB_REPLY_BUSY, -EBUSY},
405 static int skl_ipc_set_reply_error_code(struct sst_generic_ipc *ipc, u32 reply) in skl_ipc_set_reply_error_code() argument
415 dev_err(ipc->dev, "ipc FW reply: %d FW Error Code: %u\n", in skl_ipc_set_reply_error_code()
417 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); in skl_ipc_set_reply_error_code()
418 return -EINVAL; in skl_ipc_set_reply_error_code()
422 dev_err(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n", in skl_ipc_set_reply_error_code()
424 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); in skl_ipc_set_reply_error_code()
426 dev_info(ipc->dev, "ipc FW reply: %s FW Error Code: %u\n", in skl_ipc_set_reply_error_code()
428 ipc->dsp->fw_ops.get_fw_errcode(ipc->dsp)); in skl_ipc_set_reply_error_code()
433 void skl_ipc_process_reply(struct sst_generic_ipc *ipc, in skl_ipc_process_reply() argument
439 struct skl_dev *skl = container_of(ipc, struct skl_dev, ipc); in skl_ipc_process_reply()
442 spin_lock_irqsave(&ipc->dsp->spinlock, flags); in skl_ipc_process_reply()
443 msg = skl_ipc_reply_get_msg(ipc, *ipc_header); in skl_ipc_process_reply()
444 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); in skl_ipc_process_reply()
446 dev_dbg(ipc->dev, "ipc: rx list is empty\n"); in skl_ipc_process_reply()
450 msg->rx.header = *ipc_header; in skl_ipc_process_reply()
453 dev_dbg(ipc->dev, "ipc FW reply %x: success\n", header.primary); in skl_ipc_process_reply()
455 sst_dsp_inbox_read(ipc->dsp, msg->rx.data, msg->rx.size); in skl_ipc_process_reply()
459 skl->mod_load_complete = true; in skl_ipc_process_reply()
460 skl->mod_load_status = true; in skl_ipc_process_reply()
461 wake_up(&skl->mod_load_wait); in skl_ipc_process_reply()
469 msg->errno = skl_ipc_set_reply_error_code(ipc, reply); in skl_ipc_process_reply()
473 skl->mod_load_complete = true; in skl_ipc_process_reply()
474 skl->mod_load_status = false; in skl_ipc_process_reply()
475 wake_up(&skl->mod_load_wait); in skl_ipc_process_reply()
484 spin_lock_irqsave(&ipc->dsp->spinlock, flags); in skl_ipc_process_reply()
485 sst_ipc_tx_msg_reply_complete(ipc, msg); in skl_ipc_process_reply()
486 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); in skl_ipc_process_reply()
492 struct skl_dev *skl = dsp->thread_context; in skl_dsp_irq_thread_handler()
493 struct sst_generic_ipc *ipc = &skl->ipc; in skl_dsp_irq_thread_handler() local
498 if (dsp->intr_status & SKL_ADSPIS_CL_DMA) in skl_dsp_irq_thread_handler()
501 /* Here we handle IPC interrupts only */ in skl_dsp_irq_thread_handler()
502 if (!(dsp->intr_status & SKL_ADSPIS_IPC)) in skl_dsp_irq_thread_handler()
514 /* clear DONE bit - tell DSP we have completed the operation */ in skl_dsp_irq_thread_handler()
529 dev_dbg(dsp->dev, "IPC irq: Firmware respond primary:%x\n", in skl_dsp_irq_thread_handler()
531 dev_dbg(dsp->dev, "IPC irq: Firmware respond extension:%x\n", in skl_dsp_irq_thread_handler()
536 skl_ipc_process_reply(ipc, header); in skl_dsp_irq_thread_handler()
538 dev_dbg(dsp->dev, "IPC irq: Notification from firmware\n"); in skl_dsp_irq_thread_handler()
539 skl_ipc_process_notification(ipc, header); in skl_dsp_irq_thread_handler()
553 schedule_work(&ipc->kwork); in skl_dsp_irq_thread_handler()
572 /* enable IPC DONE interrupt */ in skl_ipc_op_int_enable()
576 /* Enable IPC BUSY interrupt */ in skl_ipc_op_int_enable()
583 /* disable IPC DONE interrupt */ in skl_ipc_op_int_disable()
587 /* Disable IPC BUSY interrupt */ in skl_ipc_op_int_disable()
601 struct sst_generic_ipc *ipc; in skl_ipc_init() local
604 ipc = &skl->ipc; in skl_ipc_init()
605 ipc->dsp = skl->dsp; in skl_ipc_init()
606 ipc->dev = dev; in skl_ipc_init()
608 ipc->tx_data_max_size = SKL_ADSP_W1_SZ; in skl_ipc_init()
609 ipc->rx_data_max_size = SKL_ADSP_W0_UP_SZ; in skl_ipc_init()
611 err = sst_ipc_init(ipc); in skl_ipc_init()
615 ipc->ops.tx_msg = skl_ipc_tx_msg; in skl_ipc_init()
616 ipc->ops.tx_data_copy = skl_ipc_tx_data_copy; in skl_ipc_init()
617 ipc->ops.is_dsp_busy = skl_ipc_is_dsp_busy; in skl_ipc_init()
622 void skl_ipc_free(struct sst_generic_ipc *ipc) in skl_ipc_free() argument
624 /* Disable IPC DONE interrupt */ in skl_ipc_free()
625 sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, in skl_ipc_free()
628 /* Disable IPC BUSY interrupt */ in skl_ipc_free()
629 sst_dsp_shim_update_bits(ipc->dsp, SKL_ADSP_REG_HIPCCTL, in skl_ipc_free()
632 sst_ipc_fini(ipc); in skl_ipc_free()
635 int skl_ipc_create_pipeline(struct sst_generic_ipc *ipc, in skl_ipc_create_pipeline() argument
652 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); in skl_ipc_create_pipeline()
653 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_create_pipeline()
655 dev_err(ipc->dev, "ipc: create pipeline fail, err: %d\n", ret); in skl_ipc_create_pipeline()
663 int skl_ipc_delete_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) in skl_ipc_delete_pipeline() argument
675 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); in skl_ipc_delete_pipeline()
676 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_delete_pipeline()
678 dev_err(ipc->dev, "ipc: delete pipeline failed, err %d\n", ret); in skl_ipc_delete_pipeline()
686 int skl_ipc_set_pipeline_state(struct sst_generic_ipc *ipc, in skl_ipc_set_pipeline_state() argument
700 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); in skl_ipc_set_pipeline_state()
701 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_set_pipeline_state()
703 dev_err(ipc->dev, "ipc: set pipeline state failed, err: %d\n", ret); in skl_ipc_set_pipeline_state()
711 skl_ipc_save_pipeline(struct sst_generic_ipc *ipc, u8 instance_id, int dma_id) in skl_ipc_save_pipeline() argument
725 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); in skl_ipc_save_pipeline()
726 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_save_pipeline()
728 dev_err(ipc->dev, "ipc: save pipeline failed, err: %d\n", ret); in skl_ipc_save_pipeline()
736 int skl_ipc_restore_pipeline(struct sst_generic_ipc *ipc, u8 instance_id) in skl_ipc_restore_pipeline() argument
748 dev_dbg(ipc->dev, "In %s header=%d\n", __func__, header.primary); in skl_ipc_restore_pipeline()
749 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_restore_pipeline()
751 dev_err(ipc->dev, "ipc: restore pipeline failed, err: %d\n", ret); in skl_ipc_restore_pipeline()
759 int skl_ipc_set_dx(struct sst_generic_ipc *ipc, u8 instance_id, in skl_ipc_set_dx() argument
776 dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, in skl_ipc_set_dx()
778 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_set_dx()
780 dev_err(ipc->dev, "ipc: set dx failed, err %d\n", ret); in skl_ipc_set_dx()
788 int skl_ipc_init_instance(struct sst_generic_ipc *ipc, in skl_ipc_init_instance() argument
796 u16 param_block_size = msg->param_data_size / sizeof(u32); in skl_ipc_init_instance()
804 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); in skl_ipc_init_instance()
805 header.primary |= IPC_MOD_ID(msg->module_id); in skl_ipc_init_instance()
807 header.extension = IPC_CORE_ID(msg->core_id); in skl_ipc_init_instance()
808 header.extension |= IPC_PPL_INSTANCE_ID(msg->ppl_instance_id); in skl_ipc_init_instance()
810 header.extension |= IPC_DOMAIN(msg->domain); in skl_ipc_init_instance()
814 request.size = msg->param_data_size; in skl_ipc_init_instance()
816 dev_dbg(ipc->dev, "In %s primary =%x ext=%x\n", __func__, in skl_ipc_init_instance()
818 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_init_instance()
821 dev_err(ipc->dev, "ipc: init instance failed\n"); in skl_ipc_init_instance()
829 int skl_ipc_bind_unbind(struct sst_generic_ipc *ipc, in skl_ipc_bind_unbind() argument
834 u8 bind_unbind = msg->bind ? IPC_MOD_BIND : IPC_MOD_UNBIND; in skl_ipc_bind_unbind()
840 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); in skl_ipc_bind_unbind()
841 header.primary |= IPC_MOD_ID(msg->module_id); in skl_ipc_bind_unbind()
843 header.extension = IPC_DST_MOD_ID(msg->dst_module_id); in skl_ipc_bind_unbind()
844 header.extension |= IPC_DST_MOD_INSTANCE_ID(msg->dst_instance_id); in skl_ipc_bind_unbind()
845 header.extension |= IPC_DST_QUEUE(msg->dst_queue); in skl_ipc_bind_unbind()
846 header.extension |= IPC_SRC_QUEUE(msg->src_queue); in skl_ipc_bind_unbind()
849 dev_dbg(ipc->dev, "In %s hdr=%x ext=%x\n", __func__, header.primary, in skl_ipc_bind_unbind()
851 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_bind_unbind()
853 dev_err(ipc->dev, "ipc: bind/unbind failed\n"); in skl_ipc_bind_unbind()
862 * In order to load a module we need to send IPC to initiate that. DMA will
864 * at single shot, so we can send IPC with N modules represented by
867 int skl_ipc_load_modules(struct sst_generic_ipc *ipc, in skl_ipc_load_modules() argument
883 ret = sst_ipc_tx_message_nowait(ipc, request); in skl_ipc_load_modules()
885 dev_err(ipc->dev, "ipc: load modules failed :%d\n", ret); in skl_ipc_load_modules()
891 int skl_ipc_unload_modules(struct sst_generic_ipc *ipc, u8 module_cnt, in skl_ipc_unload_modules() argument
907 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_unload_modules()
909 dev_err(ipc->dev, "ipc: unload modules failed :%d\n", ret); in skl_ipc_unload_modules()
915 int skl_ipc_set_large_config(struct sst_generic_ipc *ipc, in skl_ipc_set_large_config() argument
926 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); in skl_ipc_set_large_config()
927 header.primary |= IPC_MOD_ID(msg->module_id); in skl_ipc_set_large_config()
929 header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); in skl_ipc_set_large_config()
930 header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); in skl_ipc_set_large_config()
934 sz_remaining = msg->param_data_size; in skl_ipc_set_large_config()
942 dev_dbg(ipc->dev, "In %s primary=%#x ext=%#x\n", __func__, in skl_ipc_set_large_config()
944 dev_dbg(ipc->dev, "transmitting offset: %#x, size: %#x\n", in skl_ipc_set_large_config()
950 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_ipc_set_large_config()
952 dev_err(ipc->dev, in skl_ipc_set_large_config()
953 "ipc: set large config fail, err: %d\n", ret); in skl_ipc_set_large_config()
956 sz_remaining -= tx_size; in skl_ipc_set_large_config()
957 data_offset = msg->param_data_size - sz_remaining; in skl_ipc_set_large_config()
971 int skl_ipc_get_large_config(struct sst_generic_ipc *ipc, in skl_ipc_get_large_config() argument
982 return -ENOMEM; in skl_ipc_get_large_config()
987 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); in skl_ipc_get_large_config()
988 header.primary |= IPC_MOD_ID(msg->module_id); in skl_ipc_get_large_config()
990 header.extension = IPC_DATA_OFFSET_SZ(msg->param_data_size); in skl_ipc_get_large_config()
991 header.extension |= IPC_LARGE_PARAM_ID(msg->large_param_id); in skl_ipc_get_large_config()
1000 ret = sst_ipc_tx_message_wait(ipc, request, &reply); in skl_ipc_get_large_config()
1002 dev_err(ipc->dev, "ipc: get large config fail, err: %d\n", ret); in skl_ipc_get_large_config()
1007 return -ENOMEM; in skl_ipc_get_large_config()
1015 int skl_sst_ipc_load_library(struct sst_generic_ipc *ipc, in skl_sst_ipc_load_library() argument
1030 ret = sst_ipc_tx_message_wait(ipc, request, NULL); in skl_sst_ipc_load_library()
1032 ret = sst_ipc_tx_message_nowait(ipc, request); in skl_sst_ipc_load_library()
1035 dev_err(ipc->dev, "ipc: load lib failed\n"); in skl_sst_ipc_load_library()
1041 int skl_ipc_set_d0ix(struct sst_generic_ipc *ipc, struct skl_ipc_d0ix_msg *msg) in skl_ipc_set_d0ix() argument
1050 header.primary |= IPC_MOD_INSTANCE_ID(msg->instance_id); in skl_ipc_set_d0ix()
1051 header.primary |= IPC_MOD_ID(msg->module_id); in skl_ipc_set_d0ix()
1053 header.extension = IPC_D0IX_WAKE(msg->wake); in skl_ipc_set_d0ix()
1054 header.extension |= IPC_D0IX_STREAMING(msg->streaming); in skl_ipc_set_d0ix()
1057 dev_dbg(ipc->dev, "In %s primary=%x ext=%x\n", __func__, in skl_ipc_set_d0ix()
1061 * Use the nopm IPC here as we dont want it checking for D0iX in skl_ipc_set_d0ix()
1063 ret = sst_ipc_tx_message_nopm(ipc, request, NULL); in skl_ipc_set_d0ix()
1065 dev_err(ipc->dev, "ipc: set d0ix failed, err %d\n", ret); in skl_ipc_set_d0ix()