kernel-brax3-ubuntu-touch/drivers/misc/mediatek/nfc_tms/tms_common.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
9.8 KiB
C
Executable file

/*****************************************************************************************
* Copyright (c) 2021- 2022 TsingTeng MicroSystem Corp.Ltd.
* TMS_EDIT
* File : tms_common.c
* Description: Source file for tms device common
* Version : 1.0
* Date : 2022/4/11
* Team : NFC Middleware
* Author : Guoliang Wu
* --------------------------------- Revision History: ---------------------------------
* <version> <date> < author > <desc>
*******************************************************************************************/
#include "tms_common.h"
/*********** PART0: Global Variables Area ***********/
struct tms_info *tms = NULL;
unsigned int tms_debug = LEVEL_DEBUG;
EXPORT_SYMBOL(tms_debug);
/*********** PART1: Declare Area ***********/
/*********** PART2: Function Area ***********/
void tms_buffer_dump(const char *tag, const uint8_t *src, int16_t len)
{
uint16_t buf_len = (len > PAGESIZE) ? PAGESIZE : len;
uint16_t index = 0;
uint16_t i;
if (tms_debug != LEVEL_DUMP) {
TMS_DEBUG("%s[%d] bytes", tag, len);
} else {
char buf[PAGESIZE * 2 + 1];
do {
memset(buf, 0, sizeof(buf));
for (i = 0; i < buf_len; i++) {
snprintf(&buf[i * 2], 3, "%02X", src[index++]);
}
TMS_ERR("%s[%d] %s", tag, buf_len, buf);
len = len - buf_len;
buf_len = (len > PAGESIZE) ? PAGESIZE : len;
} while (len > 0);
}
}
EXPORT_SYMBOL(tms_buffer_dump);
struct tms_info *tms_common_data_binding(void)
{
return tms;
}
EXPORT_SYMBOL(tms_common_data_binding);
void ven_gpio_set(struct hw_resource hw_res, bool state)
{
if (gpio_get_value(hw_res.ven_gpio) != state) {
TMS_DEBUG("Ven gpio %d state = %d\n", hw_res.ven_gpio, state);
gpio_set_value(hw_res.ven_gpio, state);
} else {
TMS_ERR("VEN gpio value is %d already\n", gpio_get_value(hw_res.ven_gpio));
}
}
void download_gpio_set(struct hw_resource hw_res, bool state)
{
if (gpio_is_valid(hw_res.download_gpio)) {
TMS_DEBUG("FW download gpio %d state = %d\n", hw_res.download_gpio,
state);
gpio_set_value(hw_res.download_gpio, state);
/* hardware dependent delay */
usleep_range(GPIO_SET_WAIT_TIME_US, GPIO_SET_WAIT_TIME_US + 100);
} else {
TMS_ERR("FW DOWNLOAD gpio value is %d already\n", gpio_get_value(hw_res.download_gpio));
}
}
void reset_gpio_set(struct hw_resource hw_res, bool state)
{
if (gpio_is_valid(hw_res.rst_gpio)) {
TMS_DEBUG("Reset gpio %d state = %d\n", hw_res.rst_gpio, state);
gpio_set_value(hw_res.rst_gpio, state);
/* hardware dependent delay */
usleep_range(GPIO_SET_WAIT_TIME_US, GPIO_SET_WAIT_TIME_US + 100);
} else {
TMS_ERR("RESET gpio value is %d already\n", gpio_get_value(hw_res.rst_gpio));
}
}
/* drv add for tms nfc ata test 20230802-start */
#define TMS_STATUS
#ifdef TMS_STATUS
static int tms_nfc_driver_status = 0;
static ssize_t tms_chip_status_show(struct device* dev,
struct device_attribute* attr, char* buf)
{
int len = 0;
len += sprintf((char*)buf, "%d\n", tms_nfc_driver_status);
return len;
}
static DEVICE_ATTR(nfc_chip_status, S_IRUGO | S_IWUSR, tms_chip_status_show, NULL);
static struct attribute *nfc_sysfs_entries[] = {
&dev_attr_nfc_chip_status.attr,
NULL
};
static struct attribute_group nfc_attribute_group = {
.attrs = nfc_sysfs_entries,
};
#endif
/* drv add for tms nfc ata test 20230802-end */
void tms_device_unregister(struct dev_register *dev)
{
device_destroy(tms->class, dev->devno);
cdev_del(&dev->chrdev);
unregister_chrdev_region(dev->devno, dev->count);
TMS_INFO("Unregister device\n");
}
int tms_device_register(struct dev_register *dev, void *data)
{
int ret;
TMS_INFO("start+\n");
dev->class = tms->class;
ret = alloc_chrdev_region(&dev->devno, 0, dev->count, dev->name);
if (ret < 0) {
TMS_ERR("Alloc chrdev region failed, ret %d\n", ret);
return ret;
}
cdev_init(&dev->chrdev, dev->fops);
ret = cdev_add(&dev->chrdev, dev->devno, dev->count);
if (ret < 0) {
TMS_ERR("Add char device failed, ret %d\n", ret);
goto err_free_devno;
}
dev->creation = device_create(tms->class, NULL, dev->devno, data, dev->name);
if (IS_ERR(dev->creation)) {
ret = PTR_ERR(dev->creation);
TMS_ERR("Create the device failed, ret %d\n", ret);
goto err_delete_cdev;
}
/* drv add for tms nfc ata test 20230802-start */
#ifdef TMS_STATUS
ret = sysfs_create_group(&dev->creation->kobj, &nfc_attribute_group);
if (ret == 0)
{
TMS_INFO("TMS_STATUS node create success!");
tms_nfc_driver_status = 1;
}
else
TMS_INFO("TMS_STATUS node create fail!");
#endif
/* drv add for tms nfc ata test 20230802-end */
TMS_INFO("Normal end+\n");
return SUCCESS;
err_delete_cdev:
cdev_del(&dev->chrdev);
err_free_devno:
unregister_chrdev_region(dev->devno, dev->count);
TMS_ERR("Error[%d] end-\n", ret);
return ret;
}
static ssize_t proc_debug_control_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
uint8_t ret;
char page[PAGESIZE] = {0};
TMS_DEBUG("Read debug_level is %d\n", tms_debug);
snprintf(page, PAGESIZE - 1, "%u\n", tms_debug);
ret = simple_read_from_buffer(buf, count, ppos, page, strlen(page));
return ret;
}
static ssize_t proc_debug_control_write(struct file *file,
const char __user *buf, size_t count, loff_t *lo)
{
int tmp = 0;
char buffer[4] = {0};
if (count > 2) {
TMS_ERR("Input format error.\n");
return count;
}
if (copy_from_user(buffer, buf, count)) {
TMS_ERR("Get debug level error.\n");
return count;
}
if (sscanf(buffer, "%d", &tmp) == 1) {
tms_debug = tmp;
TMS_DEBUG("Set debug level is %d\n", tms_debug);
} else {
TMS_ERR("Invalid content:'%s', length = %zd\n", buf, count);
}
return count;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static const struct proc_ops proc_debug_control_ops = {
.proc_write = proc_debug_control_write,
.proc_read = proc_debug_control_read,
.proc_open = simple_open,
};
#else
static const struct file_operations proc_debug_control_ops = {
.write = proc_debug_control_write,
.read = proc_debug_control_read,
.open = simple_open,
.owner = THIS_MODULE,
};
#endif
/*********** PART3: TMS Common Start Area ***********/
static int tms_proc_init(void)
{
int ret;
struct proc_dir_entry *prEntry_tmp = NULL;
TMS_INFO("Start+\n");
tms->prEntry = proc_mkdir("tmsdev", NULL);
if (tms->prEntry == NULL) {
TMS_ERR("Couldn't create tmsdev proc entry\n");
return -EFAULT;
}
prEntry_tmp = proc_create_data("debug_level", 0644, tms->prEntry,
&proc_debug_control_ops, NULL);
if (prEntry_tmp == NULL) {
ret = -EFAULT;
TMS_ERR("Couldn't create debug_level proc entry\n");
goto err_remove_proc;
}
TMS_INFO("Normal end-\n");
return SUCCESS;
err_remove_proc:
proc_remove(tms->prEntry);
TMS_ERR("Error[%d] end-\n", ret);
return ret;
}
static int tms_common_probe(void)
{
int ret;
TMS_INFO("Start+\n");
/* step1 : alloc tms common data */
tms = kzalloc(sizeof(struct tms_info), GFP_KERNEL);
if (tms == NULL) {
TMS_ERR("TMS info alloc memory error\n");
return -ENOMEM;
}
memset(tms, 0, sizeof(*tms));
/* step2 : tms class register */
tms->class = class_create(THIS_MODULE, DEVICES_CLASS_NAME);
if (IS_ERR(tms->class)) {
ret = PTR_ERR(tms->class);
TMS_ERR("Failed to register device class ret %d\n", ret);
goto err_free_tms_info;
}
/* step3 : binding common data and function */
tms->nfc_name = "thn31";
tms->registe_device = tms_device_register;
tms->unregiste_device = tms_device_unregister;
tms->set_ven = ven_gpio_set;
tms->set_download = download_gpio_set;
tms->set_reset = reset_gpio_set;
/* step4 : init proc */
ret = tms_proc_init();
if (ret) {
TMS_ERR("NFC device proc create failed.\n");
goto err_destroy_class;
}
TMS_INFO("Probe successfully\n");
return SUCCESS;
err_destroy_class:
class_destroy(tms->class);
err_free_tms_info:
kfree(tms);
tms = NULL;
TMS_ERR("Probe failed, ret = %d\n", ret);
return ret;
}
static int __init tms_common_init(void)
{
int ret;
TMS_INFO("TMS Common init is called!\n");
ret = tms_common_probe();
if (ret) {
TMS_ERR("Unable to init TMS Common, ret = %d\n", ret);
return ret;
}
#if defined(CONFIG_TMS_NFC_DEVICE_MODULE)
request_module("tms_nfc_module");
#endif
#if !defined(CONFIG_TMS_GUIDE_DEVICE) && !defined(CONFIG_TMS_GUIDE_DEVICE_MODULE)
#if defined(CONFIG_TMS_ESE_DEVICE_MODULE)
request_module("tms_ese_module");
#endif
#endif
return SUCCESS;
}
static void __exit tms_common_exit(void)
{
proc_remove(tms->prEntry);
if (!IS_ERR(tms->class)) {
class_destroy(tms->class);
}
if (tms) {
kfree(tms);
tms = NULL;
}
TMS_INFO("Remove TMS Common\n");
}
fs_initcall(tms_common_init);
module_exit(tms_common_exit);
MODULE_DESCRIPTION("TMS Device Common");
MODULE_LICENSE("GPL");