Files
threeeye bc1d038eac REVVL 6 Pro kernel bring-up: full working tree snapshot (2026-09-12)
Squashed backup commit (no shallow-clone history issues) of
xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream
commit 9eece662e) plus all fixes applied to get everpal_defconfig building
clean against a modern (GCC 15.2.0) toolchain -- see the previous commit
message on the lineage-23.2 branch (also in this repo history is not
available here since this is a squashed snapshot; full incremental history
lives in the local DL380 checkout and the upstream GitHub remote).

Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
2026-09-12 13:36:46 +00:00

198 lines
4.6 KiB
C

/*
* Copyright (C) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*/
#include <linux/module.h>
#include <linux/of_fdt.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/of_address.h>
#include <mt-plat/mtk_secure_api.h>
#include <mt-plat/mtk_wd_api.h>
#include <mt-plat/sync_write.h>
#include <mt-plat/mtk_platform_debug.h>
#include "dfd.h"
#ifdef CONFIG_MTK_DBGTOP
extern int mtk_dbgtop_dfd_timeout(int value_abnormal, int value_normal);
#endif
static struct dfd_drv *drv;
/* return -1 for error indication */
int dfd_setup(int version)
{
int ret;
int dfd_doe;
struct wd_api *wd_api = NULL;
if (drv && (drv->enabled == 1) && (drv->base_addr > 0)) {
/* check support or not first */
if (check_dfd_support() == 0)
return -1;
/* get watchdog api */
ret = get_wd_api(&wd_api);
if (ret < 0)
return ret;
#ifdef CONFIG_MTK_DBGTOP
mtk_dbgtop_dfd_timeout(drv->rg_dfd_timeout, 0);
#else
wd_api->wd_dfd_count_en(1);
wd_api->wd_dfd_thermal1_dis(1);
wd_api->wd_dfd_thermal2_dis(0);
wd_api->wd_dfd_timeout(drv->rg_dfd_timeout);
#endif
if (drv->mem_reserve && drv->cachedump_en) {
dfd_doe = DFD_CACHE_DUMP_ENABLE;
if (drv->l2c_trigger)
dfd_doe |= DFD_PARITY_ERR_TRIGGER;
if (version == DFD_EXTENDED_DUMP)
ret = mt_secure_call(MTK_SIP_KERNEL_DFD,
DFD_SMC_MAGIC_SETUP,
(u64) drv->base_addr,
drv->chain_length, dfd_doe);
else
ret = mt_secure_call(MTK_SIP_KERNEL_DFD,
DFD_SMC_MAGIC_SETUP,
(u64) drv->base_addr,
drv->chain_length, 0);
} else {
ret = mt_secure_call(MTK_SIP_KERNEL_DFD,
DFD_SMC_MAGIC_SETUP,
(u64) drv->base_addr, drv->chain_length, 0);
}
if (ret < 0)
return ret;
if (set_sram_flag_dfd_valid() < 0)
return -1;
return ret;
} else
return -1;
}
static int __init fdt_get_chosen(unsigned long node, const char *uname,
int depth, void *data)
{
if (depth != 1 || (strcmp(uname, "chosen") != 0
&& strcmp(uname, "chosen@0") != 0))
return 0;
*(unsigned long *)data = node;
return 1;
}
static int __init dfd_init(void)
{
struct device_node *dev_node, *infra_node;
unsigned long node;
const void *prop;
unsigned int val;
drv = kzalloc(sizeof(struct dfd_drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
/* get dfd settings */
dev_node = of_find_compatible_node(NULL, NULL, "mediatek,dfd");
if (dev_node) {
if (of_property_read_u32(dev_node, "mediatek,enabled", &val))
drv->enabled = 0;
else
drv->enabled = val;
if (of_property_read_u32(dev_node,
"mediatek,chain_length", &val))
drv->chain_length = 0;
else
drv->chain_length = val;
if (of_property_read_u32(dev_node,
"mediatek,rg_dfd_timeout", &val))
drv->rg_dfd_timeout = 0;
else
drv->rg_dfd_timeout = val;
} else
return -ENODEV;
/* for cachedump enable */
dev_node = of_find_compatible_node(NULL, NULL,
"mediatek,dfd_cache");
if (dev_node) {
if (of_property_read_u32(dev_node, "mediatek,enabled", &val))
drv->cachedump_en = 0;
else
drv->cachedump_en = val;
if (drv->cachedump_en) {
if (!of_property_read_u32(dev_node,
"mediatek,rg_dfd_timeout", &val))
drv->rg_dfd_timeout = val;
if (!of_property_read_u32(dev_node,
"mediatek,l2c_trigger", &val))
drv->l2c_trigger = val;
}
}
if (drv->enabled == 0)
return 0;
of_scan_flat_dt(fdt_get_chosen, &node);
if (node) {
prop = of_get_flat_dt_prop(node, "dfd,base_addr_msb", NULL);
drv->base_addr_msb = (prop) ? of_read_number(prop, 1) : 0;
} else {
drv->base_addr_msb = 0;
}
of_scan_flat_dt(fdt_get_chosen, &node);
if (node) {
prop = of_get_flat_dt_prop(node,
"dfd,cache_dump_support", NULL);
drv->mem_reserve = (prop) ? of_read_number(prop, 1) : 0;
} else {
drv->mem_reserve = 0;
}
infra_node = of_find_compatible_node(NULL, NULL,
"mediatek,infracfg_ao");
if (infra_node) {
void __iomem *infra = of_iomap(infra_node, 0);
if (infra && drv->base_addr_msb) {
infra += dfd_infra_base();
writel(readl(infra)
| (drv->base_addr_msb >> dfd_ap_addr_offset()),
infra);
}
}
/* get base address if enabled */
of_scan_flat_dt(fdt_get_chosen, &node);
if (node) {
prop = of_get_flat_dt_prop(node, "dfd,base_addr", NULL);
drv->base_addr = (prop) ? (u64) of_read_number(prop, 2) : 0;
} else
return -ENODEV;
return 0;
}
core_initcall(dfd_init);