#define BWMON_V4_IRQ_ENABLE                    0x10c
 #define BWMON_IRQ_ENABLE_MASK                  (BIT(1) | BIT(3))
+#define BWMON_V5_IRQ_STATUS                    0x000
+#define BWMON_V5_IRQ_CLEAR                     0x008
+#define BWMON_V5_IRQ_ENABLE                    0x00c
 
 #define BWMON_V4_ENABLE                                0x2a0
+#define BWMON_V5_ENABLE                                0x010
 #define BWMON_ENABLE_ENABLE                    BIT(0)
 
 #define BWMON_V4_CLEAR                         0x2a4
+#define BWMON_V5_CLEAR                         0x014
 #define BWMON_CLEAR_CLEAR                      BIT(0)
 #define BWMON_CLEAR_CLEAR_ALL                  BIT(1)
 
 #define BWMON_V4_SAMPLE_WINDOW                 0x2a8
+#define BWMON_V5_SAMPLE_WINDOW                 0x020
+
 #define BWMON_V4_THRESHOLD_HIGH                        0x2ac
 #define BWMON_V4_THRESHOLD_MED                 0x2b0
 #define BWMON_V4_THRESHOLD_LOW                 0x2b4
+#define BWMON_V5_THRESHOLD_HIGH                        0x024
+#define BWMON_V5_THRESHOLD_MED                 0x028
+#define BWMON_V5_THRESHOLD_LOW                 0x02c
 
 #define BWMON_V4_ZONE_ACTIONS                  0x2b8
+#define BWMON_V5_ZONE_ACTIONS                  0x030
 /*
  * Actions to perform on some zone 'z' when current zone hits the threshold:
  * Increment counter of zone 'z'
  * 0xff are maximum values meant to ignore the zones 0 and 2.
  */
 #define BWMON_V4_THRESHOLD_COUNT               0x2bc
+#define BWMON_V5_THRESHOLD_COUNT               0x034
 #define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT    0xff
 #define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT    0xff
 
 #define BWMON_V4_ZONE_MAX(zone)                        (0x2e0 + 4 * (zone))
+#define BWMON_V5_ZONE_MAX(zone)                        (0x044 + 4 * (zone))
 
 /* Quirks for specific BWMON types */
 #define BWMON_HAS_GLOBAL_IRQ                   BIT(0)
        .cache_type             = REGCACHE_RBTREE,
 };
 
+/* BWMON v5 */
+static const struct reg_field sdm845_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, 11),
+       [F_THRESHOLD_MED]       = REG_FIELD(BWMON_V5_THRESHOLD_MED, 0, 11),
+       [F_THRESHOLD_LOW]       = REG_FIELD(BWMON_V5_THRESHOLD_LOW, 0, 11),
+       [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, 11),
+       [F_ZONE1_MAX]           = REG_FIELD(BWMON_V5_ZONE_MAX(1), 0, 11),
+       [F_ZONE2_MAX]           = REG_FIELD(BWMON_V5_ZONE_MAX(2), 0, 11),
+       [F_ZONE3_MAX]           = REG_FIELD(BWMON_V5_ZONE_MAX(3), 0, 11),
+};
+
+static const struct regmap_range sdm845_llcc_bwmon_reg_noread_ranges[] = {
+       regmap_reg_range(BWMON_V5_IRQ_CLEAR, BWMON_V5_IRQ_CLEAR),
+       regmap_reg_range(BWMON_V5_CLEAR, BWMON_V5_CLEAR),
+};
+
+static const struct regmap_access_table sdm845_llcc_bwmon_reg_read_table = {
+       .no_ranges      = sdm845_llcc_bwmon_reg_noread_ranges,
+       .n_no_ranges    = ARRAY_SIZE(sdm845_llcc_bwmon_reg_noread_ranges),
+};
+
+static const struct regmap_range sdm845_llcc_bwmon_reg_volatile_ranges[] = {
+       regmap_reg_range(BWMON_V5_IRQ_STATUS, BWMON_V5_IRQ_STATUS),
+       regmap_reg_range(BWMON_V5_ZONE_MAX(0), BWMON_V5_ZONE_MAX(3)),
+};
+
+static const struct regmap_access_table sdm845_llcc_bwmon_reg_volatile_table = {
+       .yes_ranges     = sdm845_llcc_bwmon_reg_volatile_ranges,
+       .n_yes_ranges   = ARRAY_SIZE(sdm845_llcc_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 sdm845_llcc_bwmon_reg_defaults[] = {
+       { BWMON_V5_IRQ_CLEAR, 0x0 },
+       { BWMON_V5_CLEAR, 0x0 },
+};
+
+static const struct regmap_config sdm845_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_RBTREE,
+};
+
 static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
 {
        unsigned int val = BWMON_CLEAR_CLEAR;
        bwmon_clear_counters(bwmon, true);
 
        window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
-       /* Maximum sampling window: 0xfffff */
+       /* Maximum sampling window: 0xffffff for v4 and 0xfffff for v5 */
        regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window);
 
        bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH],
                                     "failed to initialize regmap\n");
 
        BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
+       BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
        ret = devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
                                           bwmon->data->regmap_fields,
                                           F_NUM_FIELDS);
        .regmap_cfg = &msm8998_bwmon_regmap_cfg,
 };
 
+static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
+       .sample_ms = 4,
+       .count_unit_kb = 1024,
+       .default_highbw_kbps = 800 * 1024, /* 800 MBps */
+       .default_medbw_kbps = 256 * 1024, /* 256 MBps */
+       .default_lowbw_kbps = 0,
+       .zone1_thres_count = 16,
+       .zone3_thres_count = 1,
+       .regmap_fields = sdm845_llcc_bwmon_reg_fields,
+       .regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
+};
+
 static const struct of_device_id bwmon_of_match[] = {
-       { .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
+       {
+               .compatible = "qcom,msm8998-bwmon",
+               .data = &msm8998_bwmon_data
+       }, {
+               .compatible = "qcom,sdm845-llcc-bwmon",
+               .data = &sdm845_llcc_bwmon_data
+       },
        {}
 };
 MODULE_DEVICE_TABLE(of, bwmon_of_match);