blob: 994d583dd04b6124e8094393aaa8ba766e0adc8b [file] [log] [blame]
/* 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);
}
}