Loading Documentation/devicetree/bindings/devfreq/arm-memlat-mon.txt 0 → 100644 +31 −0 Original line number Diff line number Diff line ARM CPU memory latency monitor device arm-memlat-mon is a device that represents the use of the PMU in ARM cores to measure the parameters for latency driven memory access patterns. Required properties: - compatible: Must be "qcom,arm-memlat-mon" - qcom,cpulist: List of CPU phandles to be monitored in a cluster - qcom,target-dev: The DT device that corresponds to this master port - qcom,core-dev-table: A mapping table of core frequency to a required bandwidth vote at the given core frequency. Optional properties: - qcom,cachemiss-ev: The cache miss event that this monitor is supposed to measure. Defaults to 0x17 if not specified. - qcom,inst-ev: The instruction count event that this monitor is supposed to measure. Defaults to 0x08 if not specified. Example: qcom,arm-memlat-mon { compatible = "qcom,arm-memlat-mon"; qcom,cpulist = <&CPU0 &CPU1>; qcom,target-dev = <&memlat0>; qcom,cachemiss-ev = <0x2A>; qcom,inst-ev = <0x08>; qcom,core-dev-table = < 300000 1525>, < 499200 3143>, < 1881600 5859>; }; Documentation/devicetree/bindings/devfreq/bimc-bwmon.txt +2 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,8 @@ can be used to measure the bandwidth of read/write traffic from the BIMC master ports. For example, the CPU subsystem sits on one BIMC master port. Required properties: - compatible: Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" - compatible: Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" or "qcom,bimc-bwmon3" - reg: Pairs of physical base addresses and region sizes of memory mapped registers. - reg-names: Names of the bases for the above registers. Expected Loading drivers/devfreq/bimc-bwmon.c +36 −4 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ struct bwmon_spec { bool wrap_on_thres; bool overflow; bool throt_adj; }; struct bwmon { Loading @@ -45,19 +46,24 @@ struct bwmon { const struct bwmon_spec *spec; struct device *dev; struct bw_hwmon hw; u32 throttle_adj; }; #define to_bwmon(ptr) container_of(ptr, struct bwmon, hw) #define ENABLE_MASK BIT(0) #define THROTTLE_MASK 0x1F #define THROTTLE_SHIFT 16 static DEFINE_SPINLOCK(glb_lock); static void mon_enable(struct bwmon *m) { writel_relaxed(0x1, MON_EN(m)); writel_relaxed((ENABLE_MASK | m->throttle_adj), MON_EN(m)); } static void mon_disable(struct bwmon *m) { writel_relaxed(0x0, MON_EN(m)); writel_relaxed(m->throttle_adj, MON_EN(m)); /* * mon_disable() and mon_irq_clear(), * If latter goes first and count happen to trigger irq, we would Loading Loading @@ -139,6 +145,26 @@ static void mon_irq_clear(struct bwmon *m) mb(); } static int mon_set_throttle_adj(struct bw_hwmon *hw, uint adj) { struct bwmon *m = to_bwmon(hw); if (adj > THROTTLE_MASK) return -EINVAL; adj = (adj & THROTTLE_MASK) << THROTTLE_SHIFT; m->throttle_adj = adj; return 0; } static u32 mon_get_throttle_adj(struct bw_hwmon *hw) { struct bwmon *m = to_bwmon(hw); return m->throttle_adj >> THROTTLE_SHIFT; } static void mon_set_limit(struct bwmon *m, u32 count) { writel_relaxed(count, MON_THRES(m)); Loading Loading @@ -318,13 +344,15 @@ static int resume_bw_hwmon(struct bw_hwmon *hw) /*************************************************************************/ static const struct bwmon_spec spec[] = { { .wrap_on_thres = true, .overflow = false }, { .wrap_on_thres = false, .overflow = true }, { .wrap_on_thres = true, .overflow = false, .throt_adj = false}, { .wrap_on_thres = false, .overflow = true, .throt_adj = false}, { .wrap_on_thres = false, .overflow = true, .throt_adj = true}, }; static const struct of_device_id bimc_bwmon_match_table[] = { { .compatible = "qcom,bimc-bwmon", .data = &spec[0] }, { .compatible = "qcom,bimc-bwmon2", .data = &spec[1] }, { .compatible = "qcom,bimc-bwmon3", .data = &spec[2] }, {} }; Loading Loading @@ -393,6 +421,10 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) m->hw.resume_hwmon = &resume_bw_hwmon; m->hw.get_bytes_and_clear = &get_bytes_and_clear; m->hw.set_thres = &set_thres; if (m->spec->throt_adj) { m->hw.set_throttle_adj = &mon_set_throttle_adj; m->hw.get_throttle_adj = &mon_get_throttle_adj; } ret = register_bw_hwmon(dev, &m->hw); if (ret) { Loading drivers/devfreq/devfreq_simple_dev.c +14 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2015, 2019, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "devfreq-simple-dev: " fmt Loading Loading @@ -147,12 +147,23 @@ static int devfreq_clock_probe(struct platform_device *pdev) if (of_property_read_string(dev->of_node, "governor", &gov_name)) gov_name = "performance"; if (of_property_read_bool(dev->of_node, "qcom,prepare-clk")) { ret = clk_prepare(d->clk); if (ret) return ret; } d->df = devfreq_add_device(dev, p, gov_name, NULL); if (IS_ERR(d->df)) return PTR_ERR_OR_ZERO(d->df); if (IS_ERR(d->df)) { ret = PTR_ERR_OR_ZERO(d->df); goto add_err; } return 0; add_err: if (of_property_read_bool(dev->of_node, "qcom,prepare-clk")) clk_unprepare(d->clk); return ret; } static int devfreq_clock_remove(struct platform_device *pdev) Loading drivers/devfreq/governor_bw_hwmon.c +41 −0 Original line number Diff line number Diff line Loading @@ -651,6 +651,46 @@ static int devfreq_bw_hwmon_get_freq(struct devfreq *df, return 0; } static ssize_t throttle_adj_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct devfreq *df = to_devfreq(dev); struct hwmon_node *node = df->data; int ret; unsigned int val; if (!node->hw->set_throttle_adj) return -EPERM; ret = kstrtouint(buf, 10, &val); if (ret) return ret; ret = node->hw->set_throttle_adj(node->hw, val); if (!ret) return count; else return ret; } static ssize_t throttle_adj_show(struct device *dev, struct device_attribute *attr, char *buf) { struct devfreq *df = to_devfreq(dev); struct hwmon_node *node = df->data; unsigned int val; if (!node->hw->get_throttle_adj) val = 0; else val = node->hw->get_throttle_adj(node->hw); return snprintf(buf, PAGE_SIZE, "%u\n", val); } static DEVICE_ATTR_RW(throttle_adj); gov_attr(guard_band_mbps, 0U, 2000U); gov_attr(decay_rate, 0U, 100U); gov_attr(io_percent, 1U, 100U); Loading Loading @@ -681,6 +721,7 @@ static struct attribute *dev_attr[] = { &dev_attr_hyst_length.attr, &dev_attr_idle_mbps.attr, &dev_attr_mbps_zones.attr, &dev_attr_throttle_adj.attr, NULL, }; Loading Loading
Documentation/devicetree/bindings/devfreq/arm-memlat-mon.txt 0 → 100644 +31 −0 Original line number Diff line number Diff line ARM CPU memory latency monitor device arm-memlat-mon is a device that represents the use of the PMU in ARM cores to measure the parameters for latency driven memory access patterns. Required properties: - compatible: Must be "qcom,arm-memlat-mon" - qcom,cpulist: List of CPU phandles to be monitored in a cluster - qcom,target-dev: The DT device that corresponds to this master port - qcom,core-dev-table: A mapping table of core frequency to a required bandwidth vote at the given core frequency. Optional properties: - qcom,cachemiss-ev: The cache miss event that this monitor is supposed to measure. Defaults to 0x17 if not specified. - qcom,inst-ev: The instruction count event that this monitor is supposed to measure. Defaults to 0x08 if not specified. Example: qcom,arm-memlat-mon { compatible = "qcom,arm-memlat-mon"; qcom,cpulist = <&CPU0 &CPU1>; qcom,target-dev = <&memlat0>; qcom,cachemiss-ev = <0x2A>; qcom,inst-ev = <0x08>; qcom,core-dev-table = < 300000 1525>, < 499200 3143>, < 1881600 5859>; };
Documentation/devicetree/bindings/devfreq/bimc-bwmon.txt +2 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,8 @@ can be used to measure the bandwidth of read/write traffic from the BIMC master ports. For example, the CPU subsystem sits on one BIMC master port. Required properties: - compatible: Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" - compatible: Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" or "qcom,bimc-bwmon3" - reg: Pairs of physical base addresses and region sizes of memory mapped registers. - reg-names: Names of the bases for the above registers. Expected Loading
drivers/devfreq/bimc-bwmon.c +36 −4 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ struct bwmon_spec { bool wrap_on_thres; bool overflow; bool throt_adj; }; struct bwmon { Loading @@ -45,19 +46,24 @@ struct bwmon { const struct bwmon_spec *spec; struct device *dev; struct bw_hwmon hw; u32 throttle_adj; }; #define to_bwmon(ptr) container_of(ptr, struct bwmon, hw) #define ENABLE_MASK BIT(0) #define THROTTLE_MASK 0x1F #define THROTTLE_SHIFT 16 static DEFINE_SPINLOCK(glb_lock); static void mon_enable(struct bwmon *m) { writel_relaxed(0x1, MON_EN(m)); writel_relaxed((ENABLE_MASK | m->throttle_adj), MON_EN(m)); } static void mon_disable(struct bwmon *m) { writel_relaxed(0x0, MON_EN(m)); writel_relaxed(m->throttle_adj, MON_EN(m)); /* * mon_disable() and mon_irq_clear(), * If latter goes first and count happen to trigger irq, we would Loading Loading @@ -139,6 +145,26 @@ static void mon_irq_clear(struct bwmon *m) mb(); } static int mon_set_throttle_adj(struct bw_hwmon *hw, uint adj) { struct bwmon *m = to_bwmon(hw); if (adj > THROTTLE_MASK) return -EINVAL; adj = (adj & THROTTLE_MASK) << THROTTLE_SHIFT; m->throttle_adj = adj; return 0; } static u32 mon_get_throttle_adj(struct bw_hwmon *hw) { struct bwmon *m = to_bwmon(hw); return m->throttle_adj >> THROTTLE_SHIFT; } static void mon_set_limit(struct bwmon *m, u32 count) { writel_relaxed(count, MON_THRES(m)); Loading Loading @@ -318,13 +344,15 @@ static int resume_bw_hwmon(struct bw_hwmon *hw) /*************************************************************************/ static const struct bwmon_spec spec[] = { { .wrap_on_thres = true, .overflow = false }, { .wrap_on_thres = false, .overflow = true }, { .wrap_on_thres = true, .overflow = false, .throt_adj = false}, { .wrap_on_thres = false, .overflow = true, .throt_adj = false}, { .wrap_on_thres = false, .overflow = true, .throt_adj = true}, }; static const struct of_device_id bimc_bwmon_match_table[] = { { .compatible = "qcom,bimc-bwmon", .data = &spec[0] }, { .compatible = "qcom,bimc-bwmon2", .data = &spec[1] }, { .compatible = "qcom,bimc-bwmon3", .data = &spec[2] }, {} }; Loading Loading @@ -393,6 +421,10 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) m->hw.resume_hwmon = &resume_bw_hwmon; m->hw.get_bytes_and_clear = &get_bytes_and_clear; m->hw.set_thres = &set_thres; if (m->spec->throt_adj) { m->hw.set_throttle_adj = &mon_set_throttle_adj; m->hw.get_throttle_adj = &mon_get_throttle_adj; } ret = register_bw_hwmon(dev, &m->hw); if (ret) { Loading
drivers/devfreq/devfreq_simple_dev.c +14 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014, The Linux Foundation. All rights reserved. * Copyright (c) 2014-2015, 2019, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "devfreq-simple-dev: " fmt Loading Loading @@ -147,12 +147,23 @@ static int devfreq_clock_probe(struct platform_device *pdev) if (of_property_read_string(dev->of_node, "governor", &gov_name)) gov_name = "performance"; if (of_property_read_bool(dev->of_node, "qcom,prepare-clk")) { ret = clk_prepare(d->clk); if (ret) return ret; } d->df = devfreq_add_device(dev, p, gov_name, NULL); if (IS_ERR(d->df)) return PTR_ERR_OR_ZERO(d->df); if (IS_ERR(d->df)) { ret = PTR_ERR_OR_ZERO(d->df); goto add_err; } return 0; add_err: if (of_property_read_bool(dev->of_node, "qcom,prepare-clk")) clk_unprepare(d->clk); return ret; } static int devfreq_clock_remove(struct platform_device *pdev) Loading
drivers/devfreq/governor_bw_hwmon.c +41 −0 Original line number Diff line number Diff line Loading @@ -651,6 +651,46 @@ static int devfreq_bw_hwmon_get_freq(struct devfreq *df, return 0; } static ssize_t throttle_adj_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct devfreq *df = to_devfreq(dev); struct hwmon_node *node = df->data; int ret; unsigned int val; if (!node->hw->set_throttle_adj) return -EPERM; ret = kstrtouint(buf, 10, &val); if (ret) return ret; ret = node->hw->set_throttle_adj(node->hw, val); if (!ret) return count; else return ret; } static ssize_t throttle_adj_show(struct device *dev, struct device_attribute *attr, char *buf) { struct devfreq *df = to_devfreq(dev); struct hwmon_node *node = df->data; unsigned int val; if (!node->hw->get_throttle_adj) val = 0; else val = node->hw->get_throttle_adj(node->hw); return snprintf(buf, PAGE_SIZE, "%u\n", val); } static DEVICE_ATTR_RW(throttle_adj); gov_attr(guard_band_mbps, 0U, 2000U); gov_attr(decay_rate, 0U, 100U); gov_attr(io_percent, 1U, 100U); Loading Loading @@ -681,6 +721,7 @@ static struct attribute *dev_attr[] = { &dev_attr_hyst_length.attr, &dev_attr_idle_mbps.attr, &dev_attr_mbps_zones.attr, &dev_attr_throttle_adj.attr, NULL, }; Loading