1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2025-10-07 10:09:34 +00:00
Files
physwizz 99537be4e2 first
2024-03-11 06:53:12 +11:00

157 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 MediaTek Inc.
*/
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include "user.h"
#ifndef TEEPERF_DEVICE_PROPNAME
#define TEEPERF_DEVICE_PROPNAME "mediatek,teeperf"
#endif
u32 cpu_type;
u32 cpu_map;
static struct {
dev_t device;
struct class *class;
dev_t user_dev;
struct cdev user_cdev;
} main_ctx;
static inline int teeperf_device_common_init(void)
{
int ret;
ret = alloc_chrdev_region(&main_ctx.device, 0, 1, "teeperf");
if (ret) {
pr_info(PFX "alloc_chrdev_region failed, ret %d\n", ret);
return ret;
}
main_ctx.class = class_create(THIS_MODULE, "teeperf");
if (IS_ERR(main_ctx.class)) {
ret = PTR_ERR(main_ctx.class);
pr_info(PFX "class_create failed, ret %d\n", ret);
unregister_chrdev_region(main_ctx.device, 1);
return ret;
}
return 0;
}
static inline void teeperf_device_common_exit(void)
{
class_destroy(main_ctx.class);
unregister_chrdev_region(main_ctx.device, 1);
}
static inline int teeperf_device_user_init(void)
{
struct device *dev;
int ret = 0;
main_ctx.user_dev = MKDEV(MAJOR(main_ctx.device), 1);
/* Create the user node */
teeperf_user_init(&main_ctx.user_cdev);
ret = cdev_add(&main_ctx.user_cdev, main_ctx.user_dev, 1);
if (ret) {
pr_info(PFX "user cdev_add failed, ret %d\n", ret);
return ret;
}
main_ctx.user_cdev.owner = THIS_MODULE;
dev = device_create(main_ctx.class, NULL, main_ctx.user_dev, NULL,
TEEPERF_DEVNODE);
if (IS_ERR(dev)) {
ret = PTR_ERR(dev);
cdev_del(&main_ctx.user_cdev);
pr_info(PFX "user device_create failed, ret %d\n", ret);
return ret;
}
return 0;
}
static inline void teeperf_device_user_exit(void)
{
device_destroy(main_ctx.class, main_ctx.user_dev);
cdev_del(&main_ctx.user_cdev);
}
static int teeperf_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
int ret = 0;
if (IS_ERR(node)) {
pr_info(PFX "cannot find device node\n");
return -ENODEV;
}
ret = of_property_read_u32(node, "cpu-type", &cpu_type);
if (ret || !cpu_type) {
pr_info(PFX "invalid cpu type\n");
return -EINVAL;
}
ret = of_property_read_u32(node, "cpu-map", &cpu_map);
if (ret || !cpu_map) {
pr_info(PFX "invalid cpu map\n");
return -EINVAL;
}
ret = teeperf_device_common_init();
if (ret)
goto err_common;
ret = teeperf_device_user_init();
if (ret)
goto err_user;
return 0;
err_user:
teeperf_device_common_exit();
err_common:
return ret;
}
static const struct of_device_id of_match_table[] = {
{ .compatible = TEEPERF_DEVICE_PROPNAME },
{ }
};
static struct platform_driver teeperf_plat_driver = {
.probe = teeperf_probe,
.driver = {
.name = "teeperf",
.owner = THIS_MODULE,
.of_match_table = of_match_table,
}
};
static int __init teeperf_init(void)
{
return platform_driver_register(&teeperf_plat_driver);
}
static void __exit teeperf_exit(void)
{
teeperf_device_user_exit();
teeperf_device_common_exit();
platform_driver_unregister(&teeperf_plat_driver);
}
module_init(teeperf_init);
module_exit(teeperf_exit);
MODULE_AUTHOR("Jackson Chang <jackson-kt.chang@mediatek.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("TEE perf driver");