Loading Documentation/devicetree/bindings/devfreq/bimc-bwmon.txt +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ 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" - compatible: Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" - 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 +48 −13 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/spinlock.h> #include "governor_bw_hwmon.h" Loading @@ -39,11 +40,17 @@ #define MON_MASK(m) ((m)->base + 0x298) #define MON_MATCH(m) ((m)->base + 0x29C) struct bwmon_spec { bool wrap_on_thres; bool overflow; }; struct bwmon { void __iomem *base; void __iomem *global_base; unsigned int mport; unsigned int irq; const struct bwmon_spec *spec; struct device *dev; struct bw_hwmon hw; }; Loading Loading @@ -102,7 +109,7 @@ static void mon_irq_disable(struct bwmon *m) writel_relaxed(val, MON_INT_EN(m)); } static int mon_irq_status(struct bwmon *m) static unsigned int mon_irq_status(struct bwmon *m) { u32 mval; Loading @@ -111,12 +118,12 @@ static int mon_irq_status(struct bwmon *m) dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval, readl_relaxed(GLB_INT_STATUS(m))); return mval & 0x1; return mval; } static void mon_irq_clear(struct bwmon *m) { writel_relaxed(0x1, MON_INT_CLR(m)); writel_relaxed(0x3, MON_INT_CLR(m)); mb(); writel_relaxed(1 << m->mport, GLB_INT_CLR(m)); mb(); Loading @@ -133,14 +140,22 @@ static u32 mon_get_limit(struct bwmon *m) return readl_relaxed(MON_THRES(m)); } #define THRES_HIT(status) (status & BIT(0)) #define OVERFLOW(status) (status & BIT(1)) static unsigned long mon_get_count(struct bwmon *m) { unsigned long count; unsigned long count, status; count = readl_relaxed(MON_CNT(m)); status = mon_irq_status(m); dev_dbg(m->dev, "Counter: %08lx\n", count); if (mon_irq_status(m)) if (OVERFLOW(status) && m->spec->overflow) count += 0xFFFFFFFF; if (THRES_HIT(status) && m->spec->wrap_on_thres) count += mon_get_limit(m); dev_dbg(m->dev, "Actual Count: %08lx\n", count); return count; Loading Loading @@ -179,11 +194,17 @@ static unsigned long meas_bw_and_set_irq(struct bw_hwmon *hw, mbps = mon_get_count(m); mbps = bytes_to_mbps(mbps, us); /* * The fudging of mbps when calculating limit is to workaround a HW * design issue. Needs further tuning. * If the counter wraps on thres, don't set the thres too low. * Setting it too low runs the risk of the counter wrapping around * multiple times before the IRQ is processed. */ if (likely(!m->spec->wrap_on_thres)) limit = mbps_to_bytes(mbps, sample_ms, tol); else limit = mbps_to_bytes(max(mbps, 400UL), sample_ms, tol); mon_set_limit(m, limit); mon_clear(m); Loading Loading @@ -278,11 +299,23 @@ 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 }, }; static const struct of_device_id bimc_bwmon_match_table[] = { { .compatible = "qcom,bimc-bwmon", .data = &spec[0] }, { .compatible = "qcom,bimc-bwmon2", .data = &spec[1] }, {} }; static int bimc_bwmon_driver_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct bwmon *m; const struct of_device_id *id; int ret; u32 data; Loading @@ -298,6 +331,13 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) } m->mport = data; id = of_match_device(bimc_bwmon_match_table, dev); if (!id) { dev_err(dev, "Unknown device type!\n"); return -ENODEV; } m->spec = id->data; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base"); if (!res) { dev_err(dev, "base not found!\n"); Loading Loading @@ -344,11 +384,6 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) return 0; } static const struct of_device_id bimc_bwmon_match_table[] = { { .compatible = "qcom,bimc-bwmon" }, {} }; static struct platform_driver bimc_bwmon_driver = { .probe = bimc_bwmon_driver_probe, .driver = { Loading Loading
Documentation/devicetree/bindings/devfreq/bimc-bwmon.txt +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ 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" - compatible: Must be "qcom,bimc-bwmon", "qcom,bimc-bwmon2" - 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 +48 −13 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/spinlock.h> #include "governor_bw_hwmon.h" Loading @@ -39,11 +40,17 @@ #define MON_MASK(m) ((m)->base + 0x298) #define MON_MATCH(m) ((m)->base + 0x29C) struct bwmon_spec { bool wrap_on_thres; bool overflow; }; struct bwmon { void __iomem *base; void __iomem *global_base; unsigned int mport; unsigned int irq; const struct bwmon_spec *spec; struct device *dev; struct bw_hwmon hw; }; Loading Loading @@ -102,7 +109,7 @@ static void mon_irq_disable(struct bwmon *m) writel_relaxed(val, MON_INT_EN(m)); } static int mon_irq_status(struct bwmon *m) static unsigned int mon_irq_status(struct bwmon *m) { u32 mval; Loading @@ -111,12 +118,12 @@ static int mon_irq_status(struct bwmon *m) dev_dbg(m->dev, "IRQ status p:%x, g:%x\n", mval, readl_relaxed(GLB_INT_STATUS(m))); return mval & 0x1; return mval; } static void mon_irq_clear(struct bwmon *m) { writel_relaxed(0x1, MON_INT_CLR(m)); writel_relaxed(0x3, MON_INT_CLR(m)); mb(); writel_relaxed(1 << m->mport, GLB_INT_CLR(m)); mb(); Loading @@ -133,14 +140,22 @@ static u32 mon_get_limit(struct bwmon *m) return readl_relaxed(MON_THRES(m)); } #define THRES_HIT(status) (status & BIT(0)) #define OVERFLOW(status) (status & BIT(1)) static unsigned long mon_get_count(struct bwmon *m) { unsigned long count; unsigned long count, status; count = readl_relaxed(MON_CNT(m)); status = mon_irq_status(m); dev_dbg(m->dev, "Counter: %08lx\n", count); if (mon_irq_status(m)) if (OVERFLOW(status) && m->spec->overflow) count += 0xFFFFFFFF; if (THRES_HIT(status) && m->spec->wrap_on_thres) count += mon_get_limit(m); dev_dbg(m->dev, "Actual Count: %08lx\n", count); return count; Loading Loading @@ -179,11 +194,17 @@ static unsigned long meas_bw_and_set_irq(struct bw_hwmon *hw, mbps = mon_get_count(m); mbps = bytes_to_mbps(mbps, us); /* * The fudging of mbps when calculating limit is to workaround a HW * design issue. Needs further tuning. * If the counter wraps on thres, don't set the thres too low. * Setting it too low runs the risk of the counter wrapping around * multiple times before the IRQ is processed. */ if (likely(!m->spec->wrap_on_thres)) limit = mbps_to_bytes(mbps, sample_ms, tol); else limit = mbps_to_bytes(max(mbps, 400UL), sample_ms, tol); mon_set_limit(m, limit); mon_clear(m); Loading Loading @@ -278,11 +299,23 @@ 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 }, }; static const struct of_device_id bimc_bwmon_match_table[] = { { .compatible = "qcom,bimc-bwmon", .data = &spec[0] }, { .compatible = "qcom,bimc-bwmon2", .data = &spec[1] }, {} }; static int bimc_bwmon_driver_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct bwmon *m; const struct of_device_id *id; int ret; u32 data; Loading @@ -298,6 +331,13 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) } m->mport = data; id = of_match_device(bimc_bwmon_match_table, dev); if (!id) { dev_err(dev, "Unknown device type!\n"); return -ENODEV; } m->spec = id->data; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base"); if (!res) { dev_err(dev, "base not found!\n"); Loading Loading @@ -344,11 +384,6 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) return 0; } static const struct of_device_id bimc_bwmon_match_table[] = { { .compatible = "qcom,bimc-bwmon" }, {} }; static struct platform_driver bimc_bwmon_driver = { .probe = bimc_bwmon_driver_probe, .driver = { Loading