1
0
mirror of https://github.com/physwizz/a155-U-u1.git synced 2024-11-19 13:27:49 +00:00
a155-U-u1/kernel-5.10/drivers/misc/mediatek/sda/irq-dbg.c
2024-03-11 06:53:12 +11:00

163 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#include <linux/arm-smccc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>
static unsigned int gic_irq(struct irq_data *d)
{
return d->hwirq;
}
static int virq_to_hwirq(unsigned int virq)
{
struct irq_desc *desc;
unsigned int hwirq = 0;
desc = irq_to_desc(virq);
if (desc)
hwirq = gic_irq(&desc->irq_data);
else
WARN_ON(!desc);
return hwirq;
}
static int mt_irq_dump_status_buf(unsigned int irq, char *buf)
{
unsigned int result;
unsigned int hwirq;
int num = 0;
char *ptr = buf;
struct arm_smccc_res res;
if (!ptr)
return 0;
hwirq = virq_to_hwirq(irq);
if (!hwirq)
return 0;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] hwirq = %d, virq: %d\n", hwirq, irq);
if (num == PAGE_SIZE)
goto OUT;
arm_smccc_smc(MTK_SIP_KERNEL_GIC_DUMP,
0, hwirq, 0, 0, 0, 0, 0, &res);
if (res.a0 == 0) {
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] not allowed to dump!\n");
if (num == PAGE_SIZE)
goto OUT;
return num;
}
/* get mask */
result = res.a0 & 0x1;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] enable = %d\n", result);
if (num == PAGE_SIZE)
goto OUT;
/* get group */
result = (res.a0 >> 1) & 0x1;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] group = %d\n", result);
if (num == PAGE_SIZE)
goto OUT;
/* get group modifier */
result = (res.a0 >> 2) & 0x1;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] group modifier = %d\n", result);
if (num == PAGE_SIZE)
goto OUT;
/* get priority */
result = (res.a0 >> 3) & 0xff;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] priority = %d\n", result);
if (num == PAGE_SIZE)
goto OUT;
/* get sensitivity */
result = (res.a0 >> 0xb) & 0x1;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] sensitivity = %x ", result);
num += snprintf(ptr + num, PAGE_SIZE - num,
"(edge:0x1, level:0x0)\n");
if (num == PAGE_SIZE)
goto OUT;
/* get pending status */
result = (res.a0 >> 0xc) & 0x1;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] pending = %x\n", result);
if (num == PAGE_SIZE)
goto OUT;
/* get active status */
result = (res.a0 >> 0xd) & 0x1;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] active status = %x\n", result);
if (num == PAGE_SIZE)
goto OUT;
/* get target cpu mask */
result = (res.a0 >> 0xe) & 0xffff;
num += snprintf(ptr + num, PAGE_SIZE - num,
"[mt gic dump] tartget cpu mask = 0x%x\n", result);
if (num == PAGE_SIZE)
goto OUT;
return num;
OUT:
pr_info("[mt gic dump] buffer is full\n");
return num;
}
void mt_irq_dump_status(unsigned int irq)
{
char *buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
if (!buf)
return;
/* support GIC PPI/SPI only */
if (mt_irq_dump_status_buf(irq, buf) > 0)
pr_info("%s", buf);
kfree(buf);
}
EXPORT_SYMBOL(mt_irq_dump_status);
static int __init irq_dbg_init(void)
{
return 0;
}
static __exit void irq_dbg_exit(void)
{
}
module_init(irq_dbg_init);
module_exit(irq_dbg_exit);
MODULE_DESCRIPTION("MediaTek IRQ dbg Driver");
MODULE_LICENSE("GPL v2");