Skip to content

Commit 9186a0f

Browse files
MelOlvera-Qcomandersson
authored andcommitted
soc: qcom: llcc-qcom: Add support for LLCC V6
Add support for LLCC V6. V6 adds several additional usecase IDs, rearrages several registers and offsets, and supports slice IDs over 31, so add a new function for programming LLCC V6. Signed-off-by: Melody Olvera <[email protected]> Reviewed-by: Konrad Dybcio <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 33f7187 commit 9186a0f

File tree

1 file changed

+220
-4
lines changed

1 file changed

+220
-4
lines changed

drivers/soc/qcom/llcc-qcom.c

Lines changed: 220 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
#define ATTR0_RES_WAYS_MASK GENMASK(15, 0)
3636
#define ATTR0_BONUS_WAYS_MASK GENMASK(31, 16)
3737
#define ATTR0_BONUS_WAYS_SHIFT 16
38+
#define ATTR2_PROBE_TARGET_WAYS_MASK BIT(4)
39+
#define ATTR2_FIXED_SIZE_MASK BIT(8)
40+
#define ATTR2_PRIORITY_MASK GENMASK(14, 12)
41+
#define ATTR2_PARENT_SCID_MASK GENMASK(21, 16)
42+
#define ATTR2_IN_A_GROUP_MASK BIT(24)
3843
#define LLCC_STATUS_READ_DELAY 100
3944

4045
#define CACHE_LINE_SIZE_SHIFT 6
@@ -49,6 +54,10 @@
4954
#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n)
5055
#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n)
5156
#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_4 * n)
57+
#define LLCC_V6_TRP_ATTR0_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR0_CFG] + SZ_64 * (n))
58+
#define LLCC_V6_TRP_ATTR1_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR1_CFG] + SZ_64 * (n))
59+
#define LLCC_V6_TRP_ATTR2_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR2_CFG] + SZ_64 * (n))
60+
#define LLCC_V6_TRP_ATTR3_CFGn(n) (cfg->reg_offset[LLCC_TRP_ATTR3_CFG] + SZ_64 * (n))
5261

5362
#define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00
5463
#define LLCC_TRP_PCB_ACT 0x21f04
@@ -66,6 +75,7 @@
6675
#define LLCC_VERSION_2_0_0_0 0x02000000
6776
#define LLCC_VERSION_2_1_0_0 0x02010000
6877
#define LLCC_VERSION_4_1_0_0 0x04010000
78+
#define LLCC_VERSION_6_0_0_0 0X06000000
6979

