Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ properties:
- qcom,qcs615-cpu-bwmon
- qcom,qcs8300-cpu-bwmon
- qcom,sa8775p-cpu-bwmon
- qcom,sa8797p-cpu-bwmon
- qcom,sc7180-cpu-bwmon
- qcom,sc7280-cpu-bwmon
- qcom,sc8280xp-cpu-bwmon
Expand All @@ -50,6 +51,7 @@ properties:
- qcom,qcs615-llcc-bwmon
- qcom,qcs8300-llcc-bwmon
- qcom,sa8775p-llcc-bwmon
- qcom,sa8797p-llcc-bwmon
- qcom,sc7180-llcc-bwmon
- qcom,sc8280xp-llcc-bwmon
- qcom,shikra-cpu-bwmon
Expand Down
104 changes: 104 additions & 0 deletions arch/arm64/boot/dts/qcom/nord-embedded.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,110 @@
#interconnect-cells = <2>;
qcom,bcm-voters = <&apps_bcm_voter>;
};

llcc_bwmon: pmu@21091000 {
compatible = "qcom,sa8797p-llcc-bwmon", "qcom,sc7280-llcc-bwmon";
reg = <0x0 0x21091000 0x0 0x1000>;
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
interconnects = <&mc_virt MASTER_LLCC QCOM_ICC_TAG_ACTIVE_ONLY
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ACTIVE_ONLY>;

operating-points-v2 = <&llcc_bwmon_opp_table>;

llcc_bwmon_opp_table: opp-table {
compatible = "operating-points-v2";

opp-0 {
opp-peak-kBps = <762000>;
};

opp-1 {
opp-peak-kBps = <1720000>;
};

opp-2 {
opp-peak-kBps = <2086000>;
};

opp-3 {
opp-peak-kBps = <2601000>;
};

opp-4 {
opp-peak-kBps = <2929000>;
};

opp-5 {
opp-peak-kBps = <5931000>;
};

opp-6 {
opp-peak-kBps = <6515000>;
};

opp-7 {
opp-peak-kBps = <7984000>;
};

opp-8 {
opp-peak-kBps = <10437000>;
};

opp-9 {
opp-peak-kBps = <12195000>;
};
};
};

cpu_bwmon0: pmu@1016300 {
compatible = "qcom,sa8797p-cpu-bwmon", "qcom,sdm845-bwmon";
reg = <0x0 0x1016300 0x0 0x600>;
interrupts = <GIC_SPI 813 IRQ_TYPE_LEVEL_HIGH>;
interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
&hscnoc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>;

operating-points-v2 = <&cpu_bwmon_opp_table>;

cpu_bwmon_opp_table: opp-table {
compatible = "operating-points-v2";

opp-0 {
opp-peak-kBps = <9155000>;
};

opp-1 {
opp-peak-kBps = <12298000>;
};

opp-2 {
opp-peak-kBps = <14236000>;
};

opp-3 {
opp-peak-kBps = <16265000>;
};
};
};

cpu_bwmon1: pmu@1015300 {
compatible = "qcom,sa8797p-cpu-bwmon", "qcom,sdm845-bwmon";
reg = <0x0 0x1015300 0x0 0x600>;
interrupts = <GIC_SPI 812 IRQ_TYPE_LEVEL_HIGH>;
interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
&hscnoc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>;

operating-points-v2 = <&cpu_bwmon_opp_table>;
};

cpu_bwmon2: pmu@1014300 {
compatible = "qcom,sa8797p-cpu-bwmon", "qcom,sc7280-cpu-bwmon";
reg = <0x0 0x1014300 0x0 0x600>;
interrupts = <GIC_SPI 739 IRQ_TYPE_LEVEL_HIGH>;
interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
&hscnoc SLAVE_LLCC QCOM_ICC_TAG_ACTIVE_ONLY>;

operating-points-v2 = <&cpu_bwmon_opp_table>;
};
};

