kernel-brax3-ubuntu-touch/drivers/misc/mediatek/et/mtk_et.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

347 lines
6.6 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2022 MediaTek Inc.
*/
/**
* @file mkt_et.c
* @brief Driver for et
*
*/
#define __MTK_ET_C__
/*
*=============================================================
* Include files
*=============================================================
*/
/* system includes */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/kthread.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/interrupt.h>
#include <linux/syscore_ops.h>
#include <linux/platform_device.h>
#include <linux/completion.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
#include <linux/arm-smccc.h>
#include <linux/io.h>
#ifdef __KERNEL__
#include <linux/topology.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>
#include "mtk_et.h"
#endif
#if IS_ENABLED(CONFIG_OF)
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#endif
/************************************************
* Debug print
************************************************/
//#define ET_DEBUG
#define ET_TAG "[ET]"
#define et_err(fmt, args...) \
pr_info(ET_TAG"[ERROR][%s():%d]" fmt, __func__, __LINE__, ##args)
#define et_msg(fmt, args...) \
pr_info(ET_TAG"[INFO][%s():%d]" fmt, __func__, __LINE__, ##args)
#ifdef ET_DEBUG
#define et_debug(fmt, args...) \
pr_debug(ET_TAG"[DEBUG][%s():%d]" fmt, __func__, __LINE__, ##args)
#else
#define et_debug(fmt, args...)
#endif
/************************************************
* SMC between kernel and atf
************************************************/
unsigned int et_smc_handle(
unsigned int feature, unsigned int x2, unsigned int x3, unsigned int x4)
{
unsigned int ret = 0;
#if defined(_MTK_SECURE_API_H_)
/* update atf via smc */
ret = mt_secure_call(MTK_SIP_KERNEL_PTP3_CONTROL,
feature,
x2,
x3,
x4);
#elif defined(__LINUX_ARM_SMCCC_H)
/* update TFA via smc call */
struct arm_smccc_res res;
arm_smccc_smc(MTK_SIP_KERNEL_PTP3_CONTROL,
feature,
x2,
x3,
x4,
0, 0, 0, &res);
if (res.a0 == -1)
ret = -1;
else
ret = (unsigned int)res.a0;
#else
ret = 0;
#endif
return ret;
}
/************************************************
* static function
************************************************/
/* ET_EN procfs interface */
static ssize_t et_en_proc_write(struct file *file,
const char __user *buffer, size_t count, loff_t *pos)
{
int enable = 0;
char *buf = (char *) __get_free_page(GFP_USER);
if (!buf)
return -ENOMEM;
if (count >= PAGE_SIZE)
goto out;
if (copy_from_user(buf, buffer, count))
goto out;
buf[count] = '\0';
if (kstrtoint(buf, 10, &enable)) {
et_debug("bad argument!!\n");
goto out;
}
enable = enable ? 1 : 0;
et_smc_handle(PTP3_FEATURE_ET, ET_W_EN, enable, 0);
out:
free_page((unsigned long)buf);
return count;
}
static int et_en_proc_show(struct seq_file *m, void *v)
{
int status = 0;
status = et_smc_handle(PTP3_FEATURE_ET, ET_R_EN, 0, 0);
seq_printf(m, "ET_ENABLE = 0x%x\n", status);
return 0;
}
/* ET_CFG procfs interface */
static ssize_t et_cfg_proc_write(struct file *file,
const char __user *buffer, size_t count, loff_t *pos)
{
int index = 0, value = 0;
char *buf = (char *) __get_free_page(GFP_USER);
if (!buf)
return -ENOMEM;
if (count >= PAGE_SIZE)
goto out;
if (copy_from_user(buf, buffer, count))
goto out;
buf[count] = '\0';
if (sscanf(buf, "%u %u", &index, &value) != 2) {
et_debug("bad argument!! Should input 2 arguments.\n");
goto out;
}
if ((index < 0) || (index >= ET_INDEX_NUM)) {
et_debug("index out of range!!\n");
goto out;
}
et_smc_handle(PTP3_FEATURE_ET, ET_W_CFG, index, value);
out:
free_page((unsigned long)buf);
return count;
}
static int et_cfg_proc_show(struct seq_file *m, void *v)
{
int status = 0;
unsigned int index = 0;
for (index = 0; index <= ET_INDEX_NUM; index++) {
status = et_smc_handle(PTP3_FEATURE_ET, ET_R_CFG, index, 0);
seq_printf(m, "ET_index_%d = 0x%x\n", index, status);
}
return 0;
}
static int et_state_proc_show(struct seq_file *m, void *v)
{
int status = 0;
unsigned int index = 0;
for (index = 0; index < ET_NUM; index++) {
status = et_smc_handle(PTP3_FEATURE_ET, ET_R_STATE, index, 0);
seq_printf(m, "ET_state_%d = 0x%x\n", index, status);
}
return 0;
}
/************************************************
* Kernel driver nodes
************************************************/
PROC_FOPS_RW(et_en);
PROC_FOPS_RW(et_cfg);
PROC_FOPS_RO(et_state);
static int create_procfs(void)
{
int i;
const char *proc_name = "et";
struct proc_dir_entry *dir = NULL;
struct pentry {
const char *name;
const struct proc_ops *fops;
};
struct pentry et_entries[] = {
PROC_ENTRY(et_en),
PROC_ENTRY(et_cfg),
PROC_ENTRY(et_state),
};
/* create proc dir */
dir = proc_mkdir(proc_name, NULL);
if (!dir) {
et_err(
"[%s]: mkdir /proc/%s failed\n", __func__, proc_name);
return -1;
}
for (i = 0; i < ARRAY_SIZE(et_entries); i++) {
if (!proc_create(et_entries[i].name,
0664,
dir,
et_entries[i].fops)) {
et_debug("[%s]: create /proc/%s/iglre/%s failed\n",
__func__,
proc_name,
et_entries[i].name);
return -3;
}
}
return 0;
}
static int et_probe(struct platform_device *pdev)
{
struct device_node *node = NULL;
node = pdev->dev.of_node;
if (!node) {
et_debug("get et device node err\n");
return -ENODEV;
}
return 0;
}
static int et_suspend(struct platform_device *pdev, pm_message_t state)
{
return 0;
}
static int et_resume(struct platform_device *pdev)
{
return 0;
}
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id et_of_match[] = {
{ .compatible = "mediatek,et", },
{},
};
#endif
static struct platform_driver et_driver = {
.remove = NULL,
.shutdown = NULL,
.probe = et_probe,
.suspend = et_suspend,
.resume = et_resume,
.driver = {
.name = "et",
#if IS_ENABLED(CONFIG_OF)
.of_match_table = et_of_match,
#endif
},
};
static int __init __et_init(void)
{
int err = 0;
create_procfs();
err = platform_driver_register(&et_driver);
if (err) {
et_err("et driver callback register failed..\n");
return err;
}
return 0;
}
static void __exit __et_exit(void)
{
et_msg("et de-initialization\n");
}
late_initcall(__et_init);
module_exit(__et_exit);
MODULE_DESCRIPTION("MediaTek et Driver v0.1");
MODULE_LICENSE("GPL");
#undef __MTK_ET_C__