/* * 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 #include #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);