1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2017-2018, 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>
14 #include <linux/of_device.h>
15 #include <linux/regmap.h>
16 #include <linux/sizes.h>
17 #include <linux/slab.h>
18 #include <linux/soc/qcom/llcc-qcom.h>
20 #define ACTIVATE BIT(0)
21 #define DEACTIVATE BIT(1)
22 #define ACT_CTRL_OPCODE_ACTIVATE BIT(0)
23 #define ACT_CTRL_OPCODE_DEACTIVATE BIT(1)
24 #define ACT_CTRL_ACT_TRIG BIT(0)
25 #define ACT_CTRL_OPCODE_SHIFT 0x01
26 #define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x02
27 #define ATTR1_FIXED_SIZE_SHIFT 0x03
28 #define ATTR1_PRIORITY_SHIFT 0x04
29 #define ATTR1_MAX_CAP_SHIFT 0x10
30 #define ATTR0_RES_WAYS_MASK GENMASK(11, 0)
31 #define ATTR0_BONUS_WAYS_MASK GENMASK(27, 16)
32 #define ATTR0_BONUS_WAYS_SHIFT 0x10
33 #define LLCC_STATUS_READ_DELAY 100
35 #define CACHE_LINE_SIZE_SHIFT 6
37 #define LLCC_COMMON_STATUS0 0x0003000c
38 #define LLCC_LB_CNT_MASK GENMASK(31, 28)
39 #define LLCC_LB_CNT_SHIFT 28
41 #define MAX_CAP_TO_BYTES(n) (n * SZ_1K)
42 #define LLCC_TRP_ACT_CTRLn(n) (n * SZ_4K)
43 #define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K)
44 #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n)
45 #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n)
47 #define BANK_OFFSET_STRIDE 0x80000
49 static struct llcc_drv_data
*drv_data
= (void *) -EPROBE_DEFER
;
51 static const struct regmap_config llcc_regmap_config
= {
59 * llcc_slice_getd - get llcc slice descriptor
60 * @uid: usecase_id for the client
62 * A pointer to llcc slice descriptor will be returned on success and
63 * and error pointer is returned on failure
65 struct llcc_slice_desc
*llcc_slice_getd(u32 uid
)
67 const struct llcc_slice_config
*cfg
;
68 struct llcc_slice_desc
*desc
;
72 return ERR_CAST(drv_data
);
75 sz
= drv_data
->cfg_size
;
77 for (count
= 0; cfg
&& count
< sz
; count
++, cfg
++)
78 if (cfg
->usecase_id
== uid
)
81 if (count
== sz
|| !cfg
)
82 return ERR_PTR(-ENODEV
);
84 desc
= kzalloc(sizeof(*desc
), GFP_KERNEL
);
86 return ERR_PTR(-ENOMEM
);
88 desc
->slice_id
= cfg
->slice_id
;
89 desc
->slice_size
= cfg
->max_cap
;
93 EXPORT_SYMBOL_GPL(llcc_slice_getd
);
96 * llcc_slice_putd - llcc slice descritpor
97 * @desc: Pointer to llcc slice descriptor
99 void llcc_slice_putd(struct llcc_slice_desc
*desc
)
101 if (!IS_ERR_OR_NULL(desc
))
104 EXPORT_SYMBOL_GPL(llcc_slice_putd
);
106 static int llcc_update_act_ctrl(u32 sid
,
107 u32 act_ctrl_reg_val
, u32 status
)
114 if (IS_ERR(drv_data
))
115 return PTR_ERR(drv_data
);
117 act_ctrl_reg
= LLCC_TRP_ACT_CTRLn(sid
);
118 status_reg
= LLCC_TRP_STATUSn(sid
);
120 /* Set the ACTIVE trigger */
121 act_ctrl_reg_val
|= ACT_CTRL_ACT_TRIG
;
122 ret
= regmap_write(drv_data
->bcast_regmap
, act_ctrl_reg
,
127 /* Clear the ACTIVE trigger */
128 act_ctrl_reg_val
&= ~ACT_CTRL_ACT_TRIG
;
129 ret
= regmap_write(drv_data
->bcast_regmap
, act_ctrl_reg
,
134 ret
= regmap_read_poll_timeout(drv_data
->bcast_regmap
, status_reg
,
135 slice_status
, !(slice_status
& status
),
136 0, LLCC_STATUS_READ_DELAY
);
141 * llcc_slice_activate - Activate the llcc slice
142 * @desc: Pointer to llcc slice descriptor
144 * A value of zero will be returned on success and a negative errno will
145 * be returned in error cases
147 int llcc_slice_activate(struct llcc_slice_desc
*desc
)
152 if (IS_ERR(drv_data
))
153 return PTR_ERR(drv_data
);
155 if (IS_ERR_OR_NULL(desc
))
158 mutex_lock(&drv_data
->lock
);
159 if (test_bit(desc
->slice_id
, drv_data
->bitmap
)) {
160 mutex_unlock(&drv_data
->lock
);
164 act_ctrl_val
= ACT_CTRL_OPCODE_ACTIVATE
<< ACT_CTRL_OPCODE_SHIFT
;
166 ret
= llcc_update_act_ctrl(desc
->slice_id
, act_ctrl_val
,
169 mutex_unlock(&drv_data
->lock
);
173 __set_bit(desc
->slice_id
, drv_data
->bitmap
);
174 mutex_unlock(&drv_data
->lock
);
178 EXPORT_SYMBOL_GPL(llcc_slice_activate
);
181 * llcc_slice_deactivate - Deactivate the llcc slice
182 * @desc: Pointer to llcc slice descriptor
184 * A value of zero will be returned on success and a negative errno will
185 * be returned in error cases
187 int llcc_slice_deactivate(struct llcc_slice_desc
*desc
)
192 if (IS_ERR(drv_data
))
193 return PTR_ERR(drv_data
);
195 if (IS_ERR_OR_NULL(desc
))
198 mutex_lock(&drv_data
->lock
);
199 if (!test_bit(desc
->slice_id
, drv_data
->bitmap
)) {
200 mutex_unlock(&drv_data
->lock
);
203 act_ctrl_val
= ACT_CTRL_OPCODE_DEACTIVATE
<< ACT_CTRL_OPCODE_SHIFT
;
205 ret
= llcc_update_act_ctrl(desc
->slice_id
, act_ctrl_val
,
208 mutex_unlock(&drv_data
->lock
);
212 __clear_bit(desc
->slice_id
, drv_data
->bitmap
);
213 mutex_unlock(&drv_data
->lock
);
217 EXPORT_SYMBOL_GPL(llcc_slice_deactivate
);
220 * llcc_get_slice_id - return the slice id
221 * @desc: Pointer to llcc slice descriptor
223 int llcc_get_slice_id(struct llcc_slice_desc
*desc
)
225 if (IS_ERR_OR_NULL(desc
))
228 return desc
->slice_id
;
230 EXPORT_SYMBOL_GPL(llcc_get_slice_id
);
233 * llcc_get_slice_size - return the slice id
234 * @desc: Pointer to llcc slice descriptor
236 size_t llcc_get_slice_size(struct llcc_slice_desc
*desc
)
238 if (IS_ERR_OR_NULL(desc
))
241 return desc
->slice_size
;
243 EXPORT_SYMBOL_GPL(llcc_get_slice_size
);
245 static int qcom_llcc_cfg_program(struct platform_device
*pdev
)
252 u32 max_cap_cacheline
;
255 const struct llcc_slice_config
*llcc_table
;
256 struct llcc_slice_desc desc
;
258 sz
= drv_data
->cfg_size
;
259 llcc_table
= drv_data
->cfg
;
261 for (i
= 0; i
< sz
; i
++) {
262 attr1_cfg
= LLCC_TRP_ATTR1_CFGn(llcc_table
[i
].slice_id
);
263 attr0_cfg
= LLCC_TRP_ATTR0_CFGn(llcc_table
[i
].slice_id
);
265 attr1_val
= llcc_table
[i
].cache_mode
;
266 attr1_val
|= llcc_table
[i
].probe_target_ways
<<
267 ATTR1_PROBE_TARGET_WAYS_SHIFT
;
268 attr1_val
|= llcc_table
[i
].fixed_size
<<
269 ATTR1_FIXED_SIZE_SHIFT
;
270 attr1_val
|= llcc_table
[i
].priority
<<
271 ATTR1_PRIORITY_SHIFT
;
273 max_cap_cacheline
= MAX_CAP_TO_BYTES(llcc_table
[i
].max_cap
);
275 /* LLCC instances can vary for each target.
276 * The SW writes to broadcast register which gets propagated
277 * to each llcc instace (llcc0,.. llccN).
278 * Since the size of the memory is divided equally amongst the
279 * llcc instances, we need to configure the max cap accordingly.
281 max_cap_cacheline
= max_cap_cacheline
/ drv_data
->num_banks
;
282 max_cap_cacheline
>>= CACHE_LINE_SIZE_SHIFT
;
283 attr1_val
|= max_cap_cacheline
<< ATTR1_MAX_CAP_SHIFT
;
285 attr0_val
= llcc_table
[i
].res_ways
& ATTR0_RES_WAYS_MASK
;
286 attr0_val
|= llcc_table
[i
].bonus_ways
<< ATTR0_BONUS_WAYS_SHIFT
;
288 ret
= regmap_write(drv_data
->bcast_regmap
, attr1_cfg
,
292 ret
= regmap_write(drv_data
->bcast_regmap
, attr0_cfg
,
296 if (llcc_table
[i
].activate_on_init
) {
297 desc
.slice_id
= llcc_table
[i
].slice_id
;
298 ret
= llcc_slice_activate(&desc
);
304 int qcom_llcc_remove(struct platform_device
*pdev
)
306 /* Set the global pointer to a error code to avoid referencing it */
307 drv_data
= ERR_PTR(-ENODEV
);
310 EXPORT_SYMBOL_GPL(qcom_llcc_remove
);
312 static struct regmap
*qcom_llcc_init_mmio(struct platform_device
*pdev
,
315 struct resource
*res
;
318 res
= platform_get_resource_byname(pdev
, IORESOURCE_MEM
, name
);
320 return ERR_PTR(-ENODEV
);
322 base
= devm_ioremap_resource(&pdev
->dev
, res
);
324 return ERR_CAST(base
);
326 return devm_regmap_init_mmio(&pdev
->dev
, base
, &llcc_regmap_config
);
329 int qcom_llcc_probe(struct platform_device
*pdev
,
330 const struct llcc_slice_config
*llcc_cfg
, u32 sz
)
333 struct device
*dev
= &pdev
->dev
;
335 struct platform_device
*llcc_edac
;
337 drv_data
= devm_kzalloc(dev
, sizeof(*drv_data
), GFP_KERNEL
);
343 drv_data
->regmap
= qcom_llcc_init_mmio(pdev
, "llcc_base");
344 if (IS_ERR(drv_data
->regmap
)) {
345 ret
= PTR_ERR(drv_data
->regmap
);
349 drv_data
->bcast_regmap
=
350 qcom_llcc_init_mmio(pdev
, "llcc_broadcast_base");
351 if (IS_ERR(drv_data
->bcast_regmap
)) {
352 ret
= PTR_ERR(drv_data
->bcast_regmap
);
356 ret
= regmap_read(drv_data
->regmap
, LLCC_COMMON_STATUS0
,
361 num_banks
&= LLCC_LB_CNT_MASK
;
362 num_banks
>>= LLCC_LB_CNT_SHIFT
;
363 drv_data
->num_banks
= num_banks
;
365 for (i
= 0; i
< sz
; i
++)
366 if (llcc_cfg
[i
].slice_id
> drv_data
->max_slices
)
367 drv_data
->max_slices
= llcc_cfg
[i
].slice_id
;
369 drv_data
->offsets
= devm_kcalloc(dev
, num_banks
, sizeof(u32
),
371 if (!drv_data
->offsets
) {
376 for (i
= 0; i
< num_banks
; i
++)
377 drv_data
->offsets
[i
] = i
* BANK_OFFSET_STRIDE
;
379 drv_data
->bitmap
= devm_kcalloc(dev
,
380 BITS_TO_LONGS(drv_data
->max_slices
), sizeof(unsigned long),
382 if (!drv_data
->bitmap
) {
387 drv_data
->cfg
= llcc_cfg
;
388 drv_data
->cfg_size
= sz
;
389 mutex_init(&drv_data
->lock
);
390 platform_set_drvdata(pdev
, drv_data
);
392 ret
= qcom_llcc_cfg_program(pdev
);
396 drv_data
->ecc_irq
= platform_get_irq(pdev
, 0);
397 if (drv_data
->ecc_irq
>= 0) {
398 llcc_edac
= platform_device_register_data(&pdev
->dev
,
399 "qcom_llcc_edac", -1, drv_data
,
401 if (IS_ERR(llcc_edac
))
402 dev_err(dev
, "Failed to register llcc edac driver\n");
407 drv_data
= ERR_PTR(-ENODEV
);
410 EXPORT_SYMBOL_GPL(qcom_llcc_probe
);
411 MODULE_LICENSE("GPL v2");
412 MODULE_DESCRIPTION("Qualcomm Last Level Cache Controller");