&tlmm {
Expand Down
185 changes: 185 additions & 0 deletions drivers/soc/qcom/icc-bwmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,29 @@
#define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone))
#define BWMON_V5_ZONE_MAX(zone) (0x044 + 4 * (zone))

/*
* SA8797P cpu-bwmon: global registers and monitor registers are both mapped
* in a single, unified region, but at different absolute offsets than
* BWMON v4 - no "845 offset" adjustment is needed. The zone mechanism
* (BWMON2 in the hardware docs) is used, same as v4/v5.
*/
#define SA8797P_CPU_BWMON_GLOBAL_IRQ_CLEAR 0x108
#define SA8797P_CPU_BWMON_GLOBAL_IRQ_ENABLE 0x10c

#define SA8797P_CPU_BWMON_IRQ_STATUS 0x200
#define SA8797P_CPU_BWMON_IRQ_CLEAR 0x208
#define SA8797P_CPU_BWMON_IRQ_ENABLE 0x20c

#define SA8797P_CPU_BWMON_ENABLE 0x3a0
#define SA8797P_CPU_BWMON_CLEAR 0x3a4
#define SA8797P_CPU_BWMON_SAMPLE_WINDOW 0x3a8
#define SA8797P_CPU_BWMON_THRESHOLD_HIGH 0x3ac
#define SA8797P_CPU_BWMON_THRESHOLD_MED 0x3b0
#define SA8797P_CPU_BWMON_THRESHOLD_LOW 0x3b4
#define SA8797P_CPU_BWMON_ZONE_ACTIONS 0x3b8
#define SA8797P_CPU_BWMON_THRESHOLD_COUNT 0x3bc
#define SA8797P_CPU_BWMON_ZONE_MAX(zone) (0x3e0 + 4 * (zone))

/* Quirks for specific BWMON types */
#define BWMON_HAS_GLOBAL_IRQ BIT(0)
#define BWMON_NEEDS_FORCE_CLEAR BIT(1)
Expand Down Expand Up @@ -374,6 +397,91 @@ static const struct regmap_config sdm845_cpu_bwmon_regmap_cfg = {
.cache_type = REGCACHE_MAPLE,
};

/*
* SA8797P cpu-bwmon (throttle_bwmon_wrapper_apss). Unified register space,
* but global and local IRQ registers do not overlap so, unlike the sdm845
* "unified register space" case, no offset shifting is needed for the
* global IRQ registers. Threshold and zone-max registers are 16-bit wide,
* versus 12-bit on BWMON v4/v5.
*/
static const struct reg_field sa8797p_cpu_bwmon_reg_fields[] = {
[F_GLOBAL_IRQ_CLEAR] = REG_FIELD(SA8797P_CPU_BWMON_GLOBAL_IRQ_CLEAR, 0, 0),
[F_GLOBAL_IRQ_ENABLE] = REG_FIELD(SA8797P_CPU_BWMON_GLOBAL_IRQ_ENABLE, 0, 0),
[F_IRQ_STATUS] = REG_FIELD(SA8797P_CPU_BWMON_IRQ_STATUS, 4, 7),
[F_IRQ_CLEAR] = REG_FIELD(SA8797P_CPU_BWMON_IRQ_CLEAR, 4, 7),
[F_IRQ_ENABLE] = REG_FIELD(SA8797P_CPU_BWMON_IRQ_ENABLE, 4, 7),
/* F_ENABLE covers entire register to disable other features */
[F_ENABLE] = REG_FIELD(SA8797P_CPU_BWMON_ENABLE, 0, 31),
[F_CLEAR] = REG_FIELD(SA8797P_CPU_BWMON_CLEAR, 0, 1),
[F_SAMPLE_WINDOW] = REG_FIELD(SA8797P_CPU_BWMON_SAMPLE_WINDOW, 0, 23),
[F_THRESHOLD_HIGH] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_HIGH, 0, 15),
[F_THRESHOLD_MED] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_MED, 0, 15),
[F_THRESHOLD_LOW] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_LOW, 0, 15),
[F_ZONE_ACTIONS_ZONE0] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_ACTIONS, 0, 7),
[F_ZONE_ACTIONS_ZONE1] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_ACTIONS, 8, 15),
[F_ZONE_ACTIONS_ZONE2] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_ACTIONS, 16, 23),
[F_ZONE_ACTIONS_ZONE3] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_ACTIONS, 24, 31),
[F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_COUNT, 0, 7),
[F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_COUNT, 8, 15),
[F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_COUNT, 16, 23),
[F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(SA8797P_CPU_BWMON_THRESHOLD_COUNT, 24, 31),
[F_ZONE0_MAX] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_MAX(0), 0, 15),
[F_ZONE1_MAX] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_MAX(1), 0, 15),
[F_ZONE2_MAX] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_MAX(2), 0, 15),
[F_ZONE3_MAX] = REG_FIELD(SA8797P_CPU_BWMON_ZONE_MAX(3), 0, 15),
};

