kernel-brax3-ubuntu-touch/drivers/spmi/spmi-mtk-mpu.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

199 lines
5 KiB
C

// SPDX-License-Identifier: GPL-2.0
//
// Copyright (c) 2021 MediaTek Inc.
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
struct pmif_mpu_data {
const u32 *regs;
};
struct pmif_mpu {
void __iomem *base;
const struct pmif_mpu_data *data;
};
struct pmif_mpu_timer {
struct pmif_mpu *mpu_arb;
struct platform_device *mpu_pdev;
struct timer_list mpu_enable_timer;
};
enum pmif_mpu_regs {
PMIF_MPU_CTRL,
PMIF_PMIC_ALL_RGN_EN,
PMIF_PMIC_ALL_RGN_EN_2,
};
static const u32 pmif_mpu_regs[] = {
[PMIF_MPU_CTRL] = 0x000,
[PMIF_PMIC_ALL_RGN_EN] = 0x0B0,
[PMIF_PMIC_ALL_RGN_EN_2] = 0x430,
};
static struct pmif_mpu_timer mpu_timer;
static u32 pmif_mpu_readl(struct pmif_mpu *arb, enum pmif_mpu_regs reg)
{
return readl(arb->base + arb->data->regs[reg]);
}
static void pmif_mpu_writel(struct pmif_mpu *arb, u32 val, enum pmif_mpu_regs reg)
{
writel(val, arb->base + arb->data->regs[reg]);
}
static const struct pmif_mpu_data pmif_mpu_arb = {
.regs = pmif_mpu_regs,
};
static void enable_kernel_mpu(void)
{
u32 pmic_all_rgn_en = 0, rgn_en = 0, rgn_en_2 = 0;
int err;
struct pmif_mpu_timer *pmt = from_timer(pmt,
&(mpu_timer.mpu_enable_timer), mpu_enable_timer);
struct pmif_mpu *mpu_arb = pmt->mpu_arb;
struct platform_device *mpu_pdev = pmt->mpu_pdev;
if ((IS_ERR(pmt))) {
err = PTR_ERR(pmt);
dev_info(&mpu_pdev->dev, "MPU pmt ptr error err:0x%x\n", err);
return;
}
if ((IS_ERR(mpu_arb))) {
err = PTR_ERR(mpu_arb);
dev_info(&mpu_pdev->dev, "MPU mpu_arb ptr error err:0x%x\n", err);
return;
}
if ((IS_ERR(mpu_pdev))) {
err = PTR_ERR(mpu_pdev);
dev_info(&mpu_pdev->dev, "MPU mpu_pdev ptr error err:0x%x\n", err);
return;
}
dev_info(&mpu_pdev->dev, "enable kernel stage mpu region\n");
if (!of_property_read_u32(mpu_pdev->dev.of_node, "mediatek,pmic-all-rgn-en",
&pmic_all_rgn_en)) {
rgn_en = pmif_mpu_readl(mpu_arb, PMIF_PMIC_ALL_RGN_EN);
rgn_en |= pmic_all_rgn_en;
pmif_mpu_writel(mpu_arb, rgn_en, PMIF_PMIC_ALL_RGN_EN);
rgn_en = pmif_mpu_readl(mpu_arb, PMIF_PMIC_ALL_RGN_EN);
}
if (!of_property_read_u32(mpu_pdev->dev.of_node, "mediatek,pmic-all-rgn-en-2",
&pmic_all_rgn_en)) {
rgn_en_2 = pmif_mpu_readl(mpu_arb, PMIF_PMIC_ALL_RGN_EN_2);
rgn_en_2 |= pmic_all_rgn_en;
pmif_mpu_writel(mpu_arb, rgn_en_2, PMIF_PMIC_ALL_RGN_EN_2);
rgn_en_2 = pmif_mpu_readl(mpu_arb, PMIF_PMIC_ALL_RGN_EN_2);
}
pmif_mpu_writel(mpu_arb, 1, PMIF_MPU_CTRL);
dev_info(&mpu_pdev->dev, "PMIC_ALL_RGN_EN=0x%x, PMIC_ALL_RGN_EN_2=0x%x MPU late init setting done\n",
rgn_en, rgn_en_2);
}
static void enable_kernel_mpu_handler(struct timer_list *t)
{
enable_kernel_mpu();
}
static int mtk_spmi_pmif_mpu_probe(struct platform_device *pdev)
{
struct pmif_mpu *arb = NULL;
int err = 0;
u32 disable_pmif_mpu = 0, mpu_delay_enable_time = 0;
arb = devm_kzalloc(&pdev->dev, sizeof(*arb), GFP_KERNEL);
if (!arb)
return -ENOMEM;
arb->data = of_device_get_match_data(&pdev->dev);
if (!arb->data) {
dev_info(&pdev->dev, "cannot get drv_data\n");
return -EINVAL;
}
arb->base = devm_platform_ioremap_resource_byname(pdev, "pmif_mpu");
if (IS_ERR(arb->base)) {
err = PTR_ERR(arb->base);
dev_info(&pdev->dev, "failed to get remapped address\n");
return PTR_ERR(arb->base);
}
platform_set_drvdata(pdev, arb);
if (!of_property_read_u32(pdev->dev.of_node, "disable", &disable_pmif_mpu)) {
if (disable_pmif_mpu) {
pmif_mpu_writel(arb, 0, PMIF_PMIC_ALL_RGN_EN);
dev_info(&pdev->dev, "Disable PMIF MPU\n");
return 0;
}
}
mpu_timer.mpu_arb = arb;
mpu_timer.mpu_pdev = pdev;
if (!of_property_read_u32(pdev->dev.of_node, "mediatek,kernel-enable-time",
&mpu_delay_enable_time)) {
/* enable kernel stage MPU region after insert mpu.ko for dts defined time sec*/
dev_info(&pdev->dev, "MPU delay enable %usec after mpu.ko insert\n",
mpu_delay_enable_time);
timer_setup(&mpu_timer.mpu_enable_timer, enable_kernel_mpu_handler, 0);
mod_timer(&mpu_timer.mpu_enable_timer,
(jiffies + msecs_to_jiffies(mpu_delay_enable_time*1000)));
}
return 0;
}
static int mtk_spmi_pmif_mpu_remove(struct platform_device *pdev)
{
return 0;
}
static const struct of_device_id mtk_spmi_pmif_mpu_match_table[] = {
{
.compatible = "mediatek,mt6835-spmi-pmif-mpu",
.data = &pmif_mpu_arb,
}, {
.compatible = "mediatek,mt6886-spmi_pmif_mpu",
.data = &pmif_mpu_arb,
}, {
.compatible = "mediatek,mt6895-spmi_pmif_mpu",
.data = &pmif_mpu_arb,
}, {
.compatible = "mediatek,mt6983-spmi_pmif_mpu",
.data = &pmif_mpu_arb,
}, {
.compatible = "mediatek,mt6985-spmi_pmif_mpu",
.data = &pmif_mpu_arb,
}, {
/* sentinel */
},
};
MODULE_DEVICE_TABLE(of, mtk_spmi_pmif_mpu_match_table);
static struct platform_driver mtk_spmi_pmif_mpu_driver = {
.driver = {
.name = "spmi-mtk-mpu",
.of_match_table = of_match_ptr(mtk_spmi_pmif_mpu_match_table),
},
.probe = mtk_spmi_pmif_mpu_probe,
.remove = mtk_spmi_pmif_mpu_remove,
};
module_platform_driver(mtk_spmi_pmif_mpu_driver);
MODULE_DESCRIPTION("MediaTek SPMI PMIF MPU Driver");
MODULE_LICENSE("GPL");