Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: atmel: fix the ispck initialization

The runtime enabling of the ISPCK (internally clocks the pipeline inside
the ISC) has to be done after the pm_runtime for the ISC dev has been
started.

After the commit by Mauro:
the ISC failed to probe with the error:

atmel-sama5d2-isc f0008000.isc: failed to enable ispck: -13
atmel-sama5d2-isc: probe of f0008000.isc failed with error -13

This is because the enabling of the ispck is done too early in the probe,
and the PM runtime returns invalid request.
Thus, moved this clock enabling after pm_runtime_idle is called.

The ISPCK is required only for sama5d2 type of ISC.
Thus, add a bool inside the isc struct that is platform dependent.
For the sama7g5-isc, the enabling of the ISPCK is wrong and does not make
sense. Removed it from the sama7g5 probe. In sama7g5-isc, there is only
one clock, the MCK, which also clocks the internal pipeline of the ISC.

Adapted the clk_prepare and clk_unprepare to request the runtime PM
for both clocks (MCK and ISPCK) in case of sama5d2-isc, and the single
clock (MCK) in case of sama7g5-isc.

Fixes: dd97908ee350 ("media: atmel: properly get pm_runtime")
Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Eugen Hristev and committed by
Mauro Carvalho Chehab
d7f26849 9d45ccf7