static const struct regmap_range sa8797p_cpu_bwmon_reg_noread_ranges[] = {
regmap_reg_range(SA8797P_CPU_BWMON_GLOBAL_IRQ_CLEAR, SA8797P_CPU_BWMON_GLOBAL_IRQ_CLEAR),
regmap_reg_range(SA8797P_CPU_BWMON_IRQ_CLEAR, SA8797P_CPU_BWMON_IRQ_CLEAR),
regmap_reg_range(SA8797P_CPU_BWMON_CLEAR, SA8797P_CPU_BWMON_CLEAR),
};

static const struct regmap_access_table sa8797p_cpu_bwmon_reg_read_table = {
.no_ranges = sa8797p_cpu_bwmon_reg_noread_ranges,
.n_no_ranges = ARRAY_SIZE(sa8797p_cpu_bwmon_reg_noread_ranges),
};

static const struct regmap_range sa8797p_cpu_bwmon_reg_volatile_ranges[] = {
regmap_reg_range(SA8797P_CPU_BWMON_IRQ_STATUS, SA8797P_CPU_BWMON_IRQ_STATUS),
regmap_reg_range(SA8797P_CPU_BWMON_ZONE_MAX(0), SA8797P_CPU_BWMON_ZONE_MAX(3)),
};

static const struct regmap_access_table sa8797p_cpu_bwmon_reg_volatile_table = {
.yes_ranges = sa8797p_cpu_bwmon_reg_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(sa8797p_cpu_bwmon_reg_volatile_ranges),
};

/*
* Fill the cache for non-readable registers only as rest does not really
* matter and can be read from the device.
*/
static const struct reg_default sa8797p_cpu_bwmon_reg_defaults[] = {
{ SA8797P_CPU_BWMON_GLOBAL_IRQ_CLEAR, 0x0 },
{ SA8797P_CPU_BWMON_IRQ_CLEAR, 0x0 },
{ SA8797P_CPU_BWMON_CLEAR, 0x0 },
};

