You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1494 lines
41 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2013-2020. All rights reserved.
* Description:sys drv
* Author: Hisilicon
* Create: 2013-01-01
*/
#include "drv_sys_ext.h"
#include "soc_log.h"
#include <linux/huanglong/utils/hlkapi.h>
#include <linux/interrupt.h>
#include "linux/huanglong/utils/drv_license.h"
#include "td_type.h"
#include "osal_ext.h"
#include "reg_common_ext.h"
#include "drv_dev_ext.h"
#include "drv_module_ext.h"
#include "drv_sys_ext.h"
#include "drv_mem_ext.h"
#include "drv_ioctl_sys.h"
#include "drv_reg.h"
#include "drv_sys_policy.h"
#include "hal_sys.h"
#include "linux/huanglong/securec.h"
#define SYS_NS_TO_MS 1000000
#define SYS_REGISTER_SIZE 8
/* for irq request, define the CPU num macro */
#define SYS_FIRST_CPU_INDEX 0
#define SYS_MEDIA_CPU_INDEX 1
#define SYS_GENERAL_DEV_CPU_INDEX 2
static td_char g_common_version[] __attribute__((used)) = VERSION_STRING;
static osal_semaphore g_sys_k_sem;
/* global video codec support status */
static ext_sys_video_codec g_video_codec = SYS_VIDEO_MASK;
td_s32 drv_sys_init(td_void)
{
td_s32 ret;
ret = hal_sys_page_size_write2register();
if (ret != TD_SUCCESS) {
soc_log_err("page size write2register failed.\n");
return TD_FAILURE;
}
return osal_sem_init(&g_sys_k_sem, 1);
}
td_void drv_sys_exit(td_void)
{
osal_sem_destroy(&g_sys_k_sem);
}
ext_chip_package_type ext_drv_sys_get_chip_package_type(td_void)
{
ext_chip_package_type type = CHIP_PACKAGE_TYPE_BUTT;
td_s32 ret;
ret = hal_sys_get_chip_package_type(&type);
if (ret != TD_SUCCESS) {
soc_log_err("hal get chip package type failed!\n");
}
return type;
}
td_u32 ext_drv_sys_get_time_stamp_ms(td_void)
{
td_u64 time_now;
time_now = osal_sched_clock();
time_now = osal_div_u64(time_now, SYS_NS_TO_MS);
return (td_u32)time_now;
}
/*
* from datasheet, the value of dolby_flag meaning: 0: support; 1: not support.
* but we change its meaning for return parameter: 0: not support; 1: support.
*/
td_s32 ext_drv_sys_get_dolby_support(td_u32 *dolby_support)
{
td_bool is_support;
td_s32 ret;
if (dolby_support == TD_NULL) {
soc_log_err("support_dolby is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_dolby_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get dolby support failed!\n");
return TD_FAILURE;
}
*dolby_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_dolby_ddpluse_support(td_u32 *dolby_ddpluse_support)
{
td_bool is_support;
td_s32 ret;
if (dolby_ddpluse_support == TD_NULL) {
soc_log_err("support_dolby ddpluse is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_dolby_ddpluse_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get dolby ddpluse support failed!\n");
return TD_FAILURE;
}
*dolby_ddpluse_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_hdr10_support(td_u32 *hdr10_support)
{
td_bool is_support;
td_s32 ret;
if (hdr10_support == TD_NULL) {
soc_log_err("support_hdr10 is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_hdr10_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get hdr10 support failed!\n");
return TD_FAILURE;
}
*hdr10_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_dolby_vision_support(td_u32 *dolby_vision_support)
{
td_bool is_support;
td_s32 ret;
if (dolby_vision_support == TD_NULL) {
soc_log_err("support_dolby_vision is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_dolby_vision_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get dolby vision support failed!\n");
return TD_FAILURE;
}
*dolby_vision_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
/* 1: support; 0: not_support */
td_s32 ext_drv_sys_get_dts_support(td_u32 *dts_support)
{
td_bool is_support;
td_s32 ret;
if (dts_support == TD_NULL) {
soc_log_err("support_dts is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_dts_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get dts support failed!\n");
return TD_FAILURE;
}
*dts_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
/* 1: support; 0: not_support */
td_s32 ext_drv_sys_get_rovi_support(td_u32 *rovi_support)
{
td_bool is_support;
td_s32 ret;
if (rovi_support == TD_NULL) {
soc_log_err("support_rovi is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_rovi_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get rovi support failed!\n");
return TD_FAILURE;
}
*rovi_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
/* 1: support; 0: not_support */
td_s32 ext_drv_sys_get_advca_support(td_u32 *advca_support)
{
td_bool is_support;
td_s32 ret;
if (advca_support == TD_NULL) {
soc_log_err("support_advca is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_advca_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get advca support failed!\n");
return TD_FAILURE;
}
*advca_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_ks_support(td_u32 *ks_support)
{
td_bool is_support;
td_s32 ret;
if (ks_support == TD_NULL) {
soc_log_err("ks_support is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_ks_support(&is_support);
if (ret != TD_SUCCESS) {
soc_log_err("hal get ks support failed!\n");
return TD_FAILURE;
}
*ks_support = is_support ? 1 : 0;
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_mem_cfg(td_u32 *mem_size, td_u32 *mmz_size)
{
td_s32 ret;
if (mem_size == TD_NULL) {
soc_log_err("mem_size is null\n");
return TD_FAILURE;
}
if (mmz_size == TD_NULL) {
soc_log_err("mmz_size is null\n");
return TD_FAILURE;
}
ret = get_mem_size(mem_size, HLKAPI_GET_RAM_SIZE);
if (ret != TD_SUCCESS) {
soc_log_err("get ram size failed\n");
return TD_FAILURE;
}
ret = get_mem_size(mmz_size, HLKAPI_GET_CMA_SIZE);
if (ret != TD_SUCCESS) {
soc_log_err("get mmz size failed\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_smp_support(td_bool *smp_support)
{
if (smp_support == TD_NULL) {
soc_log_err("attr is null\n");
return TD_FAILURE;
}
*smp_support = TD_FALSE;
return TD_SUCCESS;
}
td_s32 ext_drv_sys_disable_video_codec(ext_sys_video_codec video_codec)
{
td_s32 ret;
ret = osal_sem_down_interruptible(&g_sys_k_sem);
if (ret != 0) {
soc_log_err("sys sem lock failed. \n");
return TD_FAILURE;
}
g_video_codec = (td_u32)g_video_codec & (~((td_u32)video_codec));
osal_sem_up(&g_sys_k_sem);
return TD_SUCCESS;
}
ext_sys_video_codec ext_drv_sys_get_video_codec_support(td_void)
{
return g_video_codec;
}
td_s32 ext_drv_sys_write_register(const td_u32 reg_addr, const td_u32 value)
{
td_s32 ret;
td_void *virt = TD_NULL;
ret = hal_sys_check_reg_addr(reg_addr, TD_TRUE);
if (ret != TD_SUCCESS) {
soc_log_err("sys write register: invalid reg_addr 0x%x\n", reg_addr);
return TD_FAILURE;
}
ret = osal_sem_down_interruptible(&g_sys_k_sem);
if (ret != 0) {
soc_log_err("sys write register: sys sem lock failed. \n");
return TD_FAILURE;
}
virt = osal_ioremap(reg_addr, SYS_REGISTER_SIZE);
if (virt == TD_NULL) {
osal_sem_up(&g_sys_k_sem);
soc_log_info("sys write register: ioremap failed!\n");
return TD_FAILURE;
}
osal_writel(value, virt);
osal_iounmap(virt, OSAL_IOUNMAP_SIZE);
osal_sem_up(&g_sys_k_sem);
return TD_SUCCESS;
}
td_s32 ext_drv_sys_read_register(const td_u32 reg_addr, td_u32 *value)
{
td_s32 ret;
td_void *virt = TD_NULL;
if (value == TD_NULL) {
soc_log_err("Null point!\n");
return TD_FAILURE;
}
ret = hal_sys_check_reg_addr(reg_addr, TD_FALSE);
if (ret != TD_SUCCESS) {
soc_log_err("sys read register: invalid reg_addr 0x%x\n", reg_addr);
return TD_FAILURE;
}
ret = osal_sem_down_interruptible(&g_sys_k_sem);
if (ret != 0) {
soc_log_err("sys read register: sys sem lock failed. \n");
return TD_FAILURE;
}
virt = osal_ioremap(reg_addr, SYS_REGISTER_SIZE);
if (virt == TD_NULL) {
osal_sem_up(&g_sys_k_sem);
soc_log_info("sys read register: ioremap failed!\n");
return TD_FAILURE;
}
*value = osal_readl(virt);
osal_iounmap(virt, OSAL_IOUNMAP_SIZE);
osal_sem_up(&g_sys_k_sem);
return TD_SUCCESS;
}
volatile ext_reg_sys_ctrl *ext_drv_sys_get_ctrl_reg_ptr(td_void)
{
return drv_sys_get_ctrl_reg_ptr();
}
volatile ext_reg_peri *ext_drv_sys_get_peri_reg_ptr(td_void)
{
return drv_sys_get_peri_reg_ptr();
}
volatile ext_reg_io *ext_drv_sys_get_io_reg_ptr(td_void)
{
return drv_sys_get_io_reg_ptr();
}
volatile ext_reg_crg *ext_drv_sys_get_crg_reg_ptr(td_void)
{
return drv_sys_get_crg_reg_ptr();
}
volatile ext_reg_aon_crg *ext_drv_sys_get_aon_crg_reg_ptr(td_void)
{
return drv_sys_get_aon_crg_reg_ptr();
}
td_s32 ext_drv_sys_get_die_id_64bit(td_u64 *die_id)
{
td_s32 ret;
ret = osal_sem_down_interruptible(&g_sys_k_sem);
if (ret != 0) {
soc_log_err("sys sem lock failed. \n");
return TD_FAILURE;
}
ret = hal_sys_get_die_id_64bit(die_id);
if (ret != TD_SUCCESS) {
soc_log_err("hal get die id failed!\n");
*die_id = 0;
}
osal_sem_up(&g_sys_k_sem);
return ret;
}
/* get the register value on address 0x253(bit[31~30]) of otp */
char *get_chiptrim_value(char *buf, unsigned int buflen, unsigned int offset);
int get_chiptrim_size(void);
td_s32 ext_drv_sys_get_die_id(td_u32 *die_id)
{
td_s32 ret = TD_SUCCESS;
const td_u32 id = 0x0;
*die_id = id;
return ret;
}
td_s32 ext_drv_sys_get_board_id(td_u32 *board_id)
{
if (board_id == NULL) {
soc_log_err("invalid board id!\n");
return TD_FAILURE;
}
return hal_sys_get_board_id(board_id);
}
td_s32 ext_drv_sys_get_chip_name_id(ext_chip_name_id *chip_name_id)
{
if (chip_name_id == TD_NULL) {
soc_log_err("invalid input parameter\n");
return TD_FAILURE;
}
return hal_sys_get_chip_name_id(chip_name_id, TD_NULL);
}
td_s32 ext_drv_sys_get_chip_revision(ext_chip_revision *chip_revision)
{
if (chip_revision == TD_NULL) {
soc_log_err("invalid input parameter\n");
return TD_FAILURE;
}
return hal_sys_get_chip_name_id(TD_NULL, chip_revision);
}
static td_s32 ext_drv_sys_set_irq_affinity_inter(td_s32 cpu_index, td_u32 irq, const td_char *name)
{
td_s32 ret;
if (!cpu_online(cpu_index)) {
soc_log_err("cpu num %d is offline, irq num is %u, name is %s!\n", cpu_index, irq, name);
return TD_FAILURE;
}
ret = irq_set_affinity(irq, cpumask_of(cpu_index));
if (ret != TD_SUCCESS) {
soc_log_err("cpumask error, cpu num is %d, irq num is %u, name is %s!\n", cpu_index, irq, name);
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 ext_drv_sys_set_irq_affinity(const soc_mod_id module_id, const td_u32 irq_num, const td_char *name)
{
td_s32 cpu_index = 0;
td_u32 irq;
if (module_id >= SOC_ID_MAX) {
soc_log_err("Invalid module id!\n");
return TD_FAILURE;
}
irq = (td_u32)osal_get_irq_by_name((td_char *)name);
if (irq == -1) {
soc_log_err("ext_drv_sys_get_irq_by_name:%s failed.\n", name);
return TD_FAILURE;
}
/* only SMP cores and core numbers must be more than or equal to 2 */
if (num_online_cpus() < 0x2) {
soc_log_info("No need to set irq affinity!\n");
return TD_SUCCESS;
}
switch (module_id) {
case SOC_ID_IR:
case SOC_ID_I2C:
case SOC_ID_SCI:
case SOC_ID_WDG:
case SOC_ID_GPIO:
case SOC_ID_GPIO_I2C:
case SOC_ID_KEYLED:
cpu_index = SYS_GENERAL_DEV_CPU_INDEX;
soc_log_info("Gereral device interrupts use CPU %d!\n", SYS_GENERAL_DEV_CPU_INDEX);
break;
#ifdef CONFIG_SOCT_FPGA_SUPPORT
#ifdef CONFIG_SOCT_TEE_SUPPORT
/* TO avoid VPSS's reg r/w operation collision with VDH. (they are both on FPGA4) */
case SOC_ID_VFMW:
case SOC_ID_VPSS:
cpu_index = 0;
break;
#endif
#endif
default:
cpu_index = SYS_MEDIA_CPU_INDEX;
soc_log_info("Media interrupts use CPU %d!\n", SYS_MEDIA_CPU_INDEX);
break;
}
return ext_drv_sys_set_irq_affinity_inter(cpu_index, irq, name);
}
td_s32 ext_drv_sys_get_package_id(td_u32 *package_id)
{
td_s32 ret;
if (package_id == TD_NULL) {
soc_log_err("package_id is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_package_id(package_id);
if (ret != TD_SUCCESS) {
soc_log_err("hal get package id failed!\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_tee_mode(td_bool *tee_mode)
{
td_s32 ret;
if (tee_mode == TD_NULL) {
soc_log_err("tee_mode is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_tee_mode(tee_mode);
if (ret != TD_SUCCESS) {
soc_log_err("hal get tee mode failed!\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 ext_drv_sys_get_chip_secure_mode(td_bool *secure_mode)
{
td_s32 ret;
if (secure_mode == TD_NULL) {
soc_log_err("secure_mode is null\n");
return TD_FAILURE;
}
ret = hal_sys_get_chip_secure_mode(secure_mode);
if (ret != TD_SUCCESS) {
soc_log_err("hal get chip secure mode failed!\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
/*
* value: 0: normal mode, other: special mode.
* EPLL0 address: 0xF8A22030, 0x12560418: special mode, other: normal mode.
*/
td_s32 ext_drv_sys_get_flag(td_u32 *flag)
{
return TD_FAILURE;
}
td_s32 ext_drv_sys_get_audio_op_mode(td_void)
{
return -1;
}
td_s32 ext_drv_sys_get_disp_vdac_drive_mode(td_void)
{
return -1;
}
td_bool ext_drv_sys_check_phy_addr(td_ulong addr)
{
return TD_TRUE;
}
static td_s32 drv_copy_to_user_buf(struct file *file, td_u32 cmd, td_ulong arg, td_void *parg, ext_ioctl func)
{
td_s32 err;
err = func(file, cmd, (parg));
if (err == -ENOIOCTLCMD) {
err = -EINVAL;
}
if (err < 0) {
return err;
}
switch (_IOC_DIR(cmd)) {
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (((void __user *)(uintptr_t)arg != TD_NULL) && (parg != TD_NULL)) {
if (osal_copy_to_user((void __user *)(uintptr_t)arg, parg, _IOC_SIZE(cmd))) {
soc_log_fatal("osal_copy_to_user failed, when use ioctl, the para must be a address, cmd=0x%x\n",
cmd);
err = -EFAULT;
}
} else {
soc_log_fatal("parg is null!\n");
}
break;
/* when the user runs the write only command, no content is returned. */
case _IOC_WRITE:
case _IOC_NONE:
break;
default:
soc_log_err("cmd %x is invalid!\n", _IOC_DIR(cmd));
}
return err;
}
td_slong ext_drv_user_copy(struct file *file, td_u32 cmd, td_ulong arg, ext_ioctl func)
{
td_char sbuf[128]; /* array num is 128 */
td_void *mbuf = NULL;
td_void *parg = NULL;
td_s32 err = -EINVAL;
/* Copy arguments into temp kernel buffer */
switch (_IOC_DIR(cmd)) {
case _IOC_NONE:
parg = NULL;
break;
case _IOC_READ:
case _IOC_WRITE:
case (_IOC_WRITE | _IOC_READ):
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
parg = sbuf;
} else {
td_u32 buff_size = _IOC_SIZE(cmd);
/* too big to allocate from stack */
mbuf = SOC_KZALLOC(SOC_ID_MEM, buff_size, GFP_KERNEL);
if (mbuf == NULL) {
soc_log_fatal("malloc cmd buffer failed\n");
return -ENOMEM;
}
parg = mbuf;
}
err = -EFAULT;
if (_IOC_DIR(cmd) & _IOC_WRITE) {
if ((void __user *)(uintptr_t)arg == TD_NULL) {
soc_log_fatal("arg is null\n");
goto out;
}
if (osal_copy_from_user(parg, (void __user *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
soc_log_fatal("osal_copy_from_user failed, when use ioctl, the para must be a address, cmd=0x%x\n",
cmd);
goto out;
}
}
break;
default:
soc_log_fatal("cmd %x invalid\n", _IOC_DIR(cmd));
}
/* call driver */
if (func == TD_NULL) {
goto out;
}
/* Copy results into user buffer */
err = drv_copy_to_user_buf(file, cmd, arg, parg, func);
out:
if (mbuf != TD_NULL) {
SOC_KFREE(SOC_ID_MEM, mbuf);
mbuf = TD_NULL;
}
return err;
}
td_s32 drv_sys_get_boot_version(td_char *version, td_u32 len)
{
const td_char *boot_version = TD_NULL;
td_s32 ret;
td_u32 ver_len = len - 1;
ret = osal_dts_get_string_byname("huanglong,common", "boot_version", &boot_version);
if (ret < 0) {
soc_log_err("osal_dts_get_string_byname get huanglong,common failure line:%d\n", __LINE__);
return TD_FAILURE;
}
if (version == TD_NULL || len == 0) {
soc_log_err("drv_sys_get_boot_version failure line:%d\n", __LINE__);
return TD_FAILURE;
}
if (boot_version != TD_NULL) {
if (ver_len > strlen(boot_version)) {
ver_len = strlen(boot_version);
} else {
soc_log_err("drv_sys_get_boot_version input buf too short\n");
return TD_FAILURE;
}
ret = memcpy_s (version, len, boot_version, ver_len);
if (ret != EOK) {
soc_log_err("memcpy_s error\n");
return TD_FAILURE;
}
version[len - 1] = '\0';
return TD_SUCCESS;
}
return TD_FAILURE;
}
static td_s32 drv_sys_ioctl_get_build_variant(td_u32 *build_variant)
{
if (build_variant == TD_NULL) {
soc_log_err("ptr_build_variant is null\n");
return TD_FAILURE;
}
*build_variant = (td_u32)osal_get_buildvariant();
return TD_SUCCESS;
}
static td_s32 drv_sys_ioctl_get_chip_data(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_VERSION: {
ext_sys_version *sys_version = (ext_sys_version *)arg;
if (sys_version != TD_NULL) {
ext_drv_sys_get_chip_name_id(&sys_version->chip_name_id);
ext_drv_sys_get_chip_revision(&sys_version->chip_revision);
drv_sys_get_boot_version(sys_version->boot_version, sizeof(sys_version->boot_version));
ext_drv_sys_get_sos_version(sys_version->sos_version, sizeof(sys_version->sos_version));
ret = TD_SUCCESS;
}
break;
}
case SYS_GET_BOARDID_CFG: {
td_u32 *board_id = (td_u32*)arg;
if (board_id != TD_NULL) {
ret = ext_drv_sys_get_board_id(board_id);
}
break;
}
case SYS_GET_CHIP_PACKAGE_TYPE: {
ext_chip_package_type *package_type = (ext_chip_package_type *)arg;
if (package_type != TD_NULL) {
*package_type = ext_drv_sys_get_chip_package_type();
ret = TD_SUCCESS;
}
break;
}
case SYS_GET_SMP_SUPPORT:
if (arg != TD_NULL) {
ret = ext_drv_sys_get_smp_support((td_bool *)arg);
}
break;
default:
soc_log_err("unknown command 0x%x\n", cmd);
}
return ret;
}
static td_s32 drv_sys_ioctl_get_die_id(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_DIE_ID_64: {
td_u64 *die_id = (td_u64*)arg;
if (die_id != TD_NULL) {
ret = ext_drv_sys_get_die_id_64bit(die_id);
}
break;
}
case SYS_GET_DIE_ID_32: {
td_u32 *die_id = (td_u32*)arg;
if (die_id != TD_NULL) {
ret = ext_drv_sys_get_die_id(die_id);
}
break;
}
default:
soc_log_err("unknown command 0x%x\n", cmd);
}
return ret;
}
static td_s32 drv_sys_ioctl_get_uart_info(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_UART_NUM: {
if (arg != TD_NULL) {
td_u32 *uart_num = (td_u32*)arg;
ext_drv_sys_get_uart_number(uart_num);
ret = TD_SUCCESS;
}
break;
}
case SYS_SWITCH_UART: {
if (arg != TD_NULL) {
td_u32 ttyama = *((td_u32*)arg);
ret = ext_drv_sys_switch_uart(ttyama);
}
break;
}
default:
soc_log_err("unknown command 0x%x\n", cmd);
}
return ret;
}
static td_s32 drv_sys_ioctl_get_other_data(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_TIME_STAMP_MS: {
td_u32 *time_ms = (td_u32 *)arg;
if (time_ms != TD_NULL) {
*time_ms = ext_drv_sys_get_time_stamp_ms();
ret = TD_SUCCESS;
}
break;
}
case SYS_GET_DDR_CFG: {
sys_mem_info *mem = (sys_mem_info*)arg;
td_u32 mem_size = 0;
td_u32 mmz_size = 0;
if (mem == TD_NULL) {
ret = TD_FAILURE;
break;
}
ret = ext_drv_sys_get_mem_cfg(&mem_size, &mmz_size);
if (ret == TD_SUCCESS) {
mem->mem_size = mem_size;
mem->mmz_size = mmz_size;
}
break;
}
case SYS_GET_CAPABILITY: {
if (arg != TD_NULL) {
if (ext_drv_sys_get_capability(*((ext_sys_capability_type *)arg))) {
ret = TD_SUCCESS;
} else {
ret = TD_FAILURE;
}
}
break;
}
default:
soc_log_err("unknown command 0x%x\n", cmd);
}
return ret;
}
static td_s32 drv_sys_ioctl_part1(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_VERSION:
case SYS_GET_BOARDID_CFG:
case SYS_GET_CHIP_PACKAGE_TYPE:
case SYS_GET_SMP_SUPPORT:
ret = drv_sys_ioctl_get_chip_data(cmd, arg, private_data);
break;
case SYS_GET_DIE_ID_64:
case SYS_GET_DIE_ID_32:
ret = drv_sys_ioctl_get_die_id(cmd, arg, private_data);
break;
case SYS_GET_UART_NUM:
case SYS_SWITCH_UART:
ret = drv_sys_ioctl_get_uart_info(cmd, arg, private_data);
break;
case SYS_GET_TIME_STAMP_MS:
case SYS_GET_DDR_CFG:
case SYS_GET_CAPABILITY:
ret = drv_sys_ioctl_get_other_data(cmd, arg, private_data);
break;
case SYS_GET_DOLBY_SUPPORT:
ret = ext_drv_sys_get_dolby_support((td_u32 *)arg);
break;
case SYS_GET_KS_SUPPORT:
ret = ext_drv_sys_get_ks_support((td_u32 *)arg);
break;
case SYS_GET_DTS_SUPPORT:
ret = ext_drv_sys_get_dts_support((td_u32 *)arg);
break;
default:
soc_log_err("drv sys ioctl part1: unknown command 0x%x\n", cmd);
}
return ret;
}
static td_s32 drv_sys_ioctl_part2(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_ADVCA_SUPPORT:
ret = ext_drv_sys_get_advca_support((td_u32 *)arg);
break;
case SYS_GET_MACRO_VISION_SUPPORT:
ret = ext_drv_sys_get_rovi_support((td_u32 *)arg);
break;
case SYS_GET_HDR10_SUPPORT:
ret = ext_drv_sys_get_hdr10_support((td_u32 *)arg);
break;
case SYS_GET_DOLBY_VISION_SUPPORT:
ret = ext_drv_sys_get_dolby_vision_support((td_u32 *)arg);
break;
case SYS_DISABLE_VIDEO_CODEC:
if (arg != TD_NULL) {
ret = ext_drv_sys_disable_video_codec(*((ext_sys_video_codec *)arg));
}
break;
case SYS_GET_BUILD_VARIANT:
ret = drv_sys_ioctl_get_build_variant((td_s32 *)arg);
break;
case SYS_GET_DOLBY_DDPLUSE_SUPPORT:
ret = ext_drv_sys_get_dolby_ddpluse_support((td_u32 *)arg);
break;
default:
soc_log_err("drv sys ioctl part2: unknown command 0x%x\n", cmd);
}
return ret;
}
td_s32 drv_sys_ioctl(td_u32 cmd, td_void *arg, td_void *private_data)
{
td_s32 ret = -ENOIOCTLCMD;
switch (cmd) {
case SYS_GET_VERSION:
case SYS_GET_BOARDID_CFG:
case SYS_GET_CHIP_PACKAGE_TYPE:
case SYS_GET_SMP_SUPPORT:
case SYS_GET_DIE_ID_64:
case SYS_GET_DIE_ID_32:
case SYS_GET_UART_NUM:
case SYS_SWITCH_UART:
case SYS_GET_TIME_STAMP_MS:
case SYS_GET_DDR_CFG:
case SYS_GET_CAPABILITY:
case SYS_GET_DOLBY_SUPPORT:
case SYS_GET_KS_SUPPORT:
case SYS_GET_DTS_SUPPORT:
ret = drv_sys_ioctl_part1(cmd, arg, private_data); // cmd is belong to part1
break;
case SYS_GET_ADVCA_SUPPORT:
case SYS_GET_MACRO_VISION_SUPPORT:
case SYS_GET_HDR10_SUPPORT:
case SYS_GET_DOLBY_VISION_SUPPORT:
case SYS_DISABLE_VIDEO_CODEC:
case SYS_GET_BUILD_VARIANT:
case SYS_GET_DOLBY_DDPLUSE_SUPPORT:
ret = drv_sys_ioctl_part2(cmd, arg, private_data); // cmd is belong to part2
break;
default:
soc_log_err("unknown command 0x%x\n", cmd);
}
return ret;
}
static td_void drv_sys_get_chip_name(ext_chip_name_id chip_name_id, td_char **chip_name)
{
if (chip_name == TD_NULL) {
soc_log_err("Invalid parament pChipName[%#x]!\n", chip_name);
return;
}
switch (chip_name_id) {
case CHIP_NAME_RESERVED13: {
*chip_name = "reserved13";
break;
}
case CHIP_NAME_RESERVED6: {
*chip_name = "reserved6";
break;
}
case CHIP_NAME_RESERVED9: {
*chip_name = "reserved9";
break;
}
case CHIP_NAME_RESERVED5: {
*chip_name = "reserved5";
break;
}
case CHIP_NAME_RESERVED2: {
*chip_name = "reserved2";
break;
}
case CHIP_NAME_RESERVED17: {
*chip_name = "reserved17";
break;
}
case CHIP_NAME_RESERVED19: {
*chip_name = "reserved19";
break;
}
case CHIP_NAME_HI3751V811: {
*chip_name = "hi3751v811";
break;
}
case CHIP_NAME_RESERVED8: {
*chip_name = "reserved8";
break;
}
default:
*chip_name = "UNKNOWN";
}
return;
}
static td_void drv_sys_get_chip_package_type(ext_chip_package_type package_type, td_char **package_name)
{
if (package_name == TD_NULL) {
soc_log_err("Invalid parament pPackageName[%#x]!\n", package_name);
return;
}
switch (package_type) {
case CHIP_PACKAGE_TYPE_BGA_14_14:
*package_name = "BGA 14*14";
break;
case CHIP_PACKAGE_TYPE_BGA_15_15:
*package_name = "BGA 15*15";
break;
case CHIP_PACKAGE_TYPE_BGA_16_16:
*package_name = "BGA 16*16";
break;
case CHIP_PACKAGE_TYPE_BGA_19_19:
*package_name = "BGA 19*19";
break;
case CHIP_PACKAGE_TYPE_BGA_21_21:
*package_name = "BGA 21*21";
break;
case CHIP_PACKAGE_TYPE_BGA_23_23:
*package_name = "BGA 23*23";
break;
case CHIP_PACKAGE_TYPE_BGA_31_31:
*package_name = "BGA 31*31";
break;
case CHIP_PACKAGE_TYPE_BGA_35_35:
*package_name = "BGA 35*35";
break;
case CHIP_PACKAGE_TYPE_BGA_19_22:
*package_name = "BGA 19*22";
break;
case CHIP_PACKAGE_TYPE_QFP_216:
*package_name = "QFP 216";
break;
case CHIP_PACKAGE_TYPE_BGA_27_27:
*package_name = "BGA 27*27";
break;
default:
*package_name = "UNKNOWN";
}
return;
}
static td_void drv_sys_chip_info(td_void *s)
{
td_char *chip_name = TD_NULL;
td_char *package_name = TD_NULL;
ext_chip_name_id chip_name_id = 0;
ext_chip_package_type package_type;
if (s == TD_NULL) {
return;
}
ext_drv_sys_get_chip_name_id(&chip_name_id);
drv_sys_get_chip_name(chip_name_id, &chip_name);
osal_seq_printf(s, "chip_name_id :%-19s|\n", chip_name);
package_type = ext_drv_sys_get_chip_package_type();
if (package_type == CHIP_PACKAGE_TYPE_BUTT) {
soc_log_warn("invalid package type.\n");
}
drv_sys_get_chip_package_type(package_type, &package_name);
osal_seq_printf(s, "package_type :%-19s|\n", package_name);
}
static td_void drv_sys_chip_feature(td_void *s)
{
td_u32 dolby_support;
td_u32 dolby_ddpulse_support;
td_u32 hdr10_support;
td_u32 dolby_vision_support;
td_u32 dts_support;
td_u32 rovi_support;
td_u32 advca_support;
#if defined(CONFIG_SOCT_TEE_SUPPORT) && defined(CONFIG_SOCT_ADVCA_TYPE)
td_u8 version[96]; /* array num is 96 */
#endif
if (s == TD_NULL) {
return;
}
/* 30 character before ":" and 3 space append */
if (ext_drv_sys_get_dolby_support(&dolby_support) == TD_SUCCESS) {
osal_seq_printf(s, "dolby_digital :%-19s|\n", (dolby_support) ? "yes" : "no");
}
if (ext_drv_sys_get_dolby_ddpluse_support(&dolby_ddpulse_support) == TD_SUCCESS) {
osal_seq_printf(s, "dolby_digital_plus :%-19s|\n", (dolby_ddpulse_support) ? "yes" : "no");
}
if (ext_drv_sys_get_dts_support(&dts_support) == TD_SUCCESS) {
osal_seq_printf(s, "dts :%-19s|\n", (dts_support) ? "yes" : "no");
}
if (ext_drv_sys_get_advca_support(&advca_support) == TD_SUCCESS) {
osal_seq_printf(s, "advca :%-19s|\n", (advca_support) ? "yes" : "no");
}
if (ext_drv_sys_get_rovi_support(&rovi_support) == TD_SUCCESS) {
osal_seq_printf(s, "rovi(macrovision) :%-19s|\n", (rovi_support) ? "yes" : "no");
}
if (ext_drv_sys_get_hdr10_support(&hdr10_support) == TD_SUCCESS) {
osal_seq_printf(s, "hdr10 :%-19s|\n", (hdr10_support) ? "yes" : "no");
}
if (ext_drv_sys_get_dolby_vision_support(&dolby_vision_support) == TD_SUCCESS) {
osal_seq_printf(s, "dolbyvision :%-19s|\n", (dolby_vision_support) ? "yes" : "no");
}
#if defined(COMFIG_SOCT_TEE_SUPPORT) && defined(CONFIG_SOCT_ADVCA_TYPE)
if (ext_drv_sys_get_sos_version(version, sizeof(version)) == TD_SUCCESS) {
osal_seq_printf(s, "secure_OS_version :%-19s|\n", version);
}
#endif
}
static td_void drv_sys_chip_core_info(td_void *s)
{
td_u32 license_value = 0;
if (s == TD_NULL) {
return;
}
if (osal_get_license_support(OSAL_LICENSE_CPU_CAP, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "cpu :%-19s|\n", (license_value == 0) ? "4_CORE" :
((license_value == 1) ? "8_CORE" : "NOT_SUPPORT"));
}
if (osal_get_license_support(OSAL_LICENSE_GPU_CAP, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "gpu :%-19s|\n", (license_value == 0) ? "2_CORE" :
((license_value == 1) ? "6_CORE" : "NOT_SUPPORT"));
}
if (osal_get_license_support(OSAL_LICENSE_NPU_CAP, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "npu :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
}
static td_void drv_sys_chip_code_cap(td_void *s)
{
td_u32 license_value = 0;
if (s == TD_NULL) {
return;
}
if (osal_get_license_support(OSAL_LICENSE_DECODE_CAP, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "decode :%-19s|\n",
(license_value == 0) ? "4KP60" :
((license_value == 1) ? "4KP120" :
((license_value == 0x2) ? "8KP60" :
((license_value == 0x3) ? "8KP120" : "NOT_SUPPORT"))));
}
if (osal_get_license_support(OSAL_LICENSE_DECODE_FORMAT, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "decode_avs3 :%-19s|\n", (license_value & 0x01) ? "ENABLE" : "DISABLE");
osal_seq_printf(s, "decode_av1 :%-19s|\n", (license_value & 0x02) ? "ENABLE" : "DISABLE");
}
if (osal_get_license_support(OSAL_LICENSE_ADSP_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "asr :%-19s|\n", (license_value & 0x01) ? "ENABLE" : "DISABLE");
osal_seq_printf(s, "adsp :%-19s|\n", (license_value & 0x02) ? "ENABLE" : "DISABLE");
}
if (osal_get_license_support(OSAL_LICENSE_ENCODE_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "encode :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
}
static td_void drv_sys_proc_show_tsi(td_void *s)
{
td_u32 license_value = 0;
if (osal_get_license_support(OSAL_LICENSE_TSI_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "tsi :%-19s|\n",
(license_value == 0) ? "DISABLE" :
((license_value == 1) ? "4_PORT" :
((license_value == 0x2) ? "8_PORT" :
((license_value == 0x3) ? "16_PORT" : "NOT_SUPPORT"))));
}
}
/* for product auto test room, sn is wirting into one file */
static td_char g_sys_path_file[PROC_CMD_ALL_LENGTH_MAX];
#define SYS_SN_MAX_LEN 32
static td_s32 drv_sys_write_sn(td_u32 argc, td_char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private)
{
errno_t err_ret;
td_char *sn = TD_NULL;
td_char *path = TD_NULL;
void *file = TD_NULL;
td_u32 sn_len = 0;
if (argc != 3) { /* 3: argc number */
soc_log_err("argc cmmand is err.\n");
return TD_FAILURE;
}
/* save sn file path */
path = argv[1];
if (strlen(argv[1]) >= sizeof(g_sys_path_file)) {
soc_log_err("input path %s legth is over than %d\n", argv[1], PROC_CMD_ALL_LENGTH_MAX);
return TD_FAILURE;
}
err_ret = memcpy_s(g_sys_path_file, PROC_CMD_ALL_LENGTH_MAX, argv[1], strlen(argv[1]) + 1);
if (err_ret != EOK) {
return TD_FAILURE;
}
osal_printk("sys path & file %s\n", g_sys_path_file);
/* argv 2: sn number string format */
sn = argv[2];
sn_len = strlen(sn);
file = osal_klib_fopen(g_sys_path_file, OSAL_O_RDWR | OSAL_O_CREAT | OSAL_O_TRUNC, 0644); /* 0644 is authority */
if (file == TD_NULL) {
soc_log_err("osal_klib_fopen %s failure...................\n", g_sys_path_file);
return TD_FAILURE;
}
osal_klib_fwrite(sn, sn_len, file);
osal_klib_fclose(file);
return TD_SUCCESS;
}
static td_s32 drv_sys_read_sn(td_u32 argc, td_char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], td_void *private)
{
void *file = TD_NULL;
td_char sn[SYS_SN_MAX_LEN] = {0};
if (strlen(g_sys_path_file) < 1) {
osal_printk("no sys file !!!\n");
return TD_SUCCESS;
}
file = osal_klib_fopen(g_sys_path_file, OSAL_O_RDONLY, 0644); /* 0644: mode */
if (file == TD_NULL) {
soc_log_err("osal_klib_fopen %s failure...................\n", g_sys_path_file);
return TD_FAILURE;
}
osal_klib_fread(sn, sizeof(sn), file);
osal_klib_fclose(file);
osal_printk("SN:%s\n", sn);
return TD_SUCCESS;
}
static td_s32 drv_sys_proc_sn(td_void *s, td_void *arg)
{
void *file = TD_NULL;
td_char sn[SYS_SN_MAX_LEN] = {0};
if (strlen(g_sys_path_file) < 1) {
return TD_SUCCESS;
}
file = osal_klib_fopen(g_sys_path_file, OSAL_O_RDONLY, 0644); /* 0644: mode */
if (file == TD_NULL) {
soc_log_err("osal_klib_fopen %s failure...................\n", g_sys_path_file);
return TD_FAILURE;
}
osal_klib_fread(sn, sizeof(sn), file);
osal_klib_fclose(file);
osal_seq_printf(s, "SN :%-19s|\n", sn);
return TD_SUCCESS;
}
static osal_proc_cmd g_proc_cmd[] = {
{"write_sn", drv_sys_write_sn},
{"read_sn", drv_sys_read_sn}
};
static td_s32 drv_sys_proc_show(td_void *s, td_void *arg)
{
td_u32 license_value = 0;
osal_seq_printf(s, "\n[sys] %s\n", VERSION_STRING);
osal_seq_printf(s, "---------------FEATURE LICENSE-----------\n");
drv_sys_chip_info(s);
drv_sys_chip_feature(s);
drv_sys_chip_core_info(s);
drv_sys_chip_code_cap(s);
if (osal_get_license_support(OSAL_LICENSE_DISPLAY2_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "display2 :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
if (osal_get_license_support(OSAL_LICENSE_HDMI_RX_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "hdmi_rx :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
drv_sys_proc_show_tsi(s);
if (osal_get_license_support(OSAL_LICENSE_PCIE_EN, &license_value) == TD_SUCCESS) {
osal_proc_print(s, "pcie :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
if (osal_get_license_support(OSAL_LICENSE_SATA_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "sata :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
if (osal_get_license_support(OSAL_LICENSE_USB3_EN, &license_value) == TD_SUCCESS) {
osal_seq_printf(s, "usb3.0 :%-19s|\n", (license_value == 1) ? "ENABLE" : "DISABLE");
}
(void)drv_sys_proc_sn(s, arg);
osal_seq_printf(s, "=========================================\n");
return TD_SUCCESS;
}
td_s32 drv_sys_add_proc(td_void)
{
osal_proc_entry *fn_set = TD_NULL;
fn_set = osal_proc_add(SOC_MOD_SYS_NAME, strlen(SOC_MOD_SYS_NAME));
if (fn_set == TD_NULL) {
soc_log_err("add proc failed!\n");
return TD_FAILURE;
}
fn_set->read = drv_sys_proc_show;
fn_set->cmd_cnt = sizeof(g_proc_cmd) / sizeof(osal_proc_cmd);
fn_set->cmd_list = g_proc_cmd;
return TD_SUCCESS;
}
td_void drv_sys_remove_proc(td_void)
{
osal_proc_remove(SOC_MOD_SYS_NAME, strlen(SOC_MOD_SYS_NAME));
}
/* return true is support else return false */
td_bool ext_drv_sys_get_capability(ext_sys_capability_type cap_type)
{
static td_u32 capability = 0;
static td_bool flag = 0;
if (flag == 0) {
#ifdef CONFIG_SOCT_TEE_SUPPORT
capability = (1 << EXT_SYS_CAP_TYPE_TEE_SUPPORT);
#endif
capability |= ((td_u32)osal_dts_get_bool_byname("huanglong,common", "smmu_support")
<< EXT_SYS_CAP_TYPE_SMMU_SUPPORT);
}
flag = 1;
return ((capability & (1 << (td_u32)cap_type)) ? TD_TRUE : TD_FALSE);
}
td_void ext_drv_sys_get_uart_number(td_u32 *uart_num)
{
td_s32 ret;
if (uart_num == TD_NULL) {
soc_log_err("uart_num is null\n");
return;
}
ret = hal_sys_get_uart_number(uart_num);
if (ret != TD_SUCCESS) {
soc_log_err("hal get uart num failed!\n");
}
return;
}
td_s32 ext_drv_sys_switch_uart(const td_u32 tty)
{
td_s32 ret;
ret = hal_sys_switch_uart(tty);
if (ret != TD_SUCCESS) {
soc_log_err("hal switch uart failed!\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
EXPORT_SYMBOL(ext_drv_sys_get_chip_name_id);
EXPORT_SYMBOL(ext_drv_sys_get_chip_revision);
EXPORT_SYMBOL(ext_drv_sys_get_chip_package_type);
EXPORT_SYMBOL(ext_drv_sys_get_time_stamp_ms);
EXPORT_SYMBOL(ext_drv_sys_get_dolby_support);
EXPORT_SYMBOL(ext_drv_sys_get_dolby_ddpluse_support);
EXPORT_SYMBOL(ext_drv_sys_get_hdr10_support);
EXPORT_SYMBOL(ext_drv_sys_get_dolby_vision_support);
EXPORT_SYMBOL(ext_drv_sys_get_dts_support);
EXPORT_SYMBOL(ext_drv_sys_get_advca_support);
EXPORT_SYMBOL(ext_drv_sys_get_rovi_support);
EXPORT_SYMBOL(ext_drv_sys_get_mem_cfg);
EXPORT_SYMBOL(ext_drv_sys_get_die_id_64bit);
EXPORT_SYMBOL(ext_drv_sys_get_die_id);
EXPORT_SYMBOL(ext_drv_sys_get_board_id);
EXPORT_SYMBOL(ext_drv_sys_set_irq_affinity);
EXPORT_SYMBOL(ext_drv_sys_get_tee_mode);
EXPORT_SYMBOL(ext_drv_sys_get_package_id);
EXPORT_SYMBOL(ext_drv_sys_get_chip_secure_mode);
EXPORT_SYMBOL(ext_drv_sys_get_flag);
EXPORT_SYMBOL(ext_drv_sys_get_audio_op_mode);
EXPORT_SYMBOL(ext_drv_sys_get_disp_vdac_drive_mode);
EXPORT_SYMBOL(ext_drv_sys_disable_video_codec);
EXPORT_SYMBOL(ext_drv_sys_get_video_codec_support);
EXPORT_SYMBOL(ext_drv_sys_get_ks_support);
EXPORT_SYMBOL(ext_drv_sys_check_phy_addr);
EXPORT_SYMBOL(ext_drv_user_copy);
EXPORT_SYMBOL(ext_drv_sys_get_ctrl_reg_ptr);
EXPORT_SYMBOL(ext_drv_sys_get_peri_reg_ptr);
EXPORT_SYMBOL(ext_drv_sys_get_io_reg_ptr);
EXPORT_SYMBOL(ext_drv_sys_get_crg_reg_ptr);
EXPORT_SYMBOL(ext_drv_sys_get_aon_crg_reg_ptr);
EXPORT_SYMBOL(ext_drv_sys_get_capability);