Loading drivers/devfreq/devfreq_icc.c +108 −5 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2014, 2018, 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2014, 2018-2019, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "devfreq-icc: " fmt Loading @@ -20,6 +20,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/of_fdt.h> #include <linux/of_address.h> #include <trace/events/power.h> #include <linux/platform_device.h> #include <linux/interconnect.h> Loading @@ -33,22 +34,33 @@ struct dev_data { u32 cur_ab; u32 cur_ib; unsigned long gov_ab; bool is_l3; struct devfreq *df; struct devfreq_dev_profile dp; }; #define MAX_L3_ENTRIES 40U static unsigned long l3_freqs[MAX_L3_ENTRIES]; static DEFINE_MUTEX(l3_freqs_lock); static bool use_cached_l3_freqs; static int set_bw(struct device *dev, u32 new_ib, u32 new_ab) { struct dev_data *d = dev_get_drvdata(dev); int ret; u32 icc_ib = new_ib, icc_ab = new_ab; if (d->cur_ib == new_ib && d->cur_ab == new_ab) return 0; dev_dbg(dev, "BW MBps: AB: %d IB: %d\n", new_ab, new_ib); if (!d->is_l3) { icc_ib = Bps_to_icc(new_ib * MBYTE); icc_ab = Bps_to_icc(new_ab * MBYTE); } dev_dbg(dev, "ICC BW: AB: %u IB: %u\n", icc_ab, icc_ib); ret = icc_set_bw(d->icc_path, Bps_to_icc(new_ab * MBYTE), Bps_to_icc(new_ib * MBYTE)); ret = icc_set_bw(d->icc_path, icc_ab, icc_ib); if (ret < 0) { dev_err(dev, "icc set bandwidth request failed (%d)\n", ret); } else { Loading Loading @@ -80,6 +92,83 @@ static int icc_get_dev_status(struct device *dev, return 0; } #define INIT_HZ 300000000UL #define XO_HZ 19200000UL #define FTBL_ROW_SIZE 4 #define SRC_MASK GENMASK(31, 30) #define SRC_SHIFT 30 #define MULT_MASK GENMASK(7, 0) static int populate_l3_opp_table(struct device *dev) { int idx, ret; u32 data, src, mult, i; unsigned long freq, prev_freq = 0; struct resource res; void __iomem *ftbl_base; unsigned int ftbl_row_size = FTBL_ROW_SIZE; idx = of_property_match_string(dev->of_node, "reg-names", "ftbl-base"); if (idx < 0) { dev_err(dev, "Unable to find ftbl-base: %d\n", idx); return -EINVAL; } ret = of_address_to_resource(dev->of_node, idx, &res); if (ret < 0) { dev_err(dev, "Unable to get resource from address: %d\n", ret); return -EINVAL; } ftbl_base = devm_ioremap(dev, res.start, resource_size(&res)); if (!ftbl_base) { dev_err(dev, "Unable to map ftbl-base!\n"); return -ENOMEM; } of_property_read_u32(dev->of_node, "qcom,ftbl-row-size", &ftbl_row_size); for (i = 0; i < MAX_L3_ENTRIES; i++) { data = readl_relaxed(ftbl_base + i * ftbl_row_size); src = ((data & SRC_MASK) >> SRC_SHIFT); mult = (data & MULT_MASK); freq = src ? XO_HZ * mult : INIT_HZ; /* Two of the same frequencies means end of table */ if (i > 0 && prev_freq == freq) break; dev_pm_opp_add(dev, freq, 0); l3_freqs[i] = freq; prev_freq = freq; } devm_iounmap(dev, ftbl_base); use_cached_l3_freqs = true; return 0; } static int copy_l3_opp_table(struct device *dev) { int idx; for (idx = 0; idx < MAX_L3_ENTRIES; idx++) { if (l3_freqs[idx]) dev_pm_opp_add(dev, l3_freqs[idx], 0); else break; } if (!idx) { dev_err(dev, "No L3 frequencies copied for device!\n"); return -EINVAL; } return 0; } #define PROP_ACTIVE "qcom,active-only" #define ACTIVE_ONLY_TAG 0x3 Loading Loading @@ -111,7 +200,20 @@ int devfreq_add_icc(struct device *dev) } } if (of_device_is_compatible(dev->of_node, "qcom,devfreq-icc-l3")) { mutex_lock(&l3_freqs_lock); if (use_cached_l3_freqs) { mutex_unlock(&l3_freqs_lock); ret = copy_l3_opp_table(dev); } else { ret = populate_l3_opp_table(dev); mutex_unlock(&l3_freqs_lock); } d->is_l3 = true; } else { ret = dev_pm_opp_of_add_table(dev); d->is_l3 = false; } if (ret < 0) dev_err(dev, "Couldn't parse OPP table:%d\n", ret); Loading Loading @@ -172,6 +274,7 @@ static int devfreq_icc_remove(struct platform_device *pdev) } static const struct of_device_id devfreq_icc_match_table[] = { { .compatible = "qcom,devfreq-icc-l3" }, { .compatible = "qcom,devfreq-icc-llcc" }, { .compatible = "qcom,devfreq-icc-ddr" }, { .compatible = "qcom,devfreq-icc" }, Loading drivers/devfreq/governor_memlat.c +3 −0 Original line number Diff line number Diff line Loading @@ -489,6 +489,9 @@ static struct memlat_node *register_common(struct device *dev, if (hw->get_child_of_node) of_node = hw->get_child_of_node(dev); if (of_parse_phandle(of_node, "qcom,core-dev-table", 0)) of_node = of_parse_phandle(of_node, "qcom,core-dev-table", 0); hw->freq_map = init_core_dev_map(dev, of_node, "qcom,core-dev-table"); if (!hw->freq_map) { Loading Loading
drivers/devfreq/devfreq_icc.c +108 −5 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2014, 2018, 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2014, 2018-2019, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "devfreq-icc: " fmt Loading @@ -20,6 +20,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/of_fdt.h> #include <linux/of_address.h> #include <trace/events/power.h> #include <linux/platform_device.h> #include <linux/interconnect.h> Loading @@ -33,22 +34,33 @@ struct dev_data { u32 cur_ab; u32 cur_ib; unsigned long gov_ab; bool is_l3; struct devfreq *df; struct devfreq_dev_profile dp; }; #define MAX_L3_ENTRIES 40U static unsigned long l3_freqs[MAX_L3_ENTRIES]; static DEFINE_MUTEX(l3_freqs_lock); static bool use_cached_l3_freqs; static int set_bw(struct device *dev, u32 new_ib, u32 new_ab) { struct dev_data *d = dev_get_drvdata(dev); int ret; u32 icc_ib = new_ib, icc_ab = new_ab; if (d->cur_ib == new_ib && d->cur_ab == new_ab) return 0; dev_dbg(dev, "BW MBps: AB: %d IB: %d\n", new_ab, new_ib); if (!d->is_l3) { icc_ib = Bps_to_icc(new_ib * MBYTE); icc_ab = Bps_to_icc(new_ab * MBYTE); } dev_dbg(dev, "ICC BW: AB: %u IB: %u\n", icc_ab, icc_ib); ret = icc_set_bw(d->icc_path, Bps_to_icc(new_ab * MBYTE), Bps_to_icc(new_ib * MBYTE)); ret = icc_set_bw(d->icc_path, icc_ab, icc_ib); if (ret < 0) { dev_err(dev, "icc set bandwidth request failed (%d)\n", ret); } else { Loading Loading @@ -80,6 +92,83 @@ static int icc_get_dev_status(struct device *dev, return 0; } #define INIT_HZ 300000000UL #define XO_HZ 19200000UL #define FTBL_ROW_SIZE 4 #define SRC_MASK GENMASK(31, 30) #define SRC_SHIFT 30 #define MULT_MASK GENMASK(7, 0) static int populate_l3_opp_table(struct device *dev) { int idx, ret; u32 data, src, mult, i; unsigned long freq, prev_freq = 0; struct resource res; void __iomem *ftbl_base; unsigned int ftbl_row_size = FTBL_ROW_SIZE; idx = of_property_match_string(dev->of_node, "reg-names", "ftbl-base"); if (idx < 0) { dev_err(dev, "Unable to find ftbl-base: %d\n", idx); return -EINVAL; } ret = of_address_to_resource(dev->of_node, idx, &res); if (ret < 0) { dev_err(dev, "Unable to get resource from address: %d\n", ret); return -EINVAL; } ftbl_base = devm_ioremap(dev, res.start, resource_size(&res)); if (!ftbl_base) { dev_err(dev, "Unable to map ftbl-base!\n"); return -ENOMEM; } of_property_read_u32(dev->of_node, "qcom,ftbl-row-size", &ftbl_row_size); for (i = 0; i < MAX_L3_ENTRIES; i++) { data = readl_relaxed(ftbl_base + i * ftbl_row_size); src = ((data & SRC_MASK) >> SRC_SHIFT); mult = (data & MULT_MASK); freq = src ? XO_HZ * mult : INIT_HZ; /* Two of the same frequencies means end of table */ if (i > 0 && prev_freq == freq) break; dev_pm_opp_add(dev, freq, 0); l3_freqs[i] = freq; prev_freq = freq; } devm_iounmap(dev, ftbl_base); use_cached_l3_freqs = true; return 0; } static int copy_l3_opp_table(struct device *dev) { int idx; for (idx = 0; idx < MAX_L3_ENTRIES; idx++) { if (l3_freqs[idx]) dev_pm_opp_add(dev, l3_freqs[idx], 0); else break; } if (!idx) { dev_err(dev, "No L3 frequencies copied for device!\n"); return -EINVAL; } return 0; } #define PROP_ACTIVE "qcom,active-only" #define ACTIVE_ONLY_TAG 0x3 Loading Loading @@ -111,7 +200,20 @@ int devfreq_add_icc(struct device *dev) } } if (of_device_is_compatible(dev->of_node, "qcom,devfreq-icc-l3")) { mutex_lock(&l3_freqs_lock); if (use_cached_l3_freqs) { mutex_unlock(&l3_freqs_lock); ret = copy_l3_opp_table(dev); } else { ret = populate_l3_opp_table(dev); mutex_unlock(&l3_freqs_lock); } d->is_l3 = true; } else { ret = dev_pm_opp_of_add_table(dev); d->is_l3 = false; } if (ret < 0) dev_err(dev, "Couldn't parse OPP table:%d\n", ret); Loading Loading @@ -172,6 +274,7 @@ static int devfreq_icc_remove(struct platform_device *pdev) } static const struct of_device_id devfreq_icc_match_table[] = { { .compatible = "qcom,devfreq-icc-l3" }, { .compatible = "qcom,devfreq-icc-llcc" }, { .compatible = "qcom,devfreq-icc-ddr" }, { .compatible = "qcom,devfreq-icc" }, Loading
drivers/devfreq/governor_memlat.c +3 −0 Original line number Diff line number Diff line Loading @@ -489,6 +489,9 @@ static struct memlat_node *register_common(struct device *dev, if (hw->get_child_of_node) of_node = hw->get_child_of_node(dev); if (of_parse_phandle(of_node, "qcom,core-dev-table", 0)) of_node = of_parse_phandle(of_node, "qcom,core-dev-table", 0); hw->freq_map = init_core_dev_map(dev, of_node, "qcom,core-dev-table"); if (!hw->freq_map) { Loading