1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
7 #include <linux/bitmap.h>
8 #include <linux/bitops.h>
9 #include <linux/device.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
15 #include <linux/of_device.h>
16 #include <linux/regmap.h>
17 #include <linux/sizes.h>
18 #include <linux/slab.h>
19 #include <linux/soc/qcom/llcc-qcom.h>
21 #define ACTIVATE BIT(0)
22 #define DEACTIVATE BIT(1)
23 #define ACT_CTRL_OPCODE_ACTIVATE BIT(0)
24 #define ACT_CTRL_OPCODE_DEACTIVATE BIT(1)
25 #define ACT_CTRL_ACT_TRIG BIT(0)
26 #define ACT_CTRL_OPCODE_SHIFT 0x01
27 #define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x02
28 #define ATTR1_FIXED_SIZE_SHIFT 0x03
29 #define ATTR1_PRIORITY_SHIFT 0x04
30 #define ATTR1_MAX_CAP_SHIFT 0x10
31 #define ATTR0_RES_WAYS_MASK GENMASK(11, 0)
32 #define ATTR0_BONUS_WAYS_MASK GENMASK(27, 16)
33 #define ATTR0_BONUS_WAYS_SHIFT 0x10
34 #define LLCC_STATUS_READ_DELAY 100
36 #define CACHE_LINE_SIZE_SHIFT 6
38 #define LLCC_COMMON_STATUS0 0x0003000c
39 #define LLCC_LB_CNT_MASK GENMASK(31, 28)
40 #define LLCC_LB_CNT_SHIFT 28
42 #define MAX_CAP_TO_BYTES(n) (n * SZ_1K)
43 #define LLCC_TRP_ACT_CTRLn(n) (n * SZ_4K)
44 #define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K)
45 #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n)
46 #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n)
48 #define BANK_OFFSET_STRIDE 0x80000
51 * llcc_slice_config - Data associated with the llcc slice
52 * @usecase_id: Unique id for the client's use case
53 * @slice_id: llcc slice id for each client
54 * @max_cap: The maximum capacity of the cache slice provided in KB
55 * @priority: Priority of the client used to select victim line for replacement
56 * @fixed_size: Boolean indicating if the slice has a fixed capacity
57 * @bonus_ways: Bonus ways are additional ways to be used for any slice,
58 * if client ends up using more than reserved cache ways. Bonus
59 * ways are allocated only if they are not reserved for some
61 * @res_ways: Reserved ways for the cache slice, the reserved ways cannot
62 * be used by any other client than the one its assigned to.
63 * @cache_mode: Each slice operates as a cache, this controls the mode of the
64 * slice: normal or TCM(Tightly Coupled Memory)
65 * @probe_target_ways: Determines what ways to probe for access hit. When
66 * configured to 1 only bonus and reserved ways are probed.
67 * When configured to 0 all ways in llcc are probed.
68 * @dis_cap_alloc: Disable capacity based allocation for a client
69 * @retain_on_pc: If this bit is set and client has maintained active vote
70 * then the ways assigned to this client are not flushed on power
72 * @activate_on_init: Activate the slice immediately after it is programmed
74 struct llcc_slice_config
{
83 u32 probe_target_ways
;
86 bool activate_on_init
;
89 struct qcom_llcc_config
{
90 const struct llcc_slice_config
*sct_data
;
94 static const struct llcc_slice_config sc7180_data
[] = {
95 { LLCC_CPUSS
, 1, 256, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 1 },
96 { LLCC_MDM
, 8, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
97 { LLCC_GPUHTW
, 11, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
98 { LLCC_GPU
, 12, 128, 1, 0, 0xf, 0x0, 0, 0, 0, 1, 0 },
101 static const struct llcc_slice_config sdm845_data
[] = {
102 { LLCC_CPUSS
, 1, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 1 },
103 { LLCC_VIDSC0
, 2, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 },
104 { LLCC_VIDSC1
, 3, 512, 2, 1, 0x0, 0x0f0, 0, 0, 1, 1, 0 },
105 { LLCC_ROTATOR
, 4, 563, 2, 1, 0x0, 0x00e, 2, 0, 1, 1, 0 },
106 { LLCC_VOICE
, 5, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
107 { LLCC_AUDIO
, 6, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
108 { LLCC_MDMHPGRW
, 7, 1024, 2, 0, 0xfc, 0xf00, 0, 0, 1, 1, 0 },
109 { LLCC_MDM
, 8, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
110 { LLCC_CMPT
, 10, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
111 { LLCC_GPUHTW
, 11, 512, 1, 1, 0xc, 0x0, 0, 0, 1, 1, 0 },
112 { LLCC_GPU
, 12, 2304, 1, 0, 0xff0, 0x2, 0, 0, 1, 1, 0 },
113 { LLCC_MMUHWT
, 13, 256, 2, 0, 0x0, 0x1, 0, 0, 1, 0, 1 },
114 { LLCC_CMPTDMA
, 15, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
115 { LLCC_DISP
, 16, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
116 { LLCC_VIDFW
, 17, 2816, 1, 0, 0xffc, 0x2, 0, 0, 1, 1, 0 },
117 { LLCC_MDMHPFX
, 20, 1024, 2, 1, 0x0, 0xf00, 0, 0, 1, 1, 0 },
118 { LLCC_MDMPNG
, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0 },
119 { LLCC_AUDHW
, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0 },
122 static const struct qcom_llcc_config sc7180_cfg
= {
123 .sct_data
= sc7180_data
,
124 .size
= ARRAY_SIZE(sc7180_data
),
127 static const struct qcom_llcc_config sdm845_cfg
= {
128 .sct_data
= sdm845_data
,
129 .size
= ARRAY_SIZE(sdm845_data
),
132 static struct llcc_drv_data
*drv_data
= (void *) -EPROBE_DEFER
;
135 * llcc_slice_getd - get llcc slice descriptor
136 * @uid: usecase_id for the client
138 * A pointer to llcc slice descriptor will be returned on success and
139 * and error pointer is returned on failure
141 struct llcc_slice_desc
*llcc_slice_getd(u32 uid
)
143 const struct llcc_slice_config
*cfg
;
144 struct llcc_slice_desc
*desc
;
147 if (IS_ERR(drv_data
))
148 return ERR_CAST(drv_data
);
151 sz
= drv_data
->cfg_size
;
153 for (count
= 0; cfg
&& count
< sz
; count
++, cfg
++)
154 if (cfg
->usecase_id
== uid
)
157 if (count
== sz
|| !cfg
)
158 return ERR_PTR(-ENODEV
);
160 desc
= kzalloc(sizeof(*desc
), GFP_KERNEL
);
162 return ERR_PTR(-ENOMEM
);
164 desc
->slice_id
= cfg
->slice_id
;
165 desc
->slice_size
= cfg
->max_cap
;
169 EXPORT_SYMBOL_GPL(llcc_slice_getd
);
172 * llcc_slice_putd - llcc slice descritpor
173 * @desc: Pointer to llcc slice descriptor
175 void llcc_slice_putd(struct llcc_slice_desc
*desc
)
177 if (!IS_ERR_OR_NULL(desc
))
180 EXPORT_SYMBOL_GPL(llcc_slice_putd
);
182 static int llcc_update_act_ctrl(u32 sid
,
183 u32 act_ctrl_reg_val
, u32 status
)
190 if (IS_ERR(drv_data
))
191 return PTR_ERR(drv_data
);
193 act_ctrl_reg
= LLCC_TRP_ACT_CTRLn(sid
);
194 status_reg
= LLCC_TRP_STATUSn(sid
);
196 /* Set the ACTIVE trigger */
197 act_ctrl_reg_val
|= ACT_CTRL_ACT_TRIG
;
198 ret
= regmap_write(drv_data
->bcast_regmap
, act_ctrl_reg
,
203 /* Clear the ACTIVE trigger */
204 act_ctrl_reg_val
&= ~ACT_CTRL_ACT_TRIG
;
205 ret
= regmap_write(drv_data
->bcast_regmap
, act_ctrl_reg
,
210 ret
= regmap_read_poll_timeout(drv_data
->bcast_regmap
, status_reg
,
211 slice_status
, !(slice_status
& status
),
212 0, LLCC_STATUS_READ_DELAY
);
217 * llcc_slice_activate - Activate the llcc slice
218 * @desc: Pointer to llcc slice descriptor
220 * A value of zero will be returned on success and a negative errno will
221 * be returned in error cases
223 int llcc_slice_activate(struct llcc_slice_desc
*desc
)
228 if (IS_ERR(drv_data
))
229 return PTR_ERR(drv_data
);
231 if (IS_ERR_OR_NULL(desc
))
234 mutex_lock(&drv_data
->lock
);
235 if (test_bit(desc
->slice_id
, drv_data
->bitmap
)) {
236 mutex_unlock(&drv_data
->lock
);
240 act_ctrl_val
= ACT_CTRL_OPCODE_ACTIVATE
<< ACT_CTRL_OPCODE_SHIFT
;
242 ret
= llcc_update_act_ctrl(desc
->slice_id
, act_ctrl_val
,
245 mutex_unlock(&drv_data
->lock
);
249 __set_bit(desc
->slice_id
, drv_data
->bitmap
);
250 mutex_unlock(&drv_data
->lock
);
254 EXPORT_SYMBOL_GPL(llcc_slice_activate
);
257 * llcc_slice_deactivate - Deactivate the llcc slice
258 * @desc: Pointer to llcc slice descriptor
260 * A value of zero will be returned on success and a negative errno will
261 * be returned in error cases
263 int llcc_slice_deactivate(struct llcc_slice_desc
*desc
)
268 if (IS_ERR(drv_data
))
269 return PTR_ERR(drv_data
);
271 if (IS_ERR_OR_NULL(desc
))
274 mutex_lock(&drv_data
->lock
);
275 if (!test_bit(desc
->slice_id
, drv_data
->bitmap
)) {
276 mutex_unlock(&drv_data
->lock
);
279 act_ctrl_val
= ACT_CTRL_OPCODE_DEACTIVATE
<< ACT_CTRL_OPCODE_SHIFT
;
281 ret
= llcc_update_act_ctrl(desc
->slice_id
, act_ctrl_val
,
284 mutex_unlock(&drv_data
->lock
);
288 __clear_bit(desc
->slice_id
, drv_data
->bitmap
);
289 mutex_unlock(&drv_data
->lock
);
293 EXPORT_SYMBOL_GPL(llcc_slice_deactivate
);
296 * llcc_get_slice_id - return the slice id
297 * @desc: Pointer to llcc slice descriptor
299 int llcc_get_slice_id(struct llcc_slice_desc
*desc
)
301 if (IS_ERR_OR_NULL(desc
))
304 return desc
->slice_id
;
306 EXPORT_SYMBOL_GPL(llcc_get_slice_id
);
309 * llcc_get_slice_size - return the slice id
310 * @desc: Pointer to llcc slice descriptor
312 size_t llcc_get_slice_size(struct llcc_slice_desc
*desc
)
314 if (IS_ERR_OR_NULL(desc
))
317 return desc
->slice_size
;
319 EXPORT_SYMBOL_GPL(llcc_get_slice_size
);
321 static int qcom_llcc_cfg_program(struct platform_device
*pdev
)
328 u32 max_cap_cacheline
;
331 const struct llcc_slice_config
*llcc_table
;
332 struct llcc_slice_desc desc
;
334 sz
= drv_data
->cfg_size
;
335 llcc_table
= drv_data
->cfg
;
337 for (i
= 0; i
< sz
; i
++) {
338 attr1_cfg
= LLCC_TRP_ATTR1_CFGn(llcc_table
[i
].slice_id
);
339 attr0_cfg
= LLCC_TRP_ATTR0_CFGn(llcc_table
[i
].slice_id
);
341 attr1_val
= llcc_table
[i
].cache_mode
;
342 attr1_val
|= llcc_table
[i
].probe_target_ways
<<
343 ATTR1_PROBE_TARGET_WAYS_SHIFT
;
344 attr1_val
|= llcc_table
[i
].fixed_size
<<
345 ATTR1_FIXED_SIZE_SHIFT
;
346 attr1_val
|= llcc_table
[i
].priority
<<
347 ATTR1_PRIORITY_SHIFT
;
349 max_cap_cacheline
= MAX_CAP_TO_BYTES(llcc_table
[i
].max_cap
);
351 /* LLCC instances can vary for each target.
352 * The SW writes to broadcast register which gets propagated
353 * to each llcc instace (llcc0,.. llccN).
354 * Since the size of the memory is divided equally amongst the
355 * llcc instances, we need to configure the max cap accordingly.
357 max_cap_cacheline
= max_cap_cacheline
/ drv_data
->num_banks
;
358 max_cap_cacheline
>>= CACHE_LINE_SIZE_SHIFT
;
359 attr1_val
|= max_cap_cacheline
<< ATTR1_MAX_CAP_SHIFT
;
361 attr0_val
= llcc_table
[i
].res_ways
& ATTR0_RES_WAYS_MASK
;
362 attr0_val
|= llcc_table
[i
].bonus_ways
<< ATTR0_BONUS_WAYS_SHIFT
;
364 ret
= regmap_write(drv_data
->bcast_regmap
, attr1_cfg
,
368 ret
= regmap_write(drv_data
->bcast_regmap
, attr0_cfg
,
372 if (llcc_table
[i
].activate_on_init
) {
373 desc
.slice_id
= llcc_table
[i
].slice_id
;
374 ret
= llcc_slice_activate(&desc
);
380 static int qcom_llcc_remove(struct platform_device
*pdev
)
382 /* Set the global pointer to a error code to avoid referencing it */
383 drv_data
= ERR_PTR(-ENODEV
);
387 static struct regmap
*qcom_llcc_init_mmio(struct platform_device
*pdev
,
390 struct resource
*res
;
392 struct regmap_config llcc_regmap_config
= {
399 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, name
);
401 return ERR_PTR(-ENODEV
);
403 base
= devm_ioremap_resource(&pdev
->dev
, res
);
405 return ERR_CAST(base
);
407 llcc_regmap_config
.name
= name
;
408 return devm_regmap_init_mmio(&pdev
->dev
, base
, &llcc_regmap_config
);
411 static int qcom_llcc_probe(struct platform_device
*pdev
)
414 struct device
*dev
= &pdev
->dev
;
416 struct platform_device
*llcc_edac
;
417 const struct qcom_llcc_config
*cfg
;
418 const struct llcc_slice_config
*llcc_cfg
;
421 drv_data
= devm_kzalloc(dev
, sizeof(*drv_data
), GFP_KERNEL
);
427 drv_data
->regmap
= qcom_llcc_init_mmio(pdev
, "llcc_base");
428 if (IS_ERR(drv_data
->regmap
)) {
429 ret
= PTR_ERR(drv_data
->regmap
);
433 drv_data
->bcast_regmap
=
434 qcom_llcc_init_mmio(pdev
, "llcc_broadcast_base");
435 if (IS_ERR(drv_data
->bcast_regmap
)) {
436 ret
= PTR_ERR(drv_data
->bcast_regmap
);
440 ret
= regmap_read(drv_data
->regmap
, LLCC_COMMON_STATUS0
,
445 num_banks
&= LLCC_LB_CNT_MASK
;
446 num_banks
>>= LLCC_LB_CNT_SHIFT
;
447 drv_data
->num_banks
= num_banks
;
449 cfg
= of_device_get_match_data(&pdev
->dev
);
450 llcc_cfg
= cfg
->sct_data
;
453 for (i
= 0; i
< sz
; i
++)
454 if (llcc_cfg
[i
].slice_id
> drv_data
->max_slices
)
455 drv_data
->max_slices
= llcc_cfg
[i
].slice_id
;
457 drv_data
->offsets
= devm_kcalloc(dev
, num_banks
, sizeof(u32
),
459 if (!drv_data
->offsets
) {
464 for (i
= 0; i
< num_banks
; i
++)
465 drv_data
->offsets
[i
] = i
* BANK_OFFSET_STRIDE
;
467 drv_data
->bitmap
= devm_kcalloc(dev
,
468 BITS_TO_LONGS(drv_data
->max_slices
), sizeof(unsigned long),
470 if (!drv_data
->bitmap
) {
475 drv_data
->cfg
= llcc_cfg
;
476 drv_data
->cfg_size
= sz
;
477 mutex_init(&drv_data
->lock
);
478 platform_set_drvdata(pdev
, drv_data
);
480 ret
= qcom_llcc_cfg_program(pdev
);
484 drv_data
->ecc_irq
= platform_get_irq(pdev
, 0);
485 if (drv_data
->ecc_irq
>= 0) {
486 llcc_edac
= platform_device_register_data(&pdev
->dev
,
487 "qcom_llcc_edac", -1, drv_data
,
489 if (IS_ERR(llcc_edac
))
490 dev_err(dev
, "Failed to register llcc edac driver\n");
495 drv_data
= ERR_PTR(-ENODEV
);
499 static const struct of_device_id qcom_llcc_of_match
[] = {
500 { .compatible
= "qcom,sc7180-llcc", .data
= &sc7180_cfg
},
501 { .compatible
= "qcom,sdm845-llcc", .data
= &sdm845_cfg
},
505 static struct platform_driver qcom_llcc_driver
= {
508 .of_match_table
= qcom_llcc_of_match
,
510 .probe
= qcom_llcc_probe
,
511 .remove
= qcom_llcc_remove
,
513 module_platform_driver(qcom_llcc_driver
);
515 MODULE_DESCRIPTION("Qualcomm Last Level Cache Controller");
516 MODULE_LICENSE("GPL v2");