Loading Documentation/devicetree/bindings/devfreq/bimc-bwmon.txt +8 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ Required properties: - qcom,target-dev: The DT device that corresponds to this master port - qcom,hw-timer-hz: Hardware sampling rate in Hz. This field must be specified for "qcom,bimc-bwmon4" Optional properties: - qcom,byte-mid-match: Byte count MID match value - qcom,byte-mid-mask: Byte count MID mask value - qcom,count-unit: Number of bytes monitor counts in Example: qcom,cpu-bwmon { compatible = "qcom,bimc-bwmon"; Loading @@ -26,4 +31,7 @@ Example: qcom,mport = <0>; qcom,target-dev = <&cpubw>; qcom,hw-timer-hz = <19200000>; qcom,byte-mid-match = <0x1e00>; qcom,byte-mid-mask = <0x1e00>; qcom,count-unit = <0x100000>; }; drivers/devfreq/bimc-bwmon.c +57 −11 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/spinlock.h> #include <linux/log2.h> #include <linux/sizes.h> #include "governor_bw_hwmon.h" #define GLB_INT_STATUS(m) ((m)->global_base + 0x100) Loading Loading @@ -56,6 +58,8 @@ #define MON3_INT_STATUS_MASK 0x0F #define MON3_EN(m) ((m)->base + 0x10) #define MON3_CLEAR(m) ((m)->base + 0x14) #define MON3_MASK(m) ((m)->base + 0x18) #define MON3_MATCH(m) ((m)->base + 0x1C) #define MON3_SW(m) ((m)->base + 0x20) #define MON3_THRES_HI(m) ((m)->base + 0x24) #define MON3_THRES_MED(m) ((m)->base + 0x28) Loading Loading @@ -94,6 +98,10 @@ struct bwmon { u32 throttle_adj; u32 sample_size_ms; u32 intr_status; u8 count_shift; u32 thres_lim; u32 byte_mask; u32 byte_match; }; #define to_bwmon(ptr) container_of(ptr, struct bwmon, hw) Loading Loading @@ -406,11 +414,18 @@ static u32 calc_zone_counts(struct bw_hwmon *hw) return zone_counts; } static unsigned int mbps_to_mb(unsigned long mbps, unsigned int ms) #define MB_SHIFT 20 static u32 mbps_to_count(unsigned long mbps, unsigned int ms, u8 shift) { mbps *= ms; mbps = DIV_ROUND_UP(mbps, MSEC_PER_SEC); return mbps; if (shift > MB_SHIFT) mbps >>= shift - MB_SHIFT; else mbps <<= MB_SHIFT - shift; return DIV_ROUND_UP(mbps, MSEC_PER_SEC); } /* Loading @@ -418,9 +433,10 @@ static unsigned int mbps_to_mb(unsigned long mbps, unsigned int ms) * Zone 0: byte count < THRES_LO * Zone 1: THRES_LO < byte count < THRES_MED * Zone 2: THRES_MED < byte count < THRES_HI * Zone 3: byte count > THRES_HI * Zone 3: THRES_LIM > byte count > THRES_HI */ #define THRES_LIM 0x7FFU #define THRES_LIM(shift) (0xFFFFFFFF >> shift) static __always_inline void set_zone_thres(struct bwmon *m, unsigned int sample_ms, enum mon_reg_type type) Loading @@ -429,14 +445,14 @@ void set_zone_thres(struct bwmon *m, unsigned int sample_ms, u32 hi, med, lo; u32 zone_cnt_thres = calc_zone_counts(hw); hi = mbps_to_mb(hw->up_wake_mbps, sample_ms); med = mbps_to_mb(hw->down_wake_mbps, sample_ms); hi = mbps_to_count(hw->up_wake_mbps, sample_ms, m->count_shift); med = mbps_to_count(hw->down_wake_mbps, sample_ms, m->count_shift); lo = 0; if (unlikely((hi > THRES_LIM) || (med > hi) || (lo > med))) { if (unlikely((hi > m->thres_lim) || (med > hi) || (lo > med))) { pr_warn("Zone thres larger than hw limit: hi:%u med:%u lo:%u\n", hi, med, lo); hi = min(hi, THRES_LIM); hi = min(hi, m->thres_lim); med = min(med, hi - 1); lo = min(lo, med-1); } Loading Loading @@ -568,7 +584,7 @@ unsigned long mon_get_zone_stats(struct bwmon *m, enum mon_reg_type type) zone = get_zone(m, type); count = get_zone_count(m, zone, type); count *= SZ_1M; count <<= m->count_shift; dev_dbg(m->dev, "Zone%d Max byte count: %08lx\n", zone, count); Loading Loading @@ -723,6 +739,25 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev) return IRQ_HANDLED; } static __always_inline void mon_set_byte_count_filter(struct bwmon *m, enum mon_reg_type type) { if (!m->byte_mask) return; switch (type) { case MON1: case MON2: writel_relaxed(m->byte_mask, MON_MASK(m)); writel_relaxed(m->byte_match, MON_MATCH(m)); break; case MON3: writel_relaxed(m->byte_mask, MON3_MASK(m)); writel_relaxed(m->byte_match, MON3_MATCH(m)); break; } } static __always_inline int __start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps, enum mon_reg_type type) { Loading Loading @@ -774,6 +809,7 @@ static __always_inline int __start_bw_hwmon(struct bw_hwmon *hw, writel_relaxed(zone_actions, MON3_ZONE_ACTIONS(m)); } mon_set_byte_count_filter(m, type); mon_irq_clear(m, type); mon_irq_enable(m, type); mon_enable(m, type); Loading Loading @@ -960,7 +996,7 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) struct resource *res; struct bwmon *m; int ret; u32 data; u32 data, count_unit; m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL); if (!m) Loading Loading @@ -1025,6 +1061,11 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) } } if (of_property_read_u32(dev->of_node, "qcom,count-unit", &count_unit)) count_unit = SZ_1M; m->count_shift = order_base_2(count_unit); m->thres_lim = THRES_LIM(m->count_shift); switch (m->spec->reg_type) { case MON3: m->hw.start_hwmon = start_bw_hwmon3; Loading Loading @@ -1052,6 +1093,11 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) break; } of_property_read_u32(dev->of_node, "qcom,byte-mid-match", &m->byte_match); of_property_read_u32(dev->of_node, "qcom,byte-mid-mask", &m->byte_mask); if (m->spec->throt_adj) { m->hw.set_throttle_adj = mon_set_throttle_adj; m->hw.get_throttle_adj = mon_get_throttle_adj; Loading Loading
Documentation/devicetree/bindings/devfreq/bimc-bwmon.txt +8 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,11 @@ Required properties: - qcom,target-dev: The DT device that corresponds to this master port - qcom,hw-timer-hz: Hardware sampling rate in Hz. This field must be specified for "qcom,bimc-bwmon4" Optional properties: - qcom,byte-mid-match: Byte count MID match value - qcom,byte-mid-mask: Byte count MID mask value - qcom,count-unit: Number of bytes monitor counts in Example: qcom,cpu-bwmon { compatible = "qcom,bimc-bwmon"; Loading @@ -26,4 +31,7 @@ Example: qcom,mport = <0>; qcom,target-dev = <&cpubw>; qcom,hw-timer-hz = <19200000>; qcom,byte-mid-match = <0x1e00>; qcom,byte-mid-mask = <0x1e00>; qcom,count-unit = <0x100000>; };
drivers/devfreq/bimc-bwmon.c +57 −11 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/spinlock.h> #include <linux/log2.h> #include <linux/sizes.h> #include "governor_bw_hwmon.h" #define GLB_INT_STATUS(m) ((m)->global_base + 0x100) Loading Loading @@ -56,6 +58,8 @@ #define MON3_INT_STATUS_MASK 0x0F #define MON3_EN(m) ((m)->base + 0x10) #define MON3_CLEAR(m) ((m)->base + 0x14) #define MON3_MASK(m) ((m)->base + 0x18) #define MON3_MATCH(m) ((m)->base + 0x1C) #define MON3_SW(m) ((m)->base + 0x20) #define MON3_THRES_HI(m) ((m)->base + 0x24) #define MON3_THRES_MED(m) ((m)->base + 0x28) Loading Loading @@ -94,6 +98,10 @@ struct bwmon { u32 throttle_adj; u32 sample_size_ms; u32 intr_status; u8 count_shift; u32 thres_lim; u32 byte_mask; u32 byte_match; }; #define to_bwmon(ptr) container_of(ptr, struct bwmon, hw) Loading Loading @@ -406,11 +414,18 @@ static u32 calc_zone_counts(struct bw_hwmon *hw) return zone_counts; } static unsigned int mbps_to_mb(unsigned long mbps, unsigned int ms) #define MB_SHIFT 20 static u32 mbps_to_count(unsigned long mbps, unsigned int ms, u8 shift) { mbps *= ms; mbps = DIV_ROUND_UP(mbps, MSEC_PER_SEC); return mbps; if (shift > MB_SHIFT) mbps >>= shift - MB_SHIFT; else mbps <<= MB_SHIFT - shift; return DIV_ROUND_UP(mbps, MSEC_PER_SEC); } /* Loading @@ -418,9 +433,10 @@ static unsigned int mbps_to_mb(unsigned long mbps, unsigned int ms) * Zone 0: byte count < THRES_LO * Zone 1: THRES_LO < byte count < THRES_MED * Zone 2: THRES_MED < byte count < THRES_HI * Zone 3: byte count > THRES_HI * Zone 3: THRES_LIM > byte count > THRES_HI */ #define THRES_LIM 0x7FFU #define THRES_LIM(shift) (0xFFFFFFFF >> shift) static __always_inline void set_zone_thres(struct bwmon *m, unsigned int sample_ms, enum mon_reg_type type) Loading @@ -429,14 +445,14 @@ void set_zone_thres(struct bwmon *m, unsigned int sample_ms, u32 hi, med, lo; u32 zone_cnt_thres = calc_zone_counts(hw); hi = mbps_to_mb(hw->up_wake_mbps, sample_ms); med = mbps_to_mb(hw->down_wake_mbps, sample_ms); hi = mbps_to_count(hw->up_wake_mbps, sample_ms, m->count_shift); med = mbps_to_count(hw->down_wake_mbps, sample_ms, m->count_shift); lo = 0; if (unlikely((hi > THRES_LIM) || (med > hi) || (lo > med))) { if (unlikely((hi > m->thres_lim) || (med > hi) || (lo > med))) { pr_warn("Zone thres larger than hw limit: hi:%u med:%u lo:%u\n", hi, med, lo); hi = min(hi, THRES_LIM); hi = min(hi, m->thres_lim); med = min(med, hi - 1); lo = min(lo, med-1); } Loading Loading @@ -568,7 +584,7 @@ unsigned long mon_get_zone_stats(struct bwmon *m, enum mon_reg_type type) zone = get_zone(m, type); count = get_zone_count(m, zone, type); count *= SZ_1M; count <<= m->count_shift; dev_dbg(m->dev, "Zone%d Max byte count: %08lx\n", zone, count); Loading Loading @@ -723,6 +739,25 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev) return IRQ_HANDLED; } static __always_inline void mon_set_byte_count_filter(struct bwmon *m, enum mon_reg_type type) { if (!m->byte_mask) return; switch (type) { case MON1: case MON2: writel_relaxed(m->byte_mask, MON_MASK(m)); writel_relaxed(m->byte_match, MON_MATCH(m)); break; case MON3: writel_relaxed(m->byte_mask, MON3_MASK(m)); writel_relaxed(m->byte_match, MON3_MATCH(m)); break; } } static __always_inline int __start_bw_hwmon(struct bw_hwmon *hw, unsigned long mbps, enum mon_reg_type type) { Loading Loading @@ -774,6 +809,7 @@ static __always_inline int __start_bw_hwmon(struct bw_hwmon *hw, writel_relaxed(zone_actions, MON3_ZONE_ACTIONS(m)); } mon_set_byte_count_filter(m, type); mon_irq_clear(m, type); mon_irq_enable(m, type); mon_enable(m, type); Loading Loading @@ -960,7 +996,7 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) struct resource *res; struct bwmon *m; int ret; u32 data; u32 data, count_unit; m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL); if (!m) Loading Loading @@ -1025,6 +1061,11 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) } } if (of_property_read_u32(dev->of_node, "qcom,count-unit", &count_unit)) count_unit = SZ_1M; m->count_shift = order_base_2(count_unit); m->thres_lim = THRES_LIM(m->count_shift); switch (m->spec->reg_type) { case MON3: m->hw.start_hwmon = start_bw_hwmon3; Loading Loading @@ -1052,6 +1093,11 @@ static int bimc_bwmon_driver_probe(struct platform_device *pdev) break; } of_property_read_u32(dev->of_node, "qcom,byte-mid-match", &m->byte_match); of_property_read_u32(dev->of_node, "qcom,byte-mid-mask", &m->byte_mask); if (m->spec->throt_adj) { m->hw.set_throttle_adj = mon_set_throttle_adj; m->hw.get_throttle_adj = mon_get_throttle_adj; Loading