Lines Matching +full:no +full:- +full:high +full:- +full:z

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2021-2022 Linaro Ltd
6 * previous work of Thara Gopinath and msm-4.9 downstream sources.
21 #include "trace_icc-bwmon.h"
25 * configurable thresholds (Low, Medium and High) gives four windows (called
53 * implementations to work, offset the global registers by -0x100 to avoid
57 #define BWMON_V4_GLOBAL_IRQ_CLEAR_845 (BWMON_V4_GLOBAL_IRQ_CLEAR - BWMON_V4_845_OFFSET)
58 #define BWMON_V4_GLOBAL_IRQ_ENABLE_845 (BWMON_V4_GLOBAL_IRQ_ENABLE - BWMON_V4_845_OFFSET)
91 * Actions to perform on some zone 'z' when current zone hits the threshold:
92 * Increment counter of zone 'z'
94 #define BWMON_ZONE_ACTIONS_INCREMENT(z) (0x2 << ((z) * 2)) argument
95 /* Clear counter of zone 'z' */
96 #define BWMON_ZONE_ACTIONS_CLEAR(z) (0x1 << ((z) * 2)) argument
117 * There is no clear documentation/explanation of BWMON_V4_THRESHOLD_COUNT
258 * Fill the cache for non-readable registers only as rest does not really
275 * No concurrent access expected - driver has one interrupt handler,
276 * regmap is not shared, no driver or user-space API.
284 * Cache is necessary for using regmap fields with non-readable
295 * No concurrent access expected - driver has one interrupt handler,
296 * regmap is not shared, no driver or user-space API.
303 * Cache is necessary for using regmap fields with non-readable
348 * Fill the cache for non-readable registers only as rest does not really
362 * No concurrent access expected - driver has one interrupt handler,
363 * regmap is not shared, no driver or user-space API.
371 * Cache is necessary for using regmap fields with non-readable
426 * Fill the cache for non-readable registers only as rest does not really
439 * No concurrent access expected - driver has one interrupt handler,
440 * regmap is not shared, no driver or user-space API.
448 * Cache is necessary for using regmap fields with non-readable
462 * important. Quoting downstream Qualcomm msm-4.9 tree: in bwmon_clear_counters()
468 regmap_field_force_write(bwmon->regs[F_CLEAR], val); in bwmon_clear_counters()
469 if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR) in bwmon_clear_counters()
470 regmap_field_force_write(bwmon->regs[F_CLEAR], 0); in bwmon_clear_counters()
477 if (bwmon->data->global_regmap_fields) in bwmon_clear_irq()
478 global_irq_clr = bwmon->global_regs[F_GLOBAL_IRQ_CLEAR]; in bwmon_clear_irq()
480 global_irq_clr = bwmon->regs[F_GLOBAL_IRQ_CLEAR]; in bwmon_clear_irq()
484 * important. Quoting downstream Qualcomm msm-4.9 tree: in bwmon_clear_irq()
490 * to be retriggered by the local interrupt still being high. in bwmon_clear_irq()
498 regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK); in bwmon_clear_irq()
499 if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR) in bwmon_clear_irq()
500 regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0); in bwmon_clear_irq()
501 if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) in bwmon_clear_irq()
510 if (bwmon->data->global_regmap_fields) in bwmon_disable()
511 global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE]; in bwmon_disable()
513 global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE]; in bwmon_disable()
516 if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) in bwmon_disable()
518 regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0); in bwmon_disable()
524 regmap_field_write(bwmon->regs[F_ENABLE], 0x0); in bwmon_disable()
531 if (bwmon->data->global_regmap_fields) in bwmon_enable()
532 global_irq_en = bwmon->global_regs[F_GLOBAL_IRQ_ENABLE]; in bwmon_enable()
534 global_irq_en = bwmon->regs[F_GLOBAL_IRQ_ENABLE]; in bwmon_enable()
537 if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ) in bwmon_enable()
541 regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable); in bwmon_enable()
544 regmap_field_write(bwmon->regs[F_ENABLE], BWMON_ENABLE_ENABLE); in bwmon_enable()
550 return kbps / bwmon->data->count_unit_kb; in bwmon_kbps_to_count()
559 bwmon->data->sample_ms, MSEC_PER_SEC); in bwmon_set_threshold()
565 const struct icc_bwmon_data *data = bwmon->data; in bwmon_start()
569 /* No need to check for errors, as this must have succeeded before. */ in bwmon_start()
570 dev_pm_opp_put(dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_low, 0)); in bwmon_start()
574 window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC); in bwmon_start()
576 regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window); in bwmon_start()
578 bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], bw_low); in bwmon_start()
579 bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], bw_low); in bwmon_start()
580 bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW], 0); in bwmon_start()
582 regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE0], in bwmon_start()
584 regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE1], in bwmon_start()
585 data->zone1_thres_count); in bwmon_start()
586 regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE2], in bwmon_start()
588 regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE3], in bwmon_start()
589 data->zone3_thres_count); in bwmon_start()
591 regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE0], in bwmon_start()
593 regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE1], in bwmon_start()
595 regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE2], in bwmon_start()
597 regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE3], in bwmon_start()
610 if (regmap_field_read(bwmon->regs[F_IRQ_STATUS], &status)) in bwmon_intr()
629 zone = get_bitmask_order(status) - 1; in bwmon_intr()
635 if (regmap_field_read(bwmon->regs[F_ZONE0_MAX + zone], &max)) in bwmon_intr()
639 max *= bwmon->data->count_unit_kb; in bwmon_intr()
640 bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms); in bwmon_intr()
652 bw_kbps = bwmon->target_kbps; in bwmon_intr_thread()
653 meas_kbps = bwmon->target_kbps; in bwmon_intr_thread()
655 target_opp = dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_kbps, 0); in bwmon_intr_thread()
656 if (IS_ERR(target_opp) && PTR_ERR(target_opp) == -ERANGE) in bwmon_intr_thread()
657 target_opp = dev_pm_opp_find_bw_floor(bwmon->dev, &bw_kbps, 0); in bwmon_intr_thread()
659 bwmon->target_kbps = bw_kbps; in bwmon_intr_thread()
661 bw_kbps--; in bwmon_intr_thread()
662 opp = dev_pm_opp_find_bw_floor(bwmon->dev, &bw_kbps, 0); in bwmon_intr_thread()
663 if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE) in bwmon_intr_thread()
664 down_kbps = bwmon->target_kbps; in bwmon_intr_thread()
668 up_kbps = bwmon->target_kbps + 1; in bwmon_intr_thread()
670 if (bwmon->target_kbps >= bwmon->max_bw_kbps) in bwmon_intr_thread()
672 else if (bwmon->target_kbps <= bwmon->min_bw_kbps) in bwmon_intr_thread()
677 bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH], in bwmon_intr_thread()
679 bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED], in bwmon_intr_thread()
685 trace_qcom_bwmon_update(dev_name(bwmon->dev), meas_kbps, up_kbps, down_kbps); in bwmon_intr_thread()
686 if (bwmon->target_kbps == bwmon->current_kbps) in bwmon_intr_thread()
689 dev_pm_opp_set_opp(bwmon->dev, target_opp); in bwmon_intr_thread()
690 bwmon->current_kbps = bwmon->target_kbps; in bwmon_intr_thread()
703 struct device *dev = &pdev->dev; in bwmon_init_regmap()
714 map = devm_regmap_init_mmio(dev, base, bwmon->data->regmap_cfg); in bwmon_init_regmap()
724 ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs, in bwmon_init_regmap()
725 bwmon->data->regmap_fields, in bwmon_init_regmap()
730 if (bwmon->data->global_regmap_cfg) { in bwmon_init_regmap()
737 map = devm_regmap_init_mmio(dev, base, bwmon->data->global_regmap_cfg); in bwmon_init_regmap()
742 ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->global_regs, in bwmon_init_regmap()
743 bwmon->data->global_regmap_fields, in bwmon_init_regmap()
752 struct device *dev = &pdev->dev; in bwmon_probe()
759 return -ENOMEM; in bwmon_probe()
761 bwmon->data = of_device_get_match_data(dev); in bwmon_probe()
767 bwmon->irq = platform_get_irq(pdev, 0); in bwmon_probe()
768 if (bwmon->irq < 0) in bwmon_probe()
769 return bwmon->irq; in bwmon_probe()
775 bwmon->max_bw_kbps = UINT_MAX; in bwmon_probe()
776 opp = dev_pm_opp_find_bw_floor(dev, &bwmon->max_bw_kbps, 0); in bwmon_probe()
781 bwmon->min_bw_kbps = 0; in bwmon_probe()
782 opp = dev_pm_opp_find_bw_ceil(dev, &bwmon->min_bw_kbps, 0); in bwmon_probe()
787 bwmon->dev = dev; in bwmon_probe()
792 * SoCs with multiple cpu-bwmon instances can end up using a shared interrupt in bwmon_probe()
796 ret = request_threaded_irq(bwmon->irq, bwmon_intr, bwmon_intr_thread, in bwmon_probe()
812 free_irq(bwmon->irq, bwmon); in bwmon_remove()
858 { .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
860 { .compatible = "qcom,sdm845-bwmon", .data = &sdm845_cpu_bwmon_data },
862 { .compatible = "qcom,sdm845-llcc-bwmon", .data = &sdm845_llcc_bwmon_data },
863 { .compatible = "qcom,sc7280-llcc-bwmon", .data = &sc7280_llcc_bwmon_data },
866 { .compatible = "qcom,sc7280-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
867 { .compatible = "qcom,sc8280xp-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
868 { .compatible = "qcom,sm8550-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
877 .name = "qcom-bwmon",