blob: df41715c08ee1d5afe8fd5fb75bd54a223d337ae [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
*
* Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
*/
#include <linux/device.h>
#include "tops/firmware.h"
#include "tops/internal.h"
#include "tops/mcu.h"
#include "tops/trm.h"
#include "tops/tunnel.h"
#include "tops/wdt.h"
static int mtk_tops_trm_fetch_setting(const char *buf,
int *ofs,
char *name,
u32 *offset,
u32 *size,
u8 *enable)
{
int nchar = 0;
int ret = 0;
ret = sscanf(buf + *ofs, "%31s %x %x %hhx %n",
name, offset, size, enable, &nchar);
if (ret != 4)
return -EPERM;
*ofs += nchar;
return nchar;
}
static ssize_t mtk_tops_trm_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
char name[TRM_CONFIG_NAME_MAX_LEN] = { 0 };
char cmd[21] = { 0 };
int nchar = 0;
int ret = 0;
u32 offset;
u8 enable;
u32 size;
ret = sscanf(buf, "%20s %n", cmd, &nchar);
if (ret != 1)
return -EPERM;
if (!strcmp(cmd, "trm_dump")) {
ret = mtk_trm_dump(TRM_RSN_NULL);
if (ret)
return ret;
} else if (!strcmp(cmd, "trm_cfg_setup")) {
ret = mtk_tops_trm_fetch_setting(buf, &nchar,
name, &offset, &size, &enable);
if (ret < 0)
return ret;
ret = mtk_trm_cfg_setup(name, offset, size, enable);
if (ret)
return ret;
}
return count;
}
static ssize_t mtk_tops_wdt_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
char cmd[21] = {0};
u32 core = 0;
u32 i;
int ret;
ret = sscanf(buf, "%20s %x", cmd, &core);
if (ret != 2)
return -EPERM;
core &= CORE_TOPS_MASK;
if (!strcmp(cmd, "WDT_TO")) {
for (i = 0; i < CORE_TOPS_NUM; i++) {
if (core & 0x1)
mtk_tops_wdt_trigger_timeout(i);
core >>= 1;
}
} else {
return -EINVAL;
}
return count;
}
static DEVICE_ATTR_WO(mtk_tops_trm);
static DEVICE_ATTR_WO(mtk_tops_wdt);
static struct attribute *mtk_tops_attributes[] = {
&dev_attr_mtk_tops_trm.attr,
&dev_attr_mtk_tops_wdt.attr,
NULL,
};
static const struct attribute_group mtk_tops_attr_group = {
.name = "mtk_tops",
.attrs = mtk_tops_attributes,
};
int mtk_tops_ctrl_init(struct platform_device *pdev)
{
int ret = 0;
ret = sysfs_create_group(&pdev->dev.kobj, &mtk_tops_attr_group);
if (ret) {
TOPS_ERR("create sysfs failed\n");
return ret;
}
return ret;
}
void mtk_tops_ctrl_deinit(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &mtk_tops_attr_group);
}