// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019 MediaTek Inc. * Author: Samuel Hsieh */ #include #include #include #include "mtk_ccci_common.h" #include "mtk_md_power_throttling.h" #include "mtk_low_battery_throttling.h" #include "mtk_battery_oc_throttling.h" #define MD_TX_REDUCE 6 struct md_priv { u32 lbat_md_reduce_tx; u32 oc_md_reduce_tx; }; static struct md_priv md_priv; static int isThreeLevel; #if IS_ENABLED(CONFIG_MTK_LOW_BATTERY_POWER_THROTTLING) static void md_pt_low_battery_cb(enum LOW_BATTERY_LEVEL_TAG level) { unsigned int md_throttle_cmd; int ret, intensity = 0; if (isThreeLevel) { if (level != LOW_BATTERY_LEVEL_0 && level != LOW_BATTERY_LEVEL_1) intensity = md_priv.lbat_md_reduce_tx; } else { if (level != LOW_BATTERY_LEVEL_0) intensity = md_priv.lbat_md_reduce_tx; } md_throttle_cmd = TMC_CTRL_CMD_TX_POWER | level << 8 | PT_LOW_BATTERY_VOLTAGE << 16 | intensity << 24; ret = exec_ccci_kern_func(ID_THROTTLING_CFG, (char *)&md_throttle_cmd, 4); if (ret) pr_notice("%s: error, ret=%d, cmd=0x%x l=%d\n", __func__, ret, md_throttle_cmd, level); } #endif #if IS_ENABLED(CONFIG_MTK_BATTERY_OC_POWER_THROTTLING) static void md_pt_over_current_cb(enum BATTERY_OC_LEVEL_TAG level) { unsigned int md_throttle_cmd; int ret, intensity; if (level <= BATTERY_OC_LEVEL_1) { if (level != BATTERY_OC_LEVEL_0) intensity = md_priv.oc_md_reduce_tx; else intensity = 0; md_throttle_cmd = TMC_CTRL_CMD_TX_POWER | level << 8 | PT_OVER_CURRENT << 16 | intensity << 24; ret = exec_ccci_kern_func(ID_THROTTLING_CFG, (char *)&md_throttle_cmd, 4); if (ret) pr_notice("%s: error, ret=%d, cmd=0x%x l=%d\n", __func__, ret, md_throttle_cmd, level); } } #endif static int mtk_md_power_throttling_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; int ret; md_priv.lbat_md_reduce_tx = MD_TX_REDUCE; md_priv.oc_md_reduce_tx = MD_TX_REDUCE; ret = of_property_read_u32(np, "lbat_md_reduce_tx", &md_priv.lbat_md_reduce_tx); if (ret < 0) pr_notice("%s: get lbat md tx reduce fail %d\n", __func__, ret); ret = of_property_read_u32(np, "oc_md_reduce_tx", &md_priv.oc_md_reduce_tx); if (ret) pr_notice("get oc md tx reduce fail ret=%d\n", ret); #if IS_ENABLED(CONFIG_MTK_LOW_BATTERY_POWER_THROTTLING) ret = register_low_battery_notify(&md_pt_low_battery_cb, LOW_BATTERY_PRIO_MD); if (ret == 3) isThreeLevel = 1; #endif #if IS_ENABLED(CONFIG_MTK_BATTERY_OC_POWER_THROTTLING) register_battery_oc_notify(&md_pt_over_current_cb, BATTERY_OC_PRIO_MD); #endif return 0; } static int mtk_md_power_throttling_remove(struct platform_device *pdev) { return 0; } static const struct of_device_id md_power_throttling_of_match[] = { { .compatible = "mediatek,md-power-throttling", }, {}, }; MODULE_DEVICE_TABLE(of, md_power_throttling_of_match); static struct platform_driver md_power_throttling_driver = { .probe = mtk_md_power_throttling_probe, .remove = mtk_md_power_throttling_remove, .driver = { .name = "mtk-md_power_throttling", .of_match_table = md_power_throttling_of_match, }, }; module_platform_driver(md_power_throttling_driver); MODULE_AUTHOR("Samuel Hsieh"); MODULE_DESCRIPTION("MTK modem power throttling driver"); MODULE_LICENSE("GPL");