| /* 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) 2015. 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. |
| */ |
| |
| #include <FreeRTOS.h> |
| #include <task.h> |
| #ifdef CFG_LEGACY_IPI_SUPPORT |
| #include <scp_ipi.h> |
| #else |
| #include <ipi.h> |
| #include <ipi_id.h> |
| #endif |
| |
| #include <scp_scpctl.h> |
| #include <main.h> |
| #include "encoding.h" |
| #include "irq.h" |
| #ifdef CFG_XGPT_SUPPORT |
| #include <mt_gpt.h> |
| #endif |
| |
| enum SCPCTL_STAT_E { |
| SCPCTL_STAT_INACTIVE = 0, |
| SCPCTL_STAT_ACTIVE, |
| }; |
| |
| struct scpctl_ctl_s { |
| enum SCPCTL_OP_E op; |
| enum SCPCTL_STAT_E stat; |
| }; |
| |
| #define mainCHECK_DELAY ((portTickType) 10000 / portTICK_RATE_MS) |
| |
| static struct scpctl_ctl_s scpctl __attribute__ ((section(".sync"))); |
| static char *prompt = "[SCPCTL]"; |
| static TaskHandle_t xMonitorTask = NULL; |
| struct scpctl_cmd_s scpctl_cmd_s_buf __attribute__ ((section(".sync"))); |
| |
| #ifdef CFG_SCP_STRESS_SUPPORT |
| unsigned int task_stress_flag __attribute__((section(".sync"))) = 0; |
| #endif |
| |
| #ifdef CFG_SCPCTL_TASK_STATUS |
| static char list_buffer[512]; |
| |
| static void __task_status(void) |
| { |
| vTaskList(list_buffer); |
| PRINTF_E("Heap:free/total:%lu/%u\n", xPortGetFreeHeapSize(), configTOTAL_HEAP_SIZE); |
| PRINTF_E("Task Status:\n\r%s", list_buffer); |
| // PRINTF_E("max dur.:%llu,limit:%llu\n", get_max_cs_duration_time(), get_max_cs_limit()); |
| } |
| #endif |
| |
| void vTaskMonitor(void *pvParameters) |
| { |
| portTickType xLastExecutionTime, xDelayTime; |
| xDelayTime = mainCHECK_DELAY; |
| |
| do { |
| xLastExecutionTime = xTaskGetTickCount(); |
| |
| #ifdef CFG_SCPCTL_TASK_STATUS |
| __task_status(); |
| #endif |
| #ifdef CFG_MRV_UNALIGN_SUPPORT |
| PRINTF_E("unaligned Load/Store times (%u/%u)\n", misalignedLoad, misalignedStore); |
| #endif |
| vTaskDelayUntil(&xLastExecutionTime, xDelayTime); |
| } while (1); |
| } |
| |
| |
| /**************************************************************************** |
| * The ISR is to receive the IPI commands sent by ADB and then modify |
| * the operation, op, of the control state. |
| ****************************************************************************/ |
| static void scpctl_handler(unsigned int id, void *prdata, void *data, unsigned int len) |
| { |
| struct scpctl_cmd_s *cmd = (struct scpctl_cmd_s *)data; |
| enum SCPCTL_TYPE_E type = cmd->type; |
| enum SCPCTL_OP_E op = cmd->op; |
| |
| switch (type) { |
| case SCPCTL_TYPE_TMON: |
| scpctl.op = (op == SCPCTL_OP_ACTIVE) |
| ? SCPCTL_OP_ACTIVE |
| : SCPCTL_OP_INACTIVE; |
| |
| PRINTF_E("%s: type/op=%d/%d,stat=%d\n", prompt, type, op, scpctl.stat); |
| break; |
| #ifdef CFG_SCP_STRESS_SUPPORT |
| case SCPCTL_STRESS_TEST: |
| task_stress_flag = 1; |
| PRINTF_E("Stress enabled\n"); |
| break; |
| #endif |
| default: |
| PRINTF_E("%s: unknown cmd, %d, %d\n", prompt, type, op); |
| break; |
| } |
| } |
| |
| /**************************************************************************** |
| * The function is called by in vApplicationIdleHook and determine whether |
| * to resume or to suspend monitor task depending on the command and the |
| * current status. |
| * |
| * op = active, state = inactive --> resume monitor task. |
| * op = inactive, state = active --> suspend monitor task. |
| * others, keep the same status. |
| ****************************************************************************/ |
| void scpctl_idlehook(void) |
| { |
| int op = scpctl.op; |
| |
| if (op == SCPCTL_OP_ACTIVE && scpctl.stat == SCPCTL_STAT_INACTIVE) { |
| vTaskResume(xMonitorTask); |
| scpctl.stat = SCPCTL_STAT_ACTIVE; |
| } |
| else if (op == SCPCTL_OP_INACTIVE && scpctl.stat == SCPCTL_STAT_ACTIVE) { |
| vTaskSuspend(xMonitorTask); |
| scpctl.stat = SCPCTL_STAT_INACTIVE; |
| } |
| } |
| |
| |
| #ifdef CFG_SCP_STRESS_SUPPORT |
| |
| /* run on both core */ |
| static void vTaskSCPStress(void *pvParameters) |
| { |
| portTickType xLastExecutionTime, xDelayTime; |
| xLastExecutionTime = xTaskGetTickCount(); |
| unsigned int get_random_time; |
| xDelayTime = (portTickType) 60000 / portTICK_RATE_MS ; |
| do { |
| PRINTF_E("Task Stress "); |
| if (task_stress_flag == 0) { |
| PRINTF_E("status=%u\n", task_stress_flag); |
| } else { |
| /* stress flag is enable*/ |
| PRINTF_E("status=%u, stress enable!\n", task_stress_flag); |
| /* get 60 ~120 sec delay*/ |
| #ifdef CFG_XGPT_SUPPORT |
| get_random_time = (unsigned int)(get_boot_time_ns() % 60); |
| get_random_time = (30 + get_random_time) * 1000; |
| xDelayTime = (portTickType) get_random_time / portTICK_RATE_MS ; |
| #endif |
| PRINTF_E("after:%ums, will abort...\n", xDelayTime); |
| vTaskDelayUntil(&xLastExecutionTime, xDelayTime); |
| configASSERT(0); |
| } |
| xDelayTime = (portTickType) 60000 / portTICK_RATE_MS ; |
| vTaskDelayUntil(&xLastExecutionTime, xDelayTime); |
| } while (1); |
| } |
| #endif |
| |
| void scpctl_init(void) |
| { |
| int ret = 0; |
| |
| xTaskCreate(vTaskMonitor, "TMon", 384, (void*)4, PRI_MONITOR, &xMonitorTask); |
| configASSERT(xMonitorTask != NULL); |
| #ifdef CFG_SCP_STRESS_SUPPORT |
| xTaskCreate(vTaskSCPStress, "Stres", 384, (void*)4, PRI_STRESS, NULL); |
| #endif /* CFG_SCP_STRESS_SUPPORT */ |
| |
| if (scp_region_info.scpctl & (1 << SCPCTL_TYPE_TMON)) { |
| scpctl.stat = SCPCTL_STAT_ACTIVE; |
| scpctl.op = SCPCTL_OP_ACTIVE; |
| } |
| else { /* monitor task is in suspened state */ |
| scpctl.stat = SCPCTL_STAT_INACTIVE; |
| scpctl.op = SCPCTL_OP_INACTIVE; |
| vTaskSuspend(xMonitorTask); |
| } |
| /* uni-control, do it only ine one core */ |
| if (mrv_read_csr(CSR_MHARTID) == 1) { |
| ret = ipi_register(IPI_IN_SCPCTL_1, scpctl_handler, 0, &scpctl_cmd_s_buf); |
| if (ret) |
| PRINTF_E("IPI_IN_SCPCTL_1 %d\n", ret); |
| } |
| |
| |
| } |
| |