diff options
Diffstat (limited to 'drivers/soc/qcom/llcc-slice.c')
-rw-r--r-- | drivers/soc/qcom/llcc-slice.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c index 80667f7be52c..8390bc006a31 100644 --- a/drivers/soc/qcom/llcc-slice.c +++ b/drivers/soc/qcom/llcc-slice.c | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | #define BANK_OFFSET_STRIDE 0x80000 | 47 | #define BANK_OFFSET_STRIDE 0x80000 |
48 | 48 | ||
49 | static struct llcc_drv_data *drv_data; | 49 | static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; |
50 | 50 | ||
51 | static const struct regmap_config llcc_regmap_config = { | 51 | static const struct regmap_config llcc_regmap_config = { |
52 | .reg_bits = 32, | 52 | .reg_bits = 32, |
@@ -68,6 +68,9 @@ struct llcc_slice_desc *llcc_slice_getd(u32 uid) | |||
68 | struct llcc_slice_desc *desc; | 68 | struct llcc_slice_desc *desc; |
69 | u32 sz, count; | 69 | u32 sz, count; |
70 | 70 | ||
71 | if (IS_ERR(drv_data)) | ||
72 | return ERR_CAST(drv_data); | ||
73 | |||
71 | cfg = drv_data->cfg; | 74 | cfg = drv_data->cfg; |
72 | sz = drv_data->cfg_size; | 75 | sz = drv_data->cfg_size; |
73 | 76 | ||
@@ -108,6 +111,9 @@ static int llcc_update_act_ctrl(u32 sid, | |||
108 | u32 slice_status; | 111 | u32 slice_status; |
109 | int ret; | 112 | int ret; |
110 | 113 | ||
114 | if (IS_ERR(drv_data)) | ||
115 | return PTR_ERR(drv_data); | ||
116 | |||
111 | act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); | 117 | act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); |
112 | status_reg = LLCC_TRP_STATUSn(sid); | 118 | status_reg = LLCC_TRP_STATUSn(sid); |
113 | 119 | ||
@@ -143,6 +149,9 @@ int llcc_slice_activate(struct llcc_slice_desc *desc) | |||
143 | int ret; | 149 | int ret; |
144 | u32 act_ctrl_val; | 150 | u32 act_ctrl_val; |
145 | 151 | ||
152 | If (IS_ERR(drv_data)) | ||
153 | return PTR_ERR(drv_data); | ||
154 | |||
146 | if (IS_ERR_OR_NULL(desc)) | 155 | if (IS_ERR_OR_NULL(desc)) |
147 | return -EINVAL; | 156 | return -EINVAL; |
148 | 157 | ||
@@ -180,6 +189,9 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc) | |||
180 | u32 act_ctrl_val; | 189 | u32 act_ctrl_val; |
181 | int ret; | 190 | int ret; |
182 | 191 | ||
192 | If (IS_ERR(drv_data)) | ||
193 | return PTR_ERR(drv_data); | ||
194 | |||
183 | if (IS_ERR_OR_NULL(desc)) | 195 | if (IS_ERR_OR_NULL(desc)) |
184 | return -EINVAL; | 196 | return -EINVAL; |
185 | 197 | ||
@@ -289,6 +301,14 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev) | |||
289 | return ret; | 301 | return ret; |
290 | } | 302 | } |
291 | 303 | ||
304 | int qcom_llcc_remove(struct platform_device *pdev) | ||
305 | { | ||
306 | /* Set the global pointer to a error code to avoid referencing it */ | ||
307 | drv_data = ERR_PTR(-ENODEV); | ||
308 | return 0; | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(qcom_llcc_remove); | ||
311 | |||
292 | int qcom_llcc_probe(struct platform_device *pdev, | 312 | int qcom_llcc_probe(struct platform_device *pdev, |
293 | const struct llcc_slice_config *llcc_cfg, u32 sz) | 313 | const struct llcc_slice_config *llcc_cfg, u32 sz) |
294 | { | 314 | { |
@@ -300,35 +320,45 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
300 | struct platform_device *llcc_edac; | 320 | struct platform_device *llcc_edac; |
301 | 321 | ||
302 | drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); | 322 | drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); |
303 | if (!drv_data) | 323 | if (!drv_data) { |
304 | return -ENOMEM; | 324 | ret = -ENOMEM; |
325 | goto err; | ||
326 | } | ||
305 | 327 | ||
306 | llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 328 | llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
307 | "llcc_base"); | 329 | "llcc_base"); |
308 | llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res); | 330 | llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res); |
309 | if (IS_ERR(llcc_banks_base)) | 331 | if (IS_ERR(llcc_banks_base)) { |
310 | return PTR_ERR(llcc_banks_base); | 332 | ret = PTR_ERR(llcc_banks_base); |
333 | goto err; | ||
334 | } | ||
311 | 335 | ||
312 | drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base, | 336 | drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base, |
313 | &llcc_regmap_config); | 337 | &llcc_regmap_config); |
314 | if (IS_ERR(drv_data->regmap)) | 338 | if (IS_ERR(drv_data->regmap)) { |
315 | return PTR_ERR(drv_data->regmap); | 339 | ret = PTR_ERR(drv_data->regmap); |
340 | goto err; | ||
341 | } | ||
316 | 342 | ||
317 | llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 343 | llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
318 | "llcc_broadcast_base"); | 344 | "llcc_broadcast_base"); |
319 | llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res); | 345 | llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res); |
320 | if (IS_ERR(llcc_bcast_base)) | 346 | if (IS_ERR(llcc_bcast_base)) { |
321 | return PTR_ERR(llcc_bcast_base); | 347 | ret = PTR_ERR(llcc_bcast_base); |
348 | goto err; | ||
349 | } | ||
322 | 350 | ||
323 | drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base, | 351 | drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base, |
324 | &llcc_regmap_config); | 352 | &llcc_regmap_config); |
325 | if (IS_ERR(drv_data->bcast_regmap)) | 353 | if (IS_ERR(drv_data->bcast_regmap)) { |
326 | return PTR_ERR(drv_data->bcast_regmap); | 354 | ret = PTR_ERR(drv_data->bcast_regmap); |
355 | goto err; | ||
356 | } | ||
327 | 357 | ||
328 | ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, | 358 | ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, |
329 | &num_banks); | 359 | &num_banks); |
330 | if (ret) | 360 | if (ret) |
331 | return ret; | 361 | goto err; |
332 | 362 | ||
333 | num_banks &= LLCC_LB_CNT_MASK; | 363 | num_banks &= LLCC_LB_CNT_MASK; |
334 | num_banks >>= LLCC_LB_CNT_SHIFT; | 364 | num_banks >>= LLCC_LB_CNT_SHIFT; |
@@ -340,8 +370,10 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
340 | 370 | ||
341 | drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32), | 371 | drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32), |
342 | GFP_KERNEL); | 372 | GFP_KERNEL); |
343 | if (!drv_data->offsets) | 373 | if (!drv_data->offsets) { |
344 | return -ENOMEM; | 374 | ret = -ENOMEM; |
375 | goto err; | ||
376 | } | ||
345 | 377 | ||
346 | for (i = 0; i < num_banks; i++) | 378 | for (i = 0; i < num_banks; i++) |
347 | drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; | 379 | drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; |
@@ -349,8 +381,10 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
349 | drv_data->bitmap = devm_kcalloc(dev, | 381 | drv_data->bitmap = devm_kcalloc(dev, |
350 | BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), | 382 | BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), |
351 | GFP_KERNEL); | 383 | GFP_KERNEL); |
352 | if (!drv_data->bitmap) | 384 | if (!drv_data->bitmap) { |
353 | return -ENOMEM; | 385 | ret = -ENOMEM; |
386 | goto err; | ||
387 | } | ||
354 | 388 | ||
355 | drv_data->cfg = llcc_cfg; | 389 | drv_data->cfg = llcc_cfg; |
356 | drv_data->cfg_size = sz; | 390 | drv_data->cfg_size = sz; |
@@ -359,7 +393,7 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
359 | 393 | ||
360 | ret = qcom_llcc_cfg_program(pdev); | 394 | ret = qcom_llcc_cfg_program(pdev); |
361 | if (ret) | 395 | if (ret) |
362 | return ret; | 396 | goto err; |
363 | 397 | ||
364 | drv_data->ecc_irq = platform_get_irq(pdev, 0); | 398 | drv_data->ecc_irq = platform_get_irq(pdev, 0); |
365 | if (drv_data->ecc_irq >= 0) { | 399 | if (drv_data->ecc_irq >= 0) { |
@@ -370,6 +404,9 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
370 | dev_err(dev, "Failed to register llcc edac driver\n"); | 404 | dev_err(dev, "Failed to register llcc edac driver\n"); |
371 | } | 405 | } |
372 | 406 | ||
407 | return 0; | ||
408 | err: | ||
409 | drv_data = ERR_PTR(-ENODEV); | ||
373 | return ret; | 410 | return ret; |
374 | } | 411 | } |
375 | EXPORT_SYMBOL_GPL(qcom_llcc_probe); | 412 | EXPORT_SYMBOL_GPL(qcom_llcc_probe); |