diff options
| -rw-r--r-- | drivers/soc/qcom/llcc-sdm845.c | 6 | ||||
| -rw-r--r-- | drivers/soc/qcom/llcc-slice.c | 71 | ||||
| -rw-r--r-- | include/linux/soc/qcom/llcc-qcom.h | 6 |
3 files changed, 66 insertions, 17 deletions
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c index 2e1e4f0a5db8..86600d97c36d 100644 --- a/drivers/soc/qcom/llcc-sdm845.c +++ b/drivers/soc/qcom/llcc-sdm845.c | |||
| @@ -71,6 +71,11 @@ static struct llcc_slice_config sdm845_data[] = { | |||
| 71 | SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0), | 71 | SCT_ENTRY(LLCC_AUDHW, 22, 1024, 1, 1, 0xffc, 0x2, 0, 0, 1, 1, 0), |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | static int sdm845_qcom_llcc_remove(struct platform_device *pdev) | ||
| 75 | { | ||
| 76 | return qcom_llcc_remove(pdev); | ||
| 77 | } | ||
| 78 | |||
| 74 | static int sdm845_qcom_llcc_probe(struct platform_device *pdev) | 79 | static int sdm845_qcom_llcc_probe(struct platform_device *pdev) |
| 75 | { | 80 | { |
| 76 | return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data)); | 81 | return qcom_llcc_probe(pdev, sdm845_data, ARRAY_SIZE(sdm845_data)); |
| @@ -87,6 +92,7 @@ static struct platform_driver sdm845_qcom_llcc_driver = { | |||
| 87 | .of_match_table = sdm845_qcom_llcc_of_match, | 92 | .of_match_table = sdm845_qcom_llcc_of_match, |
| 88 | }, | 93 | }, |
| 89 | .probe = sdm845_qcom_llcc_probe, | 94 | .probe = sdm845_qcom_llcc_probe, |
| 95 | .remove = sdm845_qcom_llcc_remove, | ||
| 90 | }; | 96 | }; |
| 91 | module_platform_driver(sdm845_qcom_llcc_driver); | 97 | module_platform_driver(sdm845_qcom_llcc_driver); |
| 92 | 98 | ||
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); |
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h index 69c285b1c990..eb71a50b8afc 100644 --- a/include/linux/soc/qcom/llcc-qcom.h +++ b/include/linux/soc/qcom/llcc-qcom.h | |||
| @@ -162,6 +162,12 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc); | |||
| 162 | */ | 162 | */ |
| 163 | int qcom_llcc_probe(struct platform_device *pdev, | 163 | int qcom_llcc_probe(struct platform_device *pdev, |
| 164 | const struct llcc_slice_config *table, u32 sz); | 164 | const struct llcc_slice_config *table, u32 sz); |
| 165 | |||
| 166 | /** | ||
| 167 | * qcom_llcc_remove - remove the sct table | ||
| 168 | * @pdev: Platform device pointer | ||
| 169 | */ | ||
| 170 | int qcom_llcc_remove(struct platform_device *pdev); | ||
| 165 | #else | 171 | #else |
| 166 | static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid) | 172 | static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid) |
| 167 | { | 173 | { |
