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;
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 sz = drv_data->cfg_size;
74 for (count = 0; cfg && count < sz; count++, cfg++)
75 if (cfg->usecase_id == uid)
78 if (count == sz || !cfg)
79 return ERR_PTR(-ENODEV);
81 desc = kzalloc(sizeof(*desc), GFP_KERNEL);
83 return ERR_PTR(-ENOMEM);
85 desc->slice_id = cfg->slice_id;
86 desc->slice_size = cfg->max_cap;
90 EXPORT_SYMBOL_GPL(llcc_slice_getd);
93 * llcc_slice_putd - llcc slice descritpor
94 * @desc: Pointer to llcc slice descriptor
96 void llcc_slice_putd(struct llcc_slice_desc *desc)
100 EXPORT_SYMBOL_GPL(llcc_slice_putd);
102 static int llcc_update_act_ctrl(u32 sid,
103 u32 act_ctrl_reg_val, u32 status)
110 act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
111 status_reg = LLCC_TRP_STATUSn(sid);
113 /* Set the ACTIVE trigger */
114 act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG;
115 ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
120 /* Clear the ACTIVE trigger */
121 act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
122 ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
127 ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
128 slice_status, !(slice_status & status),
129 0, LLCC_STATUS_READ_DELAY);
134 * llcc_slice_activate - Activate the llcc slice
135 * @desc: Pointer to llcc slice descriptor
137 * A value of zero will be returned on success and a negative errno will
138 * be returned in error cases
140 int llcc_slice_activate(struct llcc_slice_desc *desc)
145 mutex_lock(&drv_data->lock);
146 if (test_bit(desc->slice_id, drv_data->bitmap)) {
147 mutex_unlock(&drv_data->lock);
151 act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT;
153 ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
156 mutex_unlock(&drv_data->lock);
160 __set_bit(desc->slice_id, drv_data->bitmap);
161 mutex_unlock(&drv_data->lock);
165 EXPORT_SYMBOL_GPL(llcc_slice_activate);
168 * llcc_slice_deactivate - Deactivate the llcc slice
169 * @desc: Pointer to llcc slice descriptor
171 * A value of zero will be returned on success and a negative errno will
172 * be returned in error cases
174 int llcc_slice_deactivate(struct llcc_slice_desc *desc)
179 mutex_lock(&drv_data->lock);
180 if (!test_bit(desc->slice_id, drv_data->bitmap)) {
181 mutex_unlock(&drv_data->lock);
184 act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
186 ret = llcc_update_act_ctrl(desc->slice_id, act_ctrl_val,
189 mutex_unlock(&drv_data->lock);
193 __clear_bit(desc->slice_id, drv_data->bitmap);
194 mutex_unlock(&drv_data->lock);
198 EXPORT_SYMBOL_GPL(llcc_slice_deactivate);
201 * llcc_get_slice_id - return the slice id
202 * @desc: Pointer to llcc slice descriptor
204 int llcc_get_slice_id(struct llcc_slice_desc *desc)
206 return desc->slice_id;
208 EXPORT_SYMBOL_GPL(llcc_get_slice_id);
211 * llcc_get_slice_size - return the slice id
212 * @desc: Pointer to llcc slice descriptor
214 size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
216 return desc->slice_size;
218 EXPORT_SYMBOL_GPL(llcc_get_slice_size);
220 static int qcom_llcc_cfg_program(struct platform_device *pdev)
227 u32 max_cap_cacheline;
230 const struct llcc_slice_config *llcc_table;
231 struct llcc_slice_desc desc;
233 sz = drv_data->cfg_size;
234 llcc_table = drv_data->cfg;
236 for (i = 0; i < sz; i++) {
237 attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
238 attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
240 attr1_val = llcc_table[i].cache_mode;
241 attr1_val |= llcc_table[i].probe_target_ways <<
242 ATTR1_PROBE_TARGET_WAYS_SHIFT;
243 attr1_val |= llcc_table[i].fixed_size <<
244 ATTR1_FIXED_SIZE_SHIFT;
245 attr1_val |= llcc_table[i].priority <<
246 ATTR1_PRIORITY_SHIFT;
248 max_cap_cacheline = MAX_CAP_TO_BYTES(llcc_table[i].max_cap);
250 /* LLCC instances can vary for each target.
251 * The SW writes to broadcast register which gets propagated
252 * to each llcc instace (llcc0,.. llccN).
253 * Since the size of the memory is divided equally amongst the
254 * llcc instances, we need to configure the max cap accordingly.
256 max_cap_cacheline = max_cap_cacheline / drv_data->num_banks;
257 max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
258 attr1_val |= max_cap_cacheline << ATTR1_MAX_CAP_SHIFT;
260 attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
261 attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
263 ret = regmap_write(drv_data->bcast_regmap, attr1_cfg,
267 ret = regmap_write(drv_data->bcast_regmap, attr0_cfg,
271 if (llcc_table[i].activate_on_init) {
272 desc.slice_id = llcc_table[i].slice_id;
273 ret = llcc_slice_activate(&desc);
279 int qcom_llcc_probe(struct platform_device *pdev,
280 const struct llcc_slice_config *llcc_cfg, u32 sz)
283 struct device *dev = &pdev->dev;
284 struct resource *llcc_banks_res, *llcc_bcast_res;
285 void __iomem *llcc_banks_base, *llcc_bcast_base;
287 struct platform_device *llcc_edac;
289 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
293 llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
295 llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res);
296 if (IS_ERR(llcc_banks_base))
297 return PTR_ERR(llcc_banks_base);
299 drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base,
300 &llcc_regmap_config);
301 if (IS_ERR(drv_data->regmap))
302 return PTR_ERR(drv_data->regmap);
304 llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
305 "llcc_broadcast_base");
306 llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res);
307 if (IS_ERR(llcc_bcast_base))
308 return PTR_ERR(llcc_bcast_base);
310 drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base,
311 &llcc_regmap_config);
312 if (IS_ERR(drv_data->bcast_regmap))
313 return PTR_ERR(drv_data->bcast_regmap);
315 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
320 num_banks &= LLCC_LB_CNT_MASK;
321 num_banks >>= LLCC_LB_CNT_SHIFT;
322 drv_data->num_banks = num_banks;
324 for (i = 0; i < sz; i++)
325 if (llcc_cfg[i].slice_id > drv_data->max_slices)
326 drv_data->max_slices = llcc_cfg[i].slice_id;
328 drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32),
330 if (!drv_data->offsets)
333 for (i = 0; i < num_banks; i++)
334 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
336 drv_data->bitmap = devm_kcalloc(dev,
337 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
339 if (!drv_data->bitmap)
342 drv_data->cfg = llcc_cfg;
343 drv_data->cfg_size = sz;
344 mutex_init(&drv_data->lock);
345 platform_set_drvdata(pdev, drv_data);
347 ret = qcom_llcc_cfg_program(pdev);
351 drv_data->ecc_irq = platform_get_irq(pdev, 0);
352 if (drv_data->ecc_irq >= 0) {
353 llcc_edac = platform_device_register_data(&pdev->dev,
354 "qcom_llcc_edac", -1, drv_data,
356 if (IS_ERR(llcc_edac))
357 dev_err(dev, "Failed to register llcc edac driver\n");
362 EXPORT_SYMBOL_GPL(qcom_llcc_probe);
364 MODULE_LICENSE("GPL v2");