| /* Copyright Statement: |
| * |
| * This software/firmware and related documentation ("MediaTek Software") are |
| * protected under relevant copyright laws. The information contained herein |
| * is confidential and proprietary to MediaTek Inc. and/or its licensors. |
| * Without the prior written permission of MediaTek inc. and/or its licensors, |
| * any reproduction, modification, use or disclosure of MediaTek Software, |
| * and information contained herein, in whole or in part, shall be strictly |
| * prohibited. |
| */ |
| /* MediaTek Inc. (C) 2019. All rights reserved. |
| * |
| * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON |
| * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH |
| * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY |
| * ACKNOWLEDGES THAT IT IS RECEIVER\'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY |
| * THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK |
| * SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO |
| * RECEIVER\'S SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN |
| * FORUM. RECEIVER\'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK\'S ENTIRE AND |
| * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER |
| * WILL BE, AT MEDIATEK\'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE |
| * AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY |
| * RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| * |
| * The following software/firmware and/or related documentation |
| * ("MediaTek Software") have been modified by MediaTek Inc. All revisions are |
| * subject to any receiver\'s applicable license agreements with MediaTek Inc. |
| */ |
| |
| #include "scp_ipi.h" |
| #include "encoding.h" |
| |
| |
| static struct ipi_wrapper ipi_legacy_id [] = IPI_LEGACY_GROUP; |
| ipi_handler_t mpool_handle_list[IPI_WRAPPER_TOTAL - IPI_MPOOL - 1]; |
| struct ipi_legacy_pkt { |
| unsigned int id; |
| unsigned int len; |
| void *data; |
| }; |
| |
| /* |
| * This is a handler for handling legacy ipi callback function |
| */ |
| static void legacy_handler(int id, void *prdata, void *data, unsigned int len) |
| { |
| ipi_handler_t handler; |
| unsigned int ptr = (unsigned int)data; |
| struct ipi_legacy_pkt pkt; |
| |
| /* variation length will only support chre, chrex and sensor for reducing |
| * slot and cpu time cost by memcpy. |
| */ |
| pkt.id = *(unsigned int *)ptr; |
| pkt.len = *(unsigned int *)(ptr + 4); |
| pkt.data = (void *)(ptr + 8); |
| |
| if (pkt.id > IPI_MPOOL) |
| handler = mpool_handle_list[pkt.id - IPI_MPOOL - 1]; |
| else |
| handler = (ipi_handler_t)prdata; |
| handler(pkt.id, pkt.data, pkt.len); |
| } |
| |
| /* |
| * Wrapper api for legacy api and supports only legacy features |
| * which is listed in ipi_legacy_id[] |
| */ |
| ipi_status scp_ipi_send(enum ipi_id id, void* buf, uint32_t len, uint32_t wait, |
| enum ipi_dir dir) |
| { |
| int ret = 0, tmp_id; |
| void *ptr; |
| |
| if (id >= IPI_WRAPPER_TOTAL || id == IPI_MPOOL) { |
| PRINTF_E("%s: id not support\n", __func__); |
| return ERROR; |
| } |
| |
| if (id > IPI_MPOOL) |
| tmp_id = IPI_MPOOL; |
| else |
| tmp_id = id; |
| |
| if (len > (ipi_legacy_id[tmp_id].out_size - 2) * MBOX_SLOT_SIZE) { |
| PRINTF_E("%s: len overflow\n", __func__); |
| return ERROR; |
| } |
| |
| /* variation length will only support chre and sensor for reducing slot |
| * and cpu time cost by memcpy. |
| */ |
| char pkt[ipi_legacy_id[tmp_id].out_size * MBOX_SLOT_SIZE]; |
| memcpy((void *)pkt, (void *)&id, sizeof(uint32_t)); |
| memcpy((void *)(pkt + 4), (void *)&len, sizeof(uint32_t)); |
| memcpy((void *)(pkt + 8), buf, len); |
| ptr = pkt; |
| |
| if (mrv_read_csr(CSR_MHARTID) == 0) |
| ret = ipi_send(ipi_legacy_id[tmp_id].out_id_0, ptr, |
| (int)ipi_legacy_id[tmp_id].out_size, |
| wait * IPI_WAIT_LEGACY); |
| else |
| ret = ipi_send(ipi_legacy_id[tmp_id].out_id_1, ptr, |
| (int)ipi_legacy_id[tmp_id].out_size, |
| wait * IPI_WAIT_LEGACY); |
| |
| if (ret == IPI_ACTION_DONE) |
| return DONE; |
| else if (ret == IPI_PIN_BUSY) |
| return BUSY; |
| else |
| return ERROR; |
| } |
| |
| ipi_status scp_ipi_registration(enum ipi_id id, ipi_handler_t handler, |
| const char *name) |
| { |
| int ret = 0; |
| |
| if (id >= IPI_WRAPPER_TOTAL || id == IPI_MPOOL) { |
| PRINTF_E("%s: id not support\n", __func__); |
| return ERROR; |
| } |
| |
| if (id > IPI_MPOOL) { |
| /* if there's any new ipi, hook handler only */ |
| mpool_handle_list[id - IPI_MPOOL - 1] = handler; |
| return DONE; |
| } |
| |
| if (mrv_read_csr(CSR_MHARTID) == 0) { |
| ret = ipi_register(ipi_legacy_id[id].in_id_0, legacy_handler, |
| handler, ipi_legacy_id[id].msg); |
| } else { |
| ret = ipi_register(ipi_legacy_id[id].in_id_1, legacy_handler, |
| handler, ipi_legacy_id[id].msg); |
| } |
| |
| if (ret == IPI_ACTION_DONE) |
| return DONE; |
| else |
| return ERROR; |
| } |
| |
| void scp_legacy_ipi_init(void) |
| { |
| int ret = 0; |
| |
| if (mrv_read_csr(CSR_MHARTID) == 0) { |
| ret = ipi_register(IPI_IN_SCP_MPOOL_0, legacy_handler, 0, |
| msg_legacy_ipi_mpool); |
| } else { |
| ret = ipi_register(IPI_IN_SCP_MPOOL_1, legacy_handler, 0, |
| msg_legacy_ipi_mpool); |
| } |
| |
| if (ret) |
| PRINTF_E("ipi mpool register fail, ret %d\n", ret); |
| } |