+38 -50
+11 -14
drivers/media/platform/atmel/atmel-isc-base.c
··· 123 123 struct isc_clk *isc_clk = to_isc_clk(hw); 124 124 int ret; 125 125 126 - if (isc_clk->id == ISC_ISPCK) { 127 - ret = pm_runtime_resume_and_get(isc_clk->dev); 128 - if (ret < 0) 129 - return ret; 130 - } 126 + ret = pm_runtime_resume_and_get(isc_clk->dev); 127 + if (ret < 0) 128 + return ret; 131 129 132 130 return isc_wait_clk_stable(hw); 133 131 } ··· 136 138 137 139 isc_wait_clk_stable(hw); 138 140 139 - if (isc_clk->id == ISC_ISPCK) 140 - pm_runtime_put_sync(isc_clk->dev); 141 + pm_runtime_put_sync(isc_clk->dev); 141 142 } 142 143 143 144 static int isc_clk_enable(struct clk_hw *hw) ··· 183 186 u32 status; 184 187 int ret; 185 188 186 - if (isc_clk->id == ISC_ISPCK) { 187 - ret = pm_runtime_resume_and_get(isc_clk->dev); 188 - if (ret < 0) 189 - return 0; 190 - } 189 + ret = pm_runtime_resume_and_get(isc_clk->dev); 190 + if (ret < 0) 191 + return 0; 191 192 192 193 regmap_read(isc_clk->regmap, ISC_CLKSR, &status); 193 194 194 - if (isc_clk->id == ISC_ISPCK) 195 - pm_runtime_put_sync(isc_clk->dev); 195 + pm_runtime_put_sync(isc_clk->dev); 196 196 197 197 return status & ISC_CLK(isc_clk->id) ? 1 : 0; 198 198 } ··· 318 324 const char *clk_name = np->name; 319 325 const char *parent_names[3]; 320 326 int num_parents; 327 + 328 + if (id == ISC_ISPCK && !isc->ispck_required) 329 + return 0; 321 330 322 331 num_parents = of_clk_get_parent_count(np); 323 332 if (num_parents < 1 || num_parents > 3)
+2
drivers/media/platform/atmel/atmel-isc.h
··· 178 178 * @hclock: Hclock clock input (refer datasheet) 179 179 * @ispck: iscpck clock (refer datasheet) 180 180 * @isc_clks: ISC clocks 181 + * @ispck_required: ISC requires ISP Clock initialization 181 182 * @dcfg: DMA master configuration, architecture dependent 182 183 * 183 184 * @dev: Registered device driver ··· 253 252 struct clk *hclock; 254 253 struct clk *ispck; 255 254 struct isc_clk isc_clks[2]; 255 + bool ispck_required; 256 256 u32 dcfg; 257 257 258 258 struct device *dev;
+21 -18
drivers/media/platform/atmel/atmel-sama5d2-isc.c
··· 454 454 /* sama5d2-isc - 8 bits per beat */ 455 455 isc->dcfg = ISC_DCFG_YMBSIZE_BEATS8 | ISC_DCFG_CMBSIZE_BEATS8; 456 456 457 + /* sama5d2-isc : ISPCK is required and mandatory */ 458 + isc->ispck_required = true; 459 + 457 460 ret = isc_pipeline_init(isc); 458 461 if (ret) 459 462 return ret; ··· 479 476 dev_err(dev, "failed to init isc clock: %d\n", ret); 480 477 goto unprepare_hclk; 481 478 } 482 - 483 - isc->ispck = isc->isc_clks[ISC_ISPCK].clk; 484 - 485 - ret = clk_prepare_enable(isc->ispck); 486 - if (ret) { 487 - dev_err(dev, "failed to enable ispck: %d\n", ret); 488 - goto unprepare_hclk; 489 - } 490 - 491 - /* ispck should be greater or equal to hclock */ 492 - ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); 493 - if (ret) { 494 - dev_err(dev, "failed to set ispck rate: %d\n", ret); 495 - goto unprepare_clk; 496 - } 497 - 498 479 ret = v4l2_device_register(dev, &isc->v4l2_dev); 499 480 if (ret) { 500 481 dev_err(dev, "unable to register v4l2 device.\n"); ··· 533 546 pm_runtime_enable(dev); 534 547 pm_request_idle(dev); 535 548 549 + isc->ispck = isc->isc_clks[ISC_ISPCK].clk; 550 + 551 + ret = clk_prepare_enable(isc->ispck); 552 + if (ret) { 553 + dev_err(dev, "failed to enable ispck: %d\n", ret); 554 + goto cleanup_subdev; 555 + } 556 + 557 + /* ispck should be greater or equal to hclock */ 558 + ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); 559 + if (ret) { 560 + dev_err(dev, "failed to set ispck rate: %d\n", ret); 561 + goto unprepare_clk; 562 + } 563 + 536 564 regmap_read(isc->regmap, ISC_VERSION + isc->offsets.version, &ver); 537 565 dev_info(dev, "Microchip ISC version %x\n", ver); 538 566 539 567 return 0; 568 + 569 + unprepare_clk: 570 + clk_disable_unprepare(isc->ispck); 540 571 541 572 cleanup_subdev: 542 573 isc_subdev_cleanup(isc); ··· 562 557 unregister_v4l2_device: 563 558 v4l2_device_unregister(&isc->v4l2_dev); 564 559 565 - unprepare_clk: 566 - clk_disable_unprepare(isc->ispck); 567 560 unprepare_hclk: 568 561 clk_disable_unprepare(isc->hclock); 569 562
+4 -18
drivers/media/platform/atmel/atmel-sama7g5-isc.c
··· 447 447 /* sama7g5-isc RAM access port is full AXI4 - 32 bits per beat */ 448 448 isc->dcfg = ISC_DCFG_YMBSIZE_BEATS32 | ISC_DCFG_CMBSIZE_BEATS32; 449 449 450 + /* sama7g5-isc : ISPCK does not exist, ISC is clocked by MCK */ 451 + isc->ispck_required = false; 452 + 450 453 ret = isc_pipeline_init(isc); 451 454 if (ret) 452 455 return ret; ··· 473 470 goto unprepare_hclk; 474 471 } 475 472 476 - isc->ispck = isc->isc_clks[ISC_ISPCK].clk; 477 - 478 - ret = clk_prepare_enable(isc->ispck); 479 - if (ret) { 480 - dev_err(dev, "failed to enable ispck: %d\n", ret); 481 - goto unprepare_hclk; 482 - } 483 - 484 - /* ispck should be greater or equal to hclock */ 485 - ret = clk_set_rate(isc->ispck, clk_get_rate(isc->hclock)); 486 - if (ret) { 487 - dev_err(dev, "failed to set ispck rate: %d\n", ret); 488 - goto unprepare_clk; 489 - } 490 - 491 473 ret = v4l2_device_register(dev, &isc->v4l2_dev); 492 474 if (ret) { 493 475 dev_err(dev, "unable to register v4l2 device.\n"); 494 - goto unprepare_clk; 476 + goto unprepare_hclk; 495 477 } 496 478 497 479 ret = xisc_parse_dt(dev, isc); ··· 538 550 unregister_v4l2_device: 539 551 v4l2_device_unregister(&isc->v4l2_dev); 540 552 541 - unprepare_clk: 542 - clk_disable_unprepare(isc->ispck); 543 553 unprepare_hclk: 544 554 clk_disable_unprepare(isc->hclock); 545 555