static const struct regmap_config sa8797p_cpu_bwmon_regmap_cfg = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
/*
* No concurrent access expected - driver has one interrupt handler,
* regmap is not shared, no driver or user-space API.
*/
.disable_locking = true,
.rd_table = &sa8797p_cpu_bwmon_reg_read_table,
.volatile_table = &sa8797p_cpu_bwmon_reg_volatile_table,
.reg_defaults = sa8797p_cpu_bwmon_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(sa8797p_cpu_bwmon_reg_defaults),
/*
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
.cache_type = REGCACHE_MAPLE,
};

/* BWMON v5 */
static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = {
[F_GLOBAL_IRQ_CLEAR] = {},
Expand Down Expand Up @@ -451,6 +559,57 @@ static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = {
.cache_type = REGCACHE_MAPLE,
};

/*
* SA8797P llcc-bwmon: same register offsets as BWMON v5, but the
* threshold and zone-max fields are 16 bits wide instead of 12.
*/
static const struct reg_field sa8797p_llcc_bwmon_reg_fields[] = {
[F_GLOBAL_IRQ_CLEAR] = {},
[F_GLOBAL_IRQ_ENABLE] = {},
[F_IRQ_STATUS] = REG_FIELD(BWMON_V5_IRQ_STATUS, 0, 3),
[F_IRQ_CLEAR] = REG_FIELD(BWMON_V5_IRQ_CLEAR, 0, 3),
[F_IRQ_ENABLE] = REG_FIELD(BWMON_V5_IRQ_ENABLE, 0, 3),
/* F_ENABLE covers entire register to disable other features */
[F_ENABLE] = REG_FIELD(BWMON_V5_ENABLE, 0, 31),
[F_CLEAR] = REG_FIELD(BWMON_V5_CLEAR, 0, 1),
[F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V5_SAMPLE_WINDOW, 0, 19),
[F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V5_THRESHOLD_HIGH, 0, 15),
[F_THRESHOLD_MED] = REG_FIELD(BWMON_V5_THRESHOLD_MED, 0, 15),
[F_THRESHOLD_LOW] = REG_FIELD(BWMON_V5_THRESHOLD_LOW, 0, 15),
[F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 0, 7),
[F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 8, 15),
[F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 16, 23),
[F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 24, 31),
[F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 0, 7),
[F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 8, 15),
[F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 16, 23),
[F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 24, 31),
[F_ZONE0_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(0), 0, 15),
[F_ZONE1_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(1), 0, 15),
[F_ZONE2_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(2), 0, 15),
[F_ZONE3_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(3), 0, 15),
};

static const struct regmap_config sa8797p_llcc_bwmon_regmap_cfg = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
/*
* No concurrent access expected - driver has one interrupt handler,
* regmap is not shared, no driver or user-space API.
*/
.disable_locking = true,
.rd_table = &sdm845_llcc_bwmon_reg_read_table,
.volatile_table = &sdm845_llcc_bwmon_reg_volatile_table,
.reg_defaults = sdm845_llcc_bwmon_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(sdm845_llcc_bwmon_reg_defaults),
/*
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
.cache_type = REGCACHE_MAPLE,
};

static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
{
unsigned int val = BWMON_CLEAR_CLEAR;
Expand Down Expand Up @@ -722,7 +881,9 @@ static int bwmon_init_regmap(struct platform_device *pdev,
BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_global_reg_fields) != F_NUM_GLOBAL_FIELDS);
BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
BUILD_BUG_ON(ARRAY_SIZE(sdm845_cpu_bwmon_reg_fields) != F_NUM_FIELDS);
BUILD_BUG_ON(ARRAY_SIZE(sa8797p_cpu_bwmon_reg_fields) != F_NUM_FIELDS);
BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
BUILD_BUG_ON(ARRAY_SIZE(sa8797p_llcc_bwmon_reg_fields) != F_NUM_FIELDS);

ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
bwmon->data->regmap_fields,
Expand Down Expand Up @@ -837,6 +998,16 @@ static const struct icc_bwmon_data sdm845_cpu_bwmon_data = {
.regmap_cfg = &sdm845_cpu_bwmon_regmap_cfg,
};

static const struct icc_bwmon_data sa8797p_cpu_bwmon_data = {
.sample_ms = 4,
.count_unit_kb = 64,
.zone1_thres_count = 16,
.zone3_thres_count = 1,
.quirks = BWMON_HAS_GLOBAL_IRQ,
.regmap_fields = sa8797p_cpu_bwmon_reg_fields,
.regmap_cfg = &sa8797p_cpu_bwmon_regmap_cfg,
};

static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
.sample_ms = 4,
.count_unit_kb = 1024,
Expand All @@ -856,14 +1027,28 @@ static const struct icc_bwmon_data sc7280_llcc_bwmon_data = {
.regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
};

static const struct icc_bwmon_data sa8797p_llcc_bwmon_data = {
.sample_ms = 4,
.count_unit_kb = 64,
.zone1_thres_count = 16,
.zone3_thres_count = 1,
.quirks = BWMON_NEEDS_FORCE_CLEAR,
.regmap_fields = sa8797p_llcc_bwmon_reg_fields,
.regmap_cfg = &sa8797p_llcc_bwmon_regmap_cfg,
};

static const struct of_device_id bwmon_of_match[] = {
/* BWMONv4, separate monitor and global register spaces */
{ .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
/* BWMONv4, unified register space */
{ .compatible = "qcom,sdm845-bwmon", .data = &sdm845_cpu_bwmon_data },
/* SA8797P cpu-bwmon, unified register space, different layout than v4 */
{ .compatible = "qcom,sa8797p-cpu-bwmon", .data = &sa8797p_cpu_bwmon_data },
/* BWMONv5 */
{ .compatible = "qcom,sdm845-llcc-bwmon", .data = &sdm845_llcc_bwmon_data },
{ .compatible = "qcom,sc7280-llcc-bwmon", .data = &sc7280_llcc_bwmon_data },
/* BWMONv5, same offsets but wider threshold/zone-max fields */
{ .compatible = "qcom,sa8797p-llcc-bwmon", .data = &sa8797p_llcc_bwmon_data },

/* Compatibles kept for legacy reasons */
{ .compatible = "qcom,sc7280-cpu-bwmon", .data = &sdm845_cpu_bwmon_data },
Expand Down
Loading