Loading Documentation/devicetree/bindings/arm/msm/bcl.txt +20 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,13 @@ Optional parameters: are defined. Error in any of these properties will disable BTM mode of operation and will fall back to the available current monitor mode. - qcom,bcl-framework-interface: If this property is defined, then the BCL uses the BCL framework for monitoring battery voltage and current. When this property is defined, the 'high-threshold-uamp', 'low-threshold-uamp', 'mitigation-freq-khz', 'vph-high-threshold-uv', 'vph-low-threshold-uv' and 'thermal-handle' properties should be defined in the 'qcom,ibat-monitor' node. Optional nodes: - qcom,ibat-monitor: This optional node defines all the parameters for the Loading Loading @@ -96,6 +103,19 @@ Example: thermal-handle = <&msm_thermal_freq>; }; }; For Using BCL peripheral interface: qcom,bcl { compatible = "qcom,bcl"; qcom,bcl-framework-interface; qcom,ibat-monitor { high-threshold-uamp = <1500>; low-threshold-uamp = <500>; mitigation-freq-khz = <1958400>; vph-high-threshold-uv = <3700000>; vph-low-threshold-uv = <3500000>; thermal-handle = <&msm_thermal_freq>; }; }; =============================================================================== BCL PMIC Peripheral driver: Loading drivers/power/battery_current_limit.c +203 −22 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/cpufreq.h> #include <linux/qpnp/qpnp-adc.h> #include <linux/cpu.h> #include <linux/msm_bcl.h> #define BCL_DEV_NAME "battery_current_limit" #define BCL_NAME_LENGTH 20 Loading @@ -39,6 +40,13 @@ #define BATTERY_VOLTAGE_MIN 3400 #define BTM_8084_FREQ_MITIG_LIMIT 1958400 #define BCL_FETCH_DT_U32(_dev, _key, _search_str, _ret, _out, _exit) do { \ _key = _search_str; \ _ret = of_property_read_u32(_dev, _key, &_out); \ if (_ret) \ goto _exit; \ } while (0) /* * Battery Current Limit Enable or Not */ Loading Loading @@ -67,6 +75,7 @@ enum bcl_iavail_threshold_type { enum bcl_monitor_type { BCL_IAVAIL_MONITOR_TYPE, BCL_IBAT_MONITOR_TYPE, BCL_IBAT_PERIPH_MONITOR_TYPE, BCL_MONITOR_TYPE_MAX, }; Loading @@ -78,7 +87,8 @@ enum bcl_adc_monitor_mode { BCL_MONITOR_MODE_MAX, }; static const char *bcl_type[BCL_MONITOR_TYPE_MAX] = {"bcl", "btm"}; static const char *bcl_type[BCL_MONITOR_TYPE_MAX] = {"bcl", "btm", "bcl_peripheral"}; int adc_timer_val_usec[] = { [ADC_MEAS1_INTERVAL_0MS] = 0, [ADC_MEAS1_INTERVAL_1P0MS] = 1000, Loading Loading @@ -155,7 +165,14 @@ struct bcl_context { uint32_t btm_vph_low_thresh; struct qpnp_adc_tm_btm_param btm_vph_adc_param; /* Low temp min freq limit requested by thermal */ uint32_t btm_freq_limit; uint32_t thermal_freq_limit; /* BCL Peripheral monitor parameters */ struct bcl_threshold ibat_high_thresh; struct bcl_threshold ibat_low_thresh; struct bcl_threshold vbat_high_thresh; struct bcl_threshold vbat_low_thresh; uint32_t bcl_p_freq_max; }; enum bcl_threshold_state { Loading @@ -173,15 +190,19 @@ static int bcl_cpufreq_callback(struct notifier_block *nfb, unsigned long event, void *data) { struct cpufreq_policy *policy = data; uint32_t max_freq = UINT_MAX; switch (event) { case CPUFREQ_INCOMPATIBLE: if (bcl_vph_state == BCL_LOW_THRESHOLD && bcl_ibat_state == BCL_HIGH_THRESHOLD) { max_freq = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_freq_max : gbcl->bcl_p_freq_max; pr_debug("Requesting Max freq:%d for CPU%d\n", gbcl->btm_freq_max, policy->cpu); max_freq, policy->cpu); cpufreq_verify_within_limits(policy, 0, gbcl->btm_freq_max); max_freq); } break; } Loading Loading @@ -485,6 +506,79 @@ ibat_disable_exit: return ret; } static void bcl_periph_ibat_notify(enum bcl_trip_type type, int trip_temp, void *data) { if (type == BCL_HIGH_TRIP) bcl_ibat_notify(BCL_HIGH_THRESHOLD); else bcl_ibat_notify(BCL_LOW_THRESHOLD); return; } static void bcl_periph_vbat_notify(enum bcl_trip_type type, int trip_temp, void *data) { if (type == BCL_HIGH_TRIP) bcl_vph_notify(BCL_HIGH_THRESHOLD); else bcl_vph_notify(BCL_LOW_THRESHOLD); return; } static void bcl_periph_mode_set(enum bcl_device_mode mode) { int ret = 0; if (mode == BCL_DEVICE_ENABLED) { ret = msm_bcl_set_threshold(BCL_PARAM_CURRENT, BCL_HIGH_TRIP, &gbcl->ibat_high_thresh); if (ret) { pr_err("Error setting Ibat high threshold. err:%d\n", ret); return; } ret = msm_bcl_set_threshold(BCL_PARAM_CURRENT, BCL_LOW_TRIP, &gbcl->ibat_low_thresh); if (ret) { pr_err("Error setting Ibat low threshold. err:%d\n", ret); return; } ret = msm_bcl_set_threshold(BCL_PARAM_VOLTAGE, BCL_LOW_TRIP, &gbcl->vbat_low_thresh); if (ret) { pr_err("Error setting Vbat low threshold. err:%d\n", ret); return; } ret = msm_bcl_set_threshold(BCL_PARAM_VOLTAGE, BCL_HIGH_TRIP, &gbcl->vbat_high_thresh); if (ret) { pr_err("Error setting Vbat high threshold. err:%d\n", ret); return; } ret = msm_bcl_enable(); if (ret) { pr_err("Error enabling BCL\n"); return; } gbcl->btm_mode = BCL_VPH_MONITOR_MODE; } else { ret = msm_bcl_disable(); if (ret) { pr_err("Error disabling BCL\n"); return; } gbcl->btm_mode = BCL_MONITOR_DISABLED; bcl_vph_notify(BCL_HIGH_THRESHOLD); bcl_ibat_notify(BCL_LOW_THRESHOLD); } } static void ibat_mode_set(enum bcl_device_mode mode) { int ret = 0; Loading Loading @@ -599,6 +693,9 @@ static void bcl_mode_set(enum bcl_device_mode mode) case BCL_IBAT_MONITOR_TYPE: ibat_mode_set(mode); break; case BCL_IBAT_PERIPH_MONITOR_TYPE: bcl_periph_mode_set(mode); break; default: pr_err("Invalid monitor type:%d\n", gbcl->bcl_monitor_type); break; Loading @@ -623,15 +720,21 @@ show_bcl(rbat, gbcl->bcl_rbat_mohm, "%d\n") show_bcl(iavail, gbcl->bcl_iavail, "%d\n") show_bcl(vbat_min, gbcl->bcl_vbat_min, "%d\n") show_bcl(poll_interval, gbcl->bcl_poll_interval_msec, "%d\n") show_bcl(high_ua, voltage_to_current(gbcl, gbcl->btm_high_threshold_uv), "%d\n") show_bcl(low_ua, voltage_to_current(gbcl, gbcl->btm_low_threshold_uv), "%d\n") show_bcl(adc_interval_us, adc_time_to_uSec(gbcl, gbcl->btm_adc_interval), "%d\n") show_bcl(freq_max, gbcl->btm_freq_max, "%u\n") show_bcl(vph_high, gbcl->btm_vph_high_thresh, "%d\n") show_bcl(vph_low, gbcl->btm_vph_low_thresh, "%d\n") show_bcl(freq_limit, gbcl->btm_freq_limit, "%u\n") show_bcl(high_ua, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? voltage_to_current(gbcl, gbcl->btm_high_threshold_uv) : gbcl->ibat_high_thresh.trip_value, "%d\n") show_bcl(low_ua, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? voltage_to_current(gbcl, gbcl->btm_low_threshold_uv) : gbcl->ibat_low_thresh.trip_value, "%d\n") show_bcl(adc_interval_us, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? adc_time_to_uSec(gbcl, gbcl->btm_adc_interval) : 0, "%d\n") show_bcl(freq_max, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_freq_max : gbcl->bcl_p_freq_max, "%u\n") show_bcl(vph_high, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_vph_high_thresh : gbcl->vbat_high_thresh.trip_value, "%d\n") show_bcl(vph_low, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_vph_low_thresh : gbcl->vbat_low_thresh.trip_value, "%d\n") show_bcl(freq_limit, gbcl->thermal_freq_limit, "%u\n") show_bcl(vph_state, bcl_vph_state, "%d\n") show_bcl(ibat_state, bcl_ibat_state, "%d\n") Loading Loading @@ -858,7 +961,11 @@ static ssize_t high_ua_store(struct device *dev, ret = convert_to_int(buf, &val); if (ret) return ret; if (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) gbcl->btm_high_threshold_uv = current_to_voltage(gbcl, val); else gbcl->ibat_high_thresh.trip_value = val; return count; } Loading @@ -873,7 +980,11 @@ static ssize_t low_ua_store(struct device *dev, ret = convert_to_int(buf, &val); if (ret) return ret; if (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) gbcl->btm_low_threshold_uv = current_to_voltage(gbcl, val); else gbcl->ibat_low_thresh.trip_value = val; return count; } Loading @@ -884,11 +995,14 @@ static ssize_t freq_max_store(struct device *dev, { int val = 0; int ret = 0; uint32_t *freq_lim = NULL; ret = convert_to_int(buf, &val); if (ret) return ret; gbcl->btm_freq_max = max_t(uint32_t, val, gbcl->btm_freq_limit); freq_lim = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? &gbcl->btm_freq_max : &gbcl->bcl_p_freq_max; *freq_lim = max_t(uint32_t, val, gbcl->thermal_freq_limit); return count; } Loading @@ -899,11 +1013,16 @@ static ssize_t vph_low_store(struct device *dev, { int val = 0; int ret = 0; int *thresh = NULL; ret = convert_to_int(buf, &val); if (ret) return ret; gbcl->btm_vph_low_thresh = val; thresh = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? (int *)&gbcl->btm_vph_low_thresh : &gbcl->vbat_low_thresh.trip_value; *thresh = val; return count; } Loading @@ -914,11 +1033,16 @@ static ssize_t vph_high_store(struct device *dev, { int val = 0; int ret = 0; int *thresh = NULL; ret = convert_to_int(buf, &val); if (ret) return ret; gbcl->btm_vph_high_thresh = val; thresh = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? (int *)&gbcl->btm_vph_high_thresh : &gbcl->vbat_high_thresh.trip_value; *thresh = val; return count; } Loading Loading @@ -974,6 +1098,7 @@ static int create_bcl_sysfs(struct bcl_context *bcl) attr_ptr = bcl_dev_attr; break; case BCL_IBAT_MONITOR_TYPE: case BCL_IBAT_PERIPH_MONITOR_TYPE: num_attr = sizeof(btm_dev_attr)/sizeof(struct device_attribute); attr_ptr = btm_dev_attr; break; Loading Loading @@ -1154,7 +1279,7 @@ static void get_vdd_rstr_freq(struct bcl_context *bcl, } key = "qcom,levels"; ret = of_property_read_u32_index(phandle, key, 0, &bcl->btm_freq_limit); &bcl->thermal_freq_limit); if (ret) { pr_err("Error reading property %s. ret:%d\n", key, ret); goto vdd_rstr_exit; Loading @@ -1162,10 +1287,61 @@ static void get_vdd_rstr_freq(struct bcl_context *bcl, vdd_rstr_exit: if (ret) bcl->btm_freq_limit = BTM_8084_FREQ_MITIG_LIMIT; bcl->thermal_freq_limit = BTM_8084_FREQ_MITIG_LIMIT; return; } static int probe_bcl_periph_prop(struct bcl_context *bcl) { int ret = 0; struct device_node *ibat_node = NULL, *dev_node = bcl->dev->of_node; char *key = NULL; key = "qcom,ibat-monitor"; ibat_node = of_find_node_by_name(dev_node, key); if (!ibat_node) { ret = -ENODEV; goto ibat_probe_exit; } BCL_FETCH_DT_U32(ibat_node, key, "low-threshold-uamp", ret, bcl->ibat_low_thresh.trip_value, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "high-threshold-uamp", ret, bcl->ibat_high_thresh.trip_value, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "mitigation-freq-khz", ret, bcl->bcl_p_freq_max, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "vph-high-threshold-uv", ret, bcl->vbat_high_thresh.trip_value, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "vph-low-threshold-uv", ret, bcl->vbat_low_thresh.trip_value, ibat_probe_exit); bcl->vbat_high_thresh.trip_notify = bcl->vbat_low_thresh.trip_notify = bcl_periph_vbat_notify; bcl->vbat_high_thresh.trip_data = bcl->vbat_low_thresh.trip_data = (void *) bcl; bcl->ibat_high_thresh.trip_notify = bcl->ibat_low_thresh.trip_notify = bcl_periph_ibat_notify; bcl->ibat_high_thresh.trip_data = bcl->ibat_low_thresh.trip_data = (void *) bcl; get_vdd_rstr_freq(bcl, ibat_node); bcl->bcl_p_freq_max = max(bcl->bcl_p_freq_max, bcl->thermal_freq_limit); bcl->btm_mode = BCL_MONITOR_DISABLED; bcl->bcl_monitor_type = BCL_IBAT_PERIPH_MONITOR_TYPE; snprintf(bcl->bcl_type, BCL_NAME_LENGTH, "%s", bcl_type[BCL_IBAT_PERIPH_MONITOR_TYPE]); ret = cpufreq_register_notifier(&bcl_cpufreq_notifier, CPUFREQ_POLICY_NOTIFIER); if (ret) pr_err("Error with cpufreq register. err:%d\n", ret); ibat_probe_exit: if (ret && ret != -EPROBE_DEFER) dev_info(bcl->dev, "%s:%s Error reading key:%s. ret = %d\n", KBUILD_MODNAME, __func__, key, ret); return ret; } static int probe_btm_properties(struct bcl_context *bcl) { int ret = 0, curr_ua = 0; Loading Loading @@ -1249,7 +1425,7 @@ static int probe_btm_properties(struct bcl_context *bcl) goto btm_probe_exit; } get_vdd_rstr_freq(bcl, ibat_node); bcl->btm_freq_max = max(bcl->btm_freq_max, bcl->btm_freq_limit); bcl->btm_freq_max = max(bcl->btm_freq_max, bcl->thermal_freq_limit); bcl->btm_mode = BCL_MONITOR_DISABLED; bcl->bcl_monitor_type = BCL_IBAT_MONITOR_TYPE; Loading Loading @@ -1300,7 +1476,12 @@ static int bcl_probe(struct platform_device *pdev) bcl_type[BCL_IAVAIL_MONITOR_TYPE]); bcl->bcl_poll_interval_msec = BCL_POLL_INTERVAL; if (of_property_read_bool(pdev->dev.of_node, "qcom,bcl-framework-interface")) ret = probe_bcl_periph_prop(bcl); else ret = probe_btm_properties(bcl); if (ret == -EPROBE_DEFER) return ret; Loading Loading
Documentation/devicetree/bindings/arm/msm/bcl.txt +20 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,13 @@ Optional parameters: are defined. Error in any of these properties will disable BTM mode of operation and will fall back to the available current monitor mode. - qcom,bcl-framework-interface: If this property is defined, then the BCL uses the BCL framework for monitoring battery voltage and current. When this property is defined, the 'high-threshold-uamp', 'low-threshold-uamp', 'mitigation-freq-khz', 'vph-high-threshold-uv', 'vph-low-threshold-uv' and 'thermal-handle' properties should be defined in the 'qcom,ibat-monitor' node. Optional nodes: - qcom,ibat-monitor: This optional node defines all the parameters for the Loading Loading @@ -96,6 +103,19 @@ Example: thermal-handle = <&msm_thermal_freq>; }; }; For Using BCL peripheral interface: qcom,bcl { compatible = "qcom,bcl"; qcom,bcl-framework-interface; qcom,ibat-monitor { high-threshold-uamp = <1500>; low-threshold-uamp = <500>; mitigation-freq-khz = <1958400>; vph-high-threshold-uv = <3700000>; vph-low-threshold-uv = <3500000>; thermal-handle = <&msm_thermal_freq>; }; }; =============================================================================== BCL PMIC Peripheral driver: Loading
drivers/power/battery_current_limit.c +203 −22 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <linux/cpufreq.h> #include <linux/qpnp/qpnp-adc.h> #include <linux/cpu.h> #include <linux/msm_bcl.h> #define BCL_DEV_NAME "battery_current_limit" #define BCL_NAME_LENGTH 20 Loading @@ -39,6 +40,13 @@ #define BATTERY_VOLTAGE_MIN 3400 #define BTM_8084_FREQ_MITIG_LIMIT 1958400 #define BCL_FETCH_DT_U32(_dev, _key, _search_str, _ret, _out, _exit) do { \ _key = _search_str; \ _ret = of_property_read_u32(_dev, _key, &_out); \ if (_ret) \ goto _exit; \ } while (0) /* * Battery Current Limit Enable or Not */ Loading Loading @@ -67,6 +75,7 @@ enum bcl_iavail_threshold_type { enum bcl_monitor_type { BCL_IAVAIL_MONITOR_TYPE, BCL_IBAT_MONITOR_TYPE, BCL_IBAT_PERIPH_MONITOR_TYPE, BCL_MONITOR_TYPE_MAX, }; Loading @@ -78,7 +87,8 @@ enum bcl_adc_monitor_mode { BCL_MONITOR_MODE_MAX, }; static const char *bcl_type[BCL_MONITOR_TYPE_MAX] = {"bcl", "btm"}; static const char *bcl_type[BCL_MONITOR_TYPE_MAX] = {"bcl", "btm", "bcl_peripheral"}; int adc_timer_val_usec[] = { [ADC_MEAS1_INTERVAL_0MS] = 0, [ADC_MEAS1_INTERVAL_1P0MS] = 1000, Loading Loading @@ -155,7 +165,14 @@ struct bcl_context { uint32_t btm_vph_low_thresh; struct qpnp_adc_tm_btm_param btm_vph_adc_param; /* Low temp min freq limit requested by thermal */ uint32_t btm_freq_limit; uint32_t thermal_freq_limit; /* BCL Peripheral monitor parameters */ struct bcl_threshold ibat_high_thresh; struct bcl_threshold ibat_low_thresh; struct bcl_threshold vbat_high_thresh; struct bcl_threshold vbat_low_thresh; uint32_t bcl_p_freq_max; }; enum bcl_threshold_state { Loading @@ -173,15 +190,19 @@ static int bcl_cpufreq_callback(struct notifier_block *nfb, unsigned long event, void *data) { struct cpufreq_policy *policy = data; uint32_t max_freq = UINT_MAX; switch (event) { case CPUFREQ_INCOMPATIBLE: if (bcl_vph_state == BCL_LOW_THRESHOLD && bcl_ibat_state == BCL_HIGH_THRESHOLD) { max_freq = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_freq_max : gbcl->bcl_p_freq_max; pr_debug("Requesting Max freq:%d for CPU%d\n", gbcl->btm_freq_max, policy->cpu); max_freq, policy->cpu); cpufreq_verify_within_limits(policy, 0, gbcl->btm_freq_max); max_freq); } break; } Loading Loading @@ -485,6 +506,79 @@ ibat_disable_exit: return ret; } static void bcl_periph_ibat_notify(enum bcl_trip_type type, int trip_temp, void *data) { if (type == BCL_HIGH_TRIP) bcl_ibat_notify(BCL_HIGH_THRESHOLD); else bcl_ibat_notify(BCL_LOW_THRESHOLD); return; } static void bcl_periph_vbat_notify(enum bcl_trip_type type, int trip_temp, void *data) { if (type == BCL_HIGH_TRIP) bcl_vph_notify(BCL_HIGH_THRESHOLD); else bcl_vph_notify(BCL_LOW_THRESHOLD); return; } static void bcl_periph_mode_set(enum bcl_device_mode mode) { int ret = 0; if (mode == BCL_DEVICE_ENABLED) { ret = msm_bcl_set_threshold(BCL_PARAM_CURRENT, BCL_HIGH_TRIP, &gbcl->ibat_high_thresh); if (ret) { pr_err("Error setting Ibat high threshold. err:%d\n", ret); return; } ret = msm_bcl_set_threshold(BCL_PARAM_CURRENT, BCL_LOW_TRIP, &gbcl->ibat_low_thresh); if (ret) { pr_err("Error setting Ibat low threshold. err:%d\n", ret); return; } ret = msm_bcl_set_threshold(BCL_PARAM_VOLTAGE, BCL_LOW_TRIP, &gbcl->vbat_low_thresh); if (ret) { pr_err("Error setting Vbat low threshold. err:%d\n", ret); return; } ret = msm_bcl_set_threshold(BCL_PARAM_VOLTAGE, BCL_HIGH_TRIP, &gbcl->vbat_high_thresh); if (ret) { pr_err("Error setting Vbat high threshold. err:%d\n", ret); return; } ret = msm_bcl_enable(); if (ret) { pr_err("Error enabling BCL\n"); return; } gbcl->btm_mode = BCL_VPH_MONITOR_MODE; } else { ret = msm_bcl_disable(); if (ret) { pr_err("Error disabling BCL\n"); return; } gbcl->btm_mode = BCL_MONITOR_DISABLED; bcl_vph_notify(BCL_HIGH_THRESHOLD); bcl_ibat_notify(BCL_LOW_THRESHOLD); } } static void ibat_mode_set(enum bcl_device_mode mode) { int ret = 0; Loading Loading @@ -599,6 +693,9 @@ static void bcl_mode_set(enum bcl_device_mode mode) case BCL_IBAT_MONITOR_TYPE: ibat_mode_set(mode); break; case BCL_IBAT_PERIPH_MONITOR_TYPE: bcl_periph_mode_set(mode); break; default: pr_err("Invalid monitor type:%d\n", gbcl->bcl_monitor_type); break; Loading @@ -623,15 +720,21 @@ show_bcl(rbat, gbcl->bcl_rbat_mohm, "%d\n") show_bcl(iavail, gbcl->bcl_iavail, "%d\n") show_bcl(vbat_min, gbcl->bcl_vbat_min, "%d\n") show_bcl(poll_interval, gbcl->bcl_poll_interval_msec, "%d\n") show_bcl(high_ua, voltage_to_current(gbcl, gbcl->btm_high_threshold_uv), "%d\n") show_bcl(low_ua, voltage_to_current(gbcl, gbcl->btm_low_threshold_uv), "%d\n") show_bcl(adc_interval_us, adc_time_to_uSec(gbcl, gbcl->btm_adc_interval), "%d\n") show_bcl(freq_max, gbcl->btm_freq_max, "%u\n") show_bcl(vph_high, gbcl->btm_vph_high_thresh, "%d\n") show_bcl(vph_low, gbcl->btm_vph_low_thresh, "%d\n") show_bcl(freq_limit, gbcl->btm_freq_limit, "%u\n") show_bcl(high_ua, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? voltage_to_current(gbcl, gbcl->btm_high_threshold_uv) : gbcl->ibat_high_thresh.trip_value, "%d\n") show_bcl(low_ua, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? voltage_to_current(gbcl, gbcl->btm_low_threshold_uv) : gbcl->ibat_low_thresh.trip_value, "%d\n") show_bcl(adc_interval_us, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? adc_time_to_uSec(gbcl, gbcl->btm_adc_interval) : 0, "%d\n") show_bcl(freq_max, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_freq_max : gbcl->bcl_p_freq_max, "%u\n") show_bcl(vph_high, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_vph_high_thresh : gbcl->vbat_high_thresh.trip_value, "%d\n") show_bcl(vph_low, (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? gbcl->btm_vph_low_thresh : gbcl->vbat_low_thresh.trip_value, "%d\n") show_bcl(freq_limit, gbcl->thermal_freq_limit, "%u\n") show_bcl(vph_state, bcl_vph_state, "%d\n") show_bcl(ibat_state, bcl_ibat_state, "%d\n") Loading Loading @@ -858,7 +961,11 @@ static ssize_t high_ua_store(struct device *dev, ret = convert_to_int(buf, &val); if (ret) return ret; if (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) gbcl->btm_high_threshold_uv = current_to_voltage(gbcl, val); else gbcl->ibat_high_thresh.trip_value = val; return count; } Loading @@ -873,7 +980,11 @@ static ssize_t low_ua_store(struct device *dev, ret = convert_to_int(buf, &val); if (ret) return ret; if (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) gbcl->btm_low_threshold_uv = current_to_voltage(gbcl, val); else gbcl->ibat_low_thresh.trip_value = val; return count; } Loading @@ -884,11 +995,14 @@ static ssize_t freq_max_store(struct device *dev, { int val = 0; int ret = 0; uint32_t *freq_lim = NULL; ret = convert_to_int(buf, &val); if (ret) return ret; gbcl->btm_freq_max = max_t(uint32_t, val, gbcl->btm_freq_limit); freq_lim = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? &gbcl->btm_freq_max : &gbcl->bcl_p_freq_max; *freq_lim = max_t(uint32_t, val, gbcl->thermal_freq_limit); return count; } Loading @@ -899,11 +1013,16 @@ static ssize_t vph_low_store(struct device *dev, { int val = 0; int ret = 0; int *thresh = NULL; ret = convert_to_int(buf, &val); if (ret) return ret; gbcl->btm_vph_low_thresh = val; thresh = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? (int *)&gbcl->btm_vph_low_thresh : &gbcl->vbat_low_thresh.trip_value; *thresh = val; return count; } Loading @@ -914,11 +1033,16 @@ static ssize_t vph_high_store(struct device *dev, { int val = 0; int ret = 0; int *thresh = NULL; ret = convert_to_int(buf, &val); if (ret) return ret; gbcl->btm_vph_high_thresh = val; thresh = (gbcl->bcl_monitor_type == BCL_IBAT_MONITOR_TYPE) ? (int *)&gbcl->btm_vph_high_thresh : &gbcl->vbat_high_thresh.trip_value; *thresh = val; return count; } Loading Loading @@ -974,6 +1098,7 @@ static int create_bcl_sysfs(struct bcl_context *bcl) attr_ptr = bcl_dev_attr; break; case BCL_IBAT_MONITOR_TYPE: case BCL_IBAT_PERIPH_MONITOR_TYPE: num_attr = sizeof(btm_dev_attr)/sizeof(struct device_attribute); attr_ptr = btm_dev_attr; break; Loading Loading @@ -1154,7 +1279,7 @@ static void get_vdd_rstr_freq(struct bcl_context *bcl, } key = "qcom,levels"; ret = of_property_read_u32_index(phandle, key, 0, &bcl->btm_freq_limit); &bcl->thermal_freq_limit); if (ret) { pr_err("Error reading property %s. ret:%d\n", key, ret); goto vdd_rstr_exit; Loading @@ -1162,10 +1287,61 @@ static void get_vdd_rstr_freq(struct bcl_context *bcl, vdd_rstr_exit: if (ret) bcl->btm_freq_limit = BTM_8084_FREQ_MITIG_LIMIT; bcl->thermal_freq_limit = BTM_8084_FREQ_MITIG_LIMIT; return; } static int probe_bcl_periph_prop(struct bcl_context *bcl) { int ret = 0; struct device_node *ibat_node = NULL, *dev_node = bcl->dev->of_node; char *key = NULL; key = "qcom,ibat-monitor"; ibat_node = of_find_node_by_name(dev_node, key); if (!ibat_node) { ret = -ENODEV; goto ibat_probe_exit; } BCL_FETCH_DT_U32(ibat_node, key, "low-threshold-uamp", ret, bcl->ibat_low_thresh.trip_value, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "high-threshold-uamp", ret, bcl->ibat_high_thresh.trip_value, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "mitigation-freq-khz", ret, bcl->bcl_p_freq_max, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "vph-high-threshold-uv", ret, bcl->vbat_high_thresh.trip_value, ibat_probe_exit); BCL_FETCH_DT_U32(ibat_node, key, "vph-low-threshold-uv", ret, bcl->vbat_low_thresh.trip_value, ibat_probe_exit); bcl->vbat_high_thresh.trip_notify = bcl->vbat_low_thresh.trip_notify = bcl_periph_vbat_notify; bcl->vbat_high_thresh.trip_data = bcl->vbat_low_thresh.trip_data = (void *) bcl; bcl->ibat_high_thresh.trip_notify = bcl->ibat_low_thresh.trip_notify = bcl_periph_ibat_notify; bcl->ibat_high_thresh.trip_data = bcl->ibat_low_thresh.trip_data = (void *) bcl; get_vdd_rstr_freq(bcl, ibat_node); bcl->bcl_p_freq_max = max(bcl->bcl_p_freq_max, bcl->thermal_freq_limit); bcl->btm_mode = BCL_MONITOR_DISABLED; bcl->bcl_monitor_type = BCL_IBAT_PERIPH_MONITOR_TYPE; snprintf(bcl->bcl_type, BCL_NAME_LENGTH, "%s", bcl_type[BCL_IBAT_PERIPH_MONITOR_TYPE]); ret = cpufreq_register_notifier(&bcl_cpufreq_notifier, CPUFREQ_POLICY_NOTIFIER); if (ret) pr_err("Error with cpufreq register. err:%d\n", ret); ibat_probe_exit: if (ret && ret != -EPROBE_DEFER) dev_info(bcl->dev, "%s:%s Error reading key:%s. ret = %d\n", KBUILD_MODNAME, __func__, key, ret); return ret; } static int probe_btm_properties(struct bcl_context *bcl) { int ret = 0, curr_ua = 0; Loading Loading @@ -1249,7 +1425,7 @@ static int probe_btm_properties(struct bcl_context *bcl) goto btm_probe_exit; } get_vdd_rstr_freq(bcl, ibat_node); bcl->btm_freq_max = max(bcl->btm_freq_max, bcl->btm_freq_limit); bcl->btm_freq_max = max(bcl->btm_freq_max, bcl->thermal_freq_limit); bcl->btm_mode = BCL_MONITOR_DISABLED; bcl->bcl_monitor_type = BCL_IBAT_MONITOR_TYPE; Loading Loading @@ -1300,7 +1476,12 @@ static int bcl_probe(struct platform_device *pdev) bcl_type[BCL_IAVAIL_MONITOR_TYPE]); bcl->bcl_poll_interval_msec = BCL_POLL_INTERVAL; if (of_property_read_bool(pdev->dev.of_node, "qcom,bcl-framework-interface")) ret = probe_bcl_periph_prop(bcl); else ret = probe_btm_properties(bcl); if (ret == -EPROBE_DEFER) return ret; Loading