diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2019-02-15 14:49:56 -0500 |
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2019-02-15 14:50:20 -0500 |
| commit | 5aa8f495d6ef70dbb200093a31d995ba96fcccd6 (patch) | |
| tree | 8febcc3bd28dcba6b2aa6f796b8325a5ac5c6310 /drivers | |
| parent | 50b0225bf412df3cdeb2dc89b7e4b1119e30bedb (diff) | |
| parent | ed10a259faa1bbdf77b8c2153b274b70c90cbb35 (diff) | |
Merge tag 'qcom-drivers-for-5.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux into arm/drivers
Qualcomm ARM Based Driver Updates for v5.1 - Part 2
* Fixups/Cleanup for Qualcomm LLCC
* tag 'qcom-drivers-for-5.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux:
qcom: soc: llcc-slice: Consolidate some code
qcom: soc: llcc-slice: Clear the global drv_data pointer on error
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/soc/qcom/llcc-sdm845.c | 6 | ||||
| -rw-r--r-- | drivers/soc/qcom/llcc-slice.c | 101 |
2 files changed, 74 insertions, 33 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..83a263926a25 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,46 +301,62 @@ 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 | |||
| 312 | static struct regmap *qcom_llcc_init_mmio(struct platform_device *pdev, | ||
| 313 | const char *name) | ||
| 314 | { | ||
| 315 | struct resource *res; | ||
| 316 | void __iomem *base; | ||
| 317 | |||
| 318 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); | ||
| 319 | if (!res) | ||
| 320 | return ERR_PTR(-ENODEV); | ||
| 321 | |||
| 322 | base = devm_ioremap_resource(&pdev->dev, res); | ||
| 323 | if (IS_ERR(base)) | ||
| 324 | return ERR_CAST(base); | ||
| 325 | |||
| 326 | return devm_regmap_init_mmio(&pdev->dev, base, &llcc_regmap_config); | ||
| 327 | } | ||
| 328 | |||
| 292 | int qcom_llcc_probe(struct platform_device *pdev, | 329 | int qcom_llcc_probe(struct platform_device *pdev, |
| 293 | const struct llcc_slice_config *llcc_cfg, u32 sz) | 330 | const struct llcc_slice_config *llcc_cfg, u32 sz) |
| 294 | { | 331 | { |
| 295 | u32 num_banks; | 332 | u32 num_banks; |
| 296 | struct device *dev = &pdev->dev; | 333 | struct device *dev = &pdev->dev; |
| 297 | struct resource *llcc_banks_res, *llcc_bcast_res; | ||
| 298 | void __iomem *llcc_banks_base, *llcc_bcast_base; | ||
| 299 | int ret, i; | 334 | int ret, i; |
| 300 | struct platform_device *llcc_edac; | 335 | struct platform_device *llcc_edac; |
| 301 | 336 | ||
| 302 | drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); | 337 | drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); |
| 303 | if (!drv_data) | 338 | if (!drv_data) { |
| 304 | return -ENOMEM; | 339 | ret = -ENOMEM; |
| 305 | 340 | goto err; | |
| 306 | llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 341 | } |
| 307 | "llcc_base"); | 342 | |
| 308 | llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res); | 343 | drv_data->regmap = qcom_llcc_init_mmio(pdev, "llcc_base"); |
| 309 | if (IS_ERR(llcc_banks_base)) | 344 | if (IS_ERR(drv_data->regmap)) { |
| 310 | return PTR_ERR(llcc_banks_base); | 345 | ret = PTR_ERR(drv_data->regmap); |
| 311 | 346 | goto err; | |
| 312 | drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base, | 347 | } |
| 313 | &llcc_regmap_config); | 348 | |
| 314 | if (IS_ERR(drv_data->regmap)) | 349 | drv_data->bcast_regmap = |
| 315 | return PTR_ERR(drv_data->regmap); | 350 | qcom_llcc_init_mmio(pdev, "llcc_broadcast_base"); |
| 316 | 351 | if (IS_ERR(drv_data->bcast_regmap)) { | |
| 317 | llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 352 | ret = PTR_ERR(drv_data->bcast_regmap); |
| 318 | "llcc_broadcast_base"); | 353 | goto err; |
| 319 | llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res); | 354 | } |
| 320 | if (IS_ERR(llcc_bcast_base)) | ||
| 321 | return PTR_ERR(llcc_bcast_base); | ||
| 322 | |||
| 323 | drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base, | ||
| 324 | &llcc_regmap_config); | ||
| 325 | if (IS_ERR(drv_data->bcast_regmap)) | ||
| 326 | return PTR_ERR(drv_data->bcast_regmap); | ||
| 327 | 355 | ||
| 328 | ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, | 356 | ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, |
| 329 | &num_banks); | 357 | &num_banks); |
| 330 | if (ret) | 358 | if (ret) |
| 331 | return ret; | 359 | goto err; |
| 332 | 360 | ||
| 333 | num_banks &= LLCC_LB_CNT_MASK; | 361 | num_banks &= LLCC_LB_CNT_MASK; |
| 334 | num_banks >>= LLCC_LB_CNT_SHIFT; | 362 | num_banks >>= LLCC_LB_CNT_SHIFT; |
| @@ -340,8 +368,10 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
| 340 | 368 | ||
| 341 | drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32), | 369 | drv_data->offsets = devm_kcalloc(dev, num_banks, sizeof(u32), |
| 342 | GFP_KERNEL); | 370 | GFP_KERNEL); |
| 343 | if (!drv_data->offsets) | 371 | if (!drv_data->offsets) { |
| 344 | return -ENOMEM; | 372 | ret = -ENOMEM; |
| 373 | goto err; | ||
| 374 | } | ||
| 345 | 375 | ||
| 346 | for (i = 0; i < num_banks; i++) | 376 | for (i = 0; i < num_banks; i++) |
| 347 | drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; | 377 | drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; |
| @@ -349,8 +379,10 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
| 349 | drv_data->bitmap = devm_kcalloc(dev, | 379 | drv_data->bitmap = devm_kcalloc(dev, |
| 350 | BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), | 380 | BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), |
| 351 | GFP_KERNEL); | 381 | GFP_KERNEL); |
| 352 | if (!drv_data->bitmap) | 382 | if (!drv_data->bitmap) { |
| 353 | return -ENOMEM; | 383 | ret = -ENOMEM; |
| 384 | goto err; | ||
| 385 | } | ||
| 354 | 386 | ||
| 355 | drv_data->cfg = llcc_cfg; | 387 | drv_data->cfg = llcc_cfg; |
| 356 | drv_data->cfg_size = sz; | 388 | drv_data->cfg_size = sz; |
| @@ -359,7 +391,7 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
| 359 | 391 | ||
| 360 | ret = qcom_llcc_cfg_program(pdev); | 392 | ret = qcom_llcc_cfg_program(pdev); |
| 361 | if (ret) | 393 | if (ret) |
| 362 | return ret; | 394 | goto err; |
| 363 | 395 | ||
| 364 | drv_data->ecc_irq = platform_get_irq(pdev, 0); | 396 | drv_data->ecc_irq = platform_get_irq(pdev, 0); |
| 365 | if (drv_data->ecc_irq >= 0) { | 397 | if (drv_data->ecc_irq >= 0) { |
| @@ -370,6 +402,9 @@ int qcom_llcc_probe(struct platform_device *pdev, | |||
| 370 | dev_err(dev, "Failed to register llcc edac driver\n"); | 402 | dev_err(dev, "Failed to register llcc edac driver\n"); |
| 371 | } | 403 | } |
| 372 | 404 | ||
| 405 | return 0; | ||
| 406 | err: | ||
| 407 | drv_data = ERR_PTR(-ENODEV); | ||
| 373 | return ret; | 408 | return ret; |
| 374 | } | 409 | } |
| 375 | EXPORT_SYMBOL_GPL(qcom_llcc_probe); | 410 | EXPORT_SYMBOL_GPL(qcom_llcc_probe); |