7080
/**
7181
* struct llcc_slice_config - Data associated with the llcc slice
@@ -106,6 +116,7 @@
106116
* ovcap_en.
107117
* @vict_prio: When current scid is under-capacity, allocate over other
108118
* lower-than victim priority-line threshold scid.
119+
* @parent_slice_id: For grouped slices, specifies the slice id of the parent.
109120
*/
110121
struct llcc_slice_config {
111122
u32 usecase_id;
@@ -130,6 +141,7 @@ struct llcc_slice_config {
130141
bool ovcap_en;
131142
bool ovcap_prio;
132143
bool vict_prio;
144+
u32 parent_slice_id;
133145
};
134146

135147
struct qcom_llcc_config {
@@ -153,6 +165,21 @@ struct qcom_sct_config {
153165
enum llcc_reg_offset {
154166
LLCC_COMMON_HW_INFO,
155167
LLCC_COMMON_STATUS0,
168+
LLCC_TRP_ATTR0_CFG,
169+
LLCC_TRP_ATTR1_CFG,
170+
LLCC_TRP_ATTR2_CFG,
171+
LLCC_TRP_ATTR3_CFG,
172+
LLCC_TRP_SID_DIS_CAP_ALLOC,
173+
LLCC_TRP_ALGO_STALE_EN,
174+
LLCC_TRP_ALGO_STALE_CAP_EN,
175+
LLCC_TRP_ALGO_MRU0,
176+
LLCC_TRP_ALGO_MRU1,
177+
LLCC_TRP_ALGO_ALLOC0,
178+
LLCC_TRP_ALGO_ALLOC1,
179+
LLCC_TRP_ALGO_ALLOC2,
180+
LLCC_TRP_ALGO_ALLOC3,
181+
LLCC_TRP_WRS_EN,
182+
LLCC_TRP_WRS_CACHEABLE_EN,
156183
};
157184

158185
static const struct llcc_slice_config ipq5424_data[] = {
@@ -3161,6 +3188,33 @@ static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = {
31613188
.drp_ecc_db_err_syn0 = 0x52120,
31623189
};
31633190

3191+
static const struct llcc_edac_reg_offset llcc_v6_edac_reg_offset = {
3192+
.trp_ecc_error_status0 = 0x47448,
3193+
.trp_ecc_error_status1 = 0x47450,
3194+
.trp_ecc_sb_err_syn0 = 0x47490,
3195+
.trp_ecc_db_err_syn0 = 0x474d0,
3196+
.trp_ecc_error_cntr_clear = 0x47444,
3197+
.trp_interrupt_0_status = 0x47600,
3198+
.trp_interrupt_0_clear = 0x47604,
3199+
.trp_interrupt_0_enable = 0x47608,
3200+
3201+
/* LLCC Common registers */
3202+
.cmn_status0 = 0x6400c,
3203+
.cmn_interrupt_0_enable = 0x6401c,
3204+
.cmn_interrupt_2_enable = 0x6403c,
3205+
3206+
/* LLCC DRP registers */
3207+
.drp_ecc_error_cfg = 0x80000,
3208+
.drp_ecc_error_cntr_clear = 0x80004,
3209+
.drp_interrupt_status = 0x80020,
3210+
.drp_interrupt_clear = 0x80028,
3211+
.drp_interrupt_enable = 0x8002c,
3212+
.drp_ecc_error_status0 = 0x820f4,
3213+
.drp_ecc_error_status1 = 0x820f8,
3214+
.drp_ecc_sb_err_syn0 = 0x820fc,
3215+
.drp_ecc_db_err_syn0 = 0x82120,
3216+
};
3217+
31643218
/* LLCC register offset starting from v1.0.0 */
31653219
static const u32 llcc_v1_reg_offset[] = {
31663220
[LLCC_COMMON_HW_INFO] = 0x00030000,
@@ -3173,6 +3227,27 @@ static const u32 llcc_v2_1_reg_offset[] = {
31733227
[LLCC_COMMON_STATUS0] = 0x0003400c,
31743228
};
31753229

3230+
/* LLCC register offset starting from v6.0.0 */
3231+
static const u32 llcc_v6_reg_offset[] = {
3232+
[LLCC_COMMON_HW_INFO] = 0x00064000,
3233+
[LLCC_COMMON_STATUS0] = 0x0006400c,
3234+
[LLCC_TRP_ATTR0_CFG] = 0x00041000,
3235+
[LLCC_TRP_ATTR1_CFG] = 0x00041008,
3236+
[LLCC_TRP_ATTR2_CFG] = 0x00041010,
3237+
[LLCC_TRP_ATTR3_CFG] = 0x00041014,
3238+
[LLCC_TRP_SID_DIS_CAP_ALLOC] = 0x00042000,
3239+
[LLCC_TRP_ALGO_STALE_EN] = 0x00042008,
3240+
[LLCC_TRP_ALGO_STALE_CAP_EN] = 0x00042010,
3241+
[LLCC_TRP_ALGO_MRU0] = 0x00042018,
3242+
[LLCC_TRP_ALGO_MRU1] = 0x00042020,
3243+
[LLCC_TRP_ALGO_ALLOC0] = 0x00042028,
3244+
[LLCC_TRP_ALGO_ALLOC1] = 0x00042030,
3245+
[LLCC_TRP_ALGO_ALLOC2] = 0x00042038,
3246+
[LLCC_TRP_ALGO_ALLOC3] = 0x00042040,
3247+
[LLCC_TRP_WRS_EN] = 0x00042080,
3248+
[LLCC_TRP_WRS_CACHEABLE_EN] = 0x00042088,
3249+
};
3250+
31763251
static const struct qcom_llcc_config qcs615_cfg[] = {
31773252
{
31783253
.sct_data = qcs615_data,
@@ -3869,6 +3944,139 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config,
38693944
return ret;
38703945
}
38713946

3947+
static int _qcom_llcc_cfg_program_v6(const struct llcc_slice_config *config,
3948+
const struct qcom_llcc_config *cfg)
3949+
{
3950+
u32 stale_en, stale_cap_en, mru_uncap_en, mru_rollover;
3951+
u32 alloc_oneway_en, ovcap_en, ovcap_prio, vict_prio;
3952+
u32 attr0_cfg, attr1_cfg, attr2_cfg, attr3_cfg;
3953+
u32 attr0_val, attr1_val, attr2_val, attr3_val;
3954+
u32 slice_offset, reg_offset;
3955+
struct llcc_slice_desc *desc;
3956+
u32 wren, wr_cache_en;
3957+
int ret;
3958+
3959+
attr0_cfg = LLCC_V6_TRP_ATTR0_CFGn(config->slice_id);
3960+
attr1_cfg = LLCC_V6_TRP_ATTR1_CFGn(config->slice_id);
3961+
attr2_cfg = LLCC_V6_TRP_ATTR2_CFGn(config->slice_id);
3962+
attr3_cfg = LLCC_V6_TRP_ATTR3_CFGn(config->slice_id);
3963+
3964+
attr0_val = config->res_ways;
3965+
attr1_val = config->bonus_ways;
3966+
attr2_val = config->cache_mode;
3967+
attr2_val |= FIELD_PREP(ATTR2_PROBE_TARGET_WAYS_MASK, config->probe_target_ways);
3968+
attr2_val |= FIELD_PREP(ATTR2_FIXED_SIZE_MASK, config->fixed_size);
3969+
attr2_val |= FIELD_PREP(ATTR2_PRIORITY_MASK, config->priority);
3970+
3971+
if (config->parent_slice_id && config->fixed_size) {
3972+
attr2_val |= FIELD_PREP(ATTR2_PARENT_SCID_MASK, config->parent_slice_id);
3973+
attr2_val |= ATTR2_IN_A_GROUP_MASK;
3974+
}
3975+
3976+
attr3_val = MAX_CAP_TO_BYTES(config->max_cap);
3977+
attr3_val /= drv_data->num_banks;
3978+
attr3_val >>= CACHE_LINE_SIZE_SHIFT;
3979+
3980+
ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, attr0_val);
3981+
if (ret)
3982+
return ret;
3983+
3984+
ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, attr1_val);
3985+
if (ret)
3986+
return ret;
3987+
3988+
ret = regmap_write(drv_data->bcast_regmap, attr2_cfg, attr2_val);
3989+
if (ret)
3990+
return ret;
3991+
3992+
ret = regmap_write(drv_data->bcast_regmap, attr3_cfg, attr3_val);
3993+
if (ret)
3994+
return ret;
3995+
3996+
slice_offset = config->slice_id % 32;
3997+
reg_offset = (config->slice_id / 32) * 4;
3998+
3999+
wren = config->write_scid_en << slice_offset;
4000+
ret = regmap_update_bits(drv_data->bcast_regmap,
4001+
cfg->reg_offset[LLCC_TRP_WRS_EN] + reg_offset,
4002+
BIT(slice_offset), wren);
4003+
if (ret)
4004+
return ret;
4005+
4006+
wr_cache_en = config->write_scid_cacheable_en << slice_offset;
4007+
ret = regmap_update_bits(drv_data->bcast_regmap,
4008+
cfg->reg_offset[LLCC_TRP_WRS_CACHEABLE_EN] + reg_offset,
4009+
BIT(slice_offset), wr_cache_en);
4010+
if (ret)
4011+
return ret;
4012+
4013+
stale_en = config->stale_en << slice_offset;
4014+
ret = regmap_update_bits(drv_data->bcast_regmap,
4015+
cfg->reg_offset[LLCC_TRP_ALGO_STALE_EN] + reg_offset,
4016+
BIT(slice_offset), stale_en);
4017+
if (ret)
4018+
return ret;
4019+
4020+
stale_cap_en = config->stale_cap_en << slice_offset;
4021+
ret = regmap_update_bits(drv_data->bcast_regmap,
4022+
cfg->reg_offset[LLCC_TRP_ALGO_STALE_CAP_EN] + reg_offset,
4023+
BIT(slice_offset), stale_cap_en);
4024+
if (ret)
4025+
return ret;
4026+
4027+
mru_uncap_en = config->mru_uncap_en << slice_offset;
4028+
ret = regmap_update_bits(drv_data->bcast_regmap,
4029+
cfg->reg_offset[LLCC_TRP_ALGO_MRU0] + reg_offset,
4030+
BIT(slice_offset), mru_uncap_en);
4031+
if (ret)
4032+
return ret;
4033+
4034+
mru_rollover = config->mru_rollover << slice_offset;
4035+
ret = regmap_update_bits(drv_data->bcast_regmap,
4036+
cfg->reg_offset[LLCC_TRP_ALGO_MRU1] + reg_offset,
4037+
BIT(slice_offset), mru_rollover);
4038+
if (ret)
4039+
return ret;
4040+
4041+
alloc_oneway_en = config->alloc_oneway_en << slice_offset;
4042+
ret = regmap_update_bits(drv_data->bcast_regmap,
4043+
cfg->reg_offset[LLCC_TRP_ALGO_ALLOC0] + reg_offset,
4044+
BIT(slice_offset), alloc_oneway_en);
4045+
if (ret)
4046+
return ret;
4047+
4048+
ovcap_en = config->ovcap_en << slice_offset;
4049+
ret = regmap_update_bits(drv_data->bcast_regmap,
4050+
cfg->reg_offset[LLCC_TRP_ALGO_ALLOC1] + reg_offset,
4051+
BIT(slice_offset), ovcap_en);
4052+
if (ret)
4053+
return ret;
4054+
4055+
ovcap_prio = config->ovcap_prio << slice_offset;
4056+
ret = regmap_update_bits(drv_data->bcast_regmap,
4057+
cfg->reg_offset[LLCC_TRP_ALGO_ALLOC2] + reg_offset,
4058+
BIT(slice_offset), ovcap_prio);
4059+
if (ret)
4060+
return ret;
4061+
4062+
vict_prio = config->vict_prio << slice_offset;
4063+
ret = regmap_update_bits(drv_data->bcast_regmap,
4064+
cfg->reg_offset[LLCC_TRP_ALGO_ALLOC3] + reg_offset,
4065+
BIT(slice_offset), vict_prio);
4066+
if (ret)
4067+
return ret;
4068+
4069+
if (config->activate_on_init) {
4070+
desc = llcc_slice_getd(config->usecase_id);
4071+
if (PTR_ERR_OR_ZERO(desc))
4072+
return -EINVAL;
4073+
4074+
ret = llcc_slice_activate(desc);
4075+
}
4076+
4077+
return ret;
4078+
}
4079+
38724080
static int qcom_llcc_cfg_program(struct platform_device *pdev,
38734081
const struct qcom_llcc_config *cfg)
38744082
{
@@ -3880,10 +4088,18 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev,
38804088
sz = drv_data->cfg_size;
38814089
llcc_table = drv_data->cfg;
38824090

3883-
for (i = 0; i < sz; i++) {
3884-
ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg);
3885-
if (ret)
3886-
return ret;
4091+
if (drv_data->version >= LLCC_VERSION_6_0_0_0) {
4092+
for (i = 0; i < sz; i++) {
4093+
ret = _qcom_llcc_cfg_program_v6(&llcc_table[i], cfg);
4094+
if (ret)
4095+
return ret;
4096+
}
4097+
} else {
4098+
for (i = 0; i < sz; i++) {
4099+
ret = _qcom_llcc_cfg_program(&llcc_table[i], cfg);
4100+
if (ret)
4101+
return ret;
4102+
}
38874103
}
38884104

38894105
return ret;

0 commit comments

Comments
 (0)