Skip to content

Commit e1335e2

Browse files
committed
drm/tegra: sor: Reimplement pad clock
The current implementation of the pad clock isn't quite correct. This has the side-effect of being incompatible with the implementation for Tegra186 (provided by the BPMP) and therefore would require a massive change to the driver to cope with the differences. Instead, simply do what Tegra186 does and add some code to fallback to the old behaviour for existing device trees. Signed-off-by: Thierry Reding <[email protected]>
1 parent fb83be8 commit e1335e2

File tree

1 file changed

+111
-46
lines changed
  • drivers/gpu/drm/tegra

1 file changed

+111
-46
lines changed

drivers/gpu/drm/tegra/sor.c

+111-46
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ struct tegra_sor {
174174

175175
struct reset_control *rst;
176176
struct clk *clk_parent;
177-
struct clk *clk_brick;
178177
struct clk *clk_safe;
179-
struct clk *clk_src;
178+
struct clk *clk_out;
179+
struct clk *clk_pad;
180180
struct clk *clk_dp;
181181
struct clk *clk;
182182

@@ -255,7 +255,7 @@ static int tegra_sor_set_parent_clock(struct tegra_sor *sor, struct clk *parent)
255255

256256
clk_disable_unprepare(sor->clk);
257257

258-
err = clk_set_parent(sor->clk, parent);
258+
err = clk_set_parent(sor->clk_out, parent);
259259
if (err < 0)
260260
return err;
261261

@@ -266,24 +266,24 @@ static int tegra_sor_set_parent_clock(struct tegra_sor *sor, struct clk *parent)
266266
return 0;
267267
}
268268

269-
struct tegra_clk_sor_brick {
269+
struct tegra_clk_sor_pad {
270270
struct clk_hw hw;
271271
struct tegra_sor *sor;
272272
};
273273

274-
static inline struct tegra_clk_sor_brick *to_brick(struct clk_hw *hw)
274+
static inline struct tegra_clk_sor_pad *to_pad(struct clk_hw *hw)
275275
{
276-
return container_of(hw, struct tegra_clk_sor_brick, hw);
276+
return container_of(hw, struct tegra_clk_sor_pad, hw);
277277
}
278278

279-
static const char * const tegra_clk_sor_brick_parents[] = {
279+
static const char * const tegra_clk_sor_pad_parents[] = {
280280
"pll_d2_out0", "pll_dp"
281281
};
282282

283-
static int tegra_clk_sor_brick_set_parent(struct clk_hw *hw, u8 index)
283+
static int tegra_clk_sor_pad_set_parent(struct clk_hw *hw, u8 index)
284284
{
285-
struct tegra_clk_sor_brick *brick = to_brick(hw);
286-
struct tegra_sor *sor = brick->sor;
285+
struct tegra_clk_sor_pad *pad = to_pad(hw);
286+
struct tegra_sor *sor = pad->sor;
287287
u32 value;
288288

289289
value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
@@ -304,10 +304,10 @@ static int tegra_clk_sor_brick_set_parent(struct clk_hw *hw, u8 index)
304304
return 0;
305305
}
306306

307-
static u8 tegra_clk_sor_brick_get_parent(struct clk_hw *hw)
307+
static u8 tegra_clk_sor_pad_get_parent(struct clk_hw *hw)
308308
{
309-
struct tegra_clk_sor_brick *brick = to_brick(hw);
310-
struct tegra_sor *sor = brick->sor;
309+
struct tegra_clk_sor_pad *pad = to_pad(hw);
310+
struct tegra_sor *sor = pad->sor;
311311
u8 parent = U8_MAX;
312312
u32 value;
313313

@@ -328,33 +328,33 @@ static u8 tegra_clk_sor_brick_get_parent(struct clk_hw *hw)
328328
return parent;
329329
}
330330

331-
static const struct clk_ops tegra_clk_sor_brick_ops = {
332-
.set_parent = tegra_clk_sor_brick_set_parent,
333-
.get_parent = tegra_clk_sor_brick_get_parent,
331+
static const struct clk_ops tegra_clk_sor_pad_ops = {
332+
.set_parent = tegra_clk_sor_pad_set_parent,
333+
.get_parent = tegra_clk_sor_pad_get_parent,
334334
};
335335

336-
static struct clk *tegra_clk_sor_brick_register(struct tegra_sor *sor,
337-
const char *name)
336+
static struct clk *tegra_clk_sor_pad_register(struct tegra_sor *sor,
337+
const char *name)
338338
{
339-
struct tegra_clk_sor_brick *brick;
339+
struct tegra_clk_sor_pad *pad;
340340
struct clk_init_data init;
341341
struct clk *clk;
342342

343-
brick = devm_kzalloc(sor->dev, sizeof(*brick), GFP_KERNEL);
344-
if (!brick)
343+
pad = devm_kzalloc(sor->dev, sizeof(*pad), GFP_KERNEL);
344+
if (!pad)
345345
return ERR_PTR(-ENOMEM);
346346

347-
brick->sor = sor;
347+
pad->sor = sor;
348348

349349
init.name = name;
350350
init.flags = 0;
351-
init.parent_names = tegra_clk_sor_brick_parents;
352-
init.num_parents = ARRAY_SIZE(tegra_clk_sor_brick_parents);
353-
init.ops = &tegra_clk_sor_brick_ops;
351+
init.parent_names = tegra_clk_sor_pad_parents;
352+
init.num_parents = ARRAY_SIZE(tegra_clk_sor_pad_parents);
353+
init.ops = &tegra_clk_sor_pad_ops;
354354

355-
brick->hw.init = &init;
355+
pad->hw.init = &init;
356356

357-
clk = devm_clk_register(sor->dev, &brick->hw);
357+
clk = devm_clk_register(sor->dev, &pad->hw);
358358

359359
return clk;
360360
}
@@ -998,8 +998,10 @@ static int tegra_sor_power_down(struct tegra_sor *sor)
998998

999999
/* switch to safe parent clock */
10001000
err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
1001-
if (err < 0)
1001+
if (err < 0) {
10021002
dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
1003+
return err;
1004+
}
10031005

10041006
value = tegra_sor_readl(sor, SOR_DP_PADCTL0);
10051007
value &= ~(SOR_DP_PADCTL_PD_TXD_3 | SOR_DP_PADCTL_PD_TXD_0 |
@@ -2007,8 +2009,10 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
20072009

20082010
/* switch to safe parent clock */
20092011
err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
2010-
if (err < 0)
2012+
if (err < 0) {
20112013
dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
2014+
return;
2015+
}
20122016

20132017
div = clk_get_rate(sor->clk) / 1000000 * 4;
20142018

@@ -2111,13 +2115,17 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
21112115
tegra_sor_writel(sor, value, SOR_XBAR_CTRL);
21122116

21132117
/* switch to parent clock */
2114-
err = clk_set_parent(sor->clk_src, sor->clk_parent);
2115-
if (err < 0)
2116-
dev_err(sor->dev, "failed to set source clock: %d\n", err);
2117-
2118-
err = tegra_sor_set_parent_clock(sor, sor->clk_src);
2119-
if (err < 0)
2118+
err = clk_set_parent(sor->clk, sor->clk_parent);
2119+
if (err < 0) {
21202120
dev_err(sor->dev, "failed to set parent clock: %d\n", err);
2121+
return;
2122+
}
2123+
2124+
err = tegra_sor_set_parent_clock(sor, sor->clk_pad);
2125+
if (err < 0) {
2126+
dev_err(sor->dev, "failed to set pad clock: %d\n", err);
2127+
return;
2128+
}
21212129

21222130
value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
21232131

@@ -2628,11 +2636,24 @@ static int tegra_sor_probe(struct platform_device *pdev)
26282636
}
26292637

26302638
if (sor->soc->supports_hdmi || sor->soc->supports_dp) {
2631-
sor->clk_src = devm_clk_get(&pdev->dev, "source");
2632-
if (IS_ERR(sor->clk_src)) {
2633-
err = PTR_ERR(sor->clk_src);
2634-
dev_err(sor->dev, "failed to get source clock: %d\n",
2635-
err);
2639+
struct device_node *np = pdev->dev.of_node;
2640+
const char *name;
2641+
2642+
/*
2643+
* For backwards compatibility with Tegra210 device trees,
2644+
* fall back to the old clock name "source" if the new "out"
2645+
* clock is not available.
2646+
*/
2647+
if (of_property_match_string(np, "clock-names", "out") < 0)
2648+
name = "source";
2649+
else
2650+
name = "out";
2651+
2652+
sor->clk_out = devm_clk_get(&pdev->dev, name);
2653+
if (IS_ERR(sor->clk_out)) {
2654+
err = PTR_ERR(sor->clk_out);
2655+
dev_err(sor->dev, "failed to get %s clock: %d\n",
2656+
name, err);
26362657
goto remove;
26372658
}
26382659
}
@@ -2658,16 +2679,60 @@ static int tegra_sor_probe(struct platform_device *pdev)
26582679
goto remove;
26592680
}
26602681

2682+
/*
2683+
* Starting with Tegra186, the BPMP provides an implementation for
2684+
* the pad output clock, so we have to look it up from device tree.
2685+
*/
2686+
sor->clk_pad = devm_clk_get(&pdev->dev, "pad");
2687+
if (IS_ERR(sor->clk_pad)) {
2688+
if (sor->clk_pad != ERR_PTR(-ENOENT)) {
2689+
err = PTR_ERR(sor->clk_pad);
2690+
goto remove;
2691+
}
2692+
2693+
/*
2694+
* If the pad output clock is not available, then we assume
2695+
* we're on Tegra210 or earlier and have to provide our own
2696+
* implementation.
2697+
*/
2698+
sor->clk_pad = NULL;
2699+
}
2700+
2701+
/*
2702+
* The bootloader may have set up the SOR such that it's module clock
2703+
* is sourced by one of the display PLLs. However, that doesn't work
2704+
* without properly having set up other bits of the SOR.
2705+
*/
2706+
err = clk_set_parent(sor->clk_out, sor->clk_safe);
2707+
if (err < 0) {
2708+
dev_err(&pdev->dev, "failed to use safe clock: %d\n", err);
2709+
goto remove;
2710+
}
2711+
26612712
platform_set_drvdata(pdev, sor);
26622713
pm_runtime_enable(&pdev->dev);
26632714

2664-
pm_runtime_get_sync(&pdev->dev);
2665-
sor->clk_brick = tegra_clk_sor_brick_register(sor, "sor1_brick");
2666-
pm_runtime_put(&pdev->dev);
2715+
/*
2716+
* On Tegra210 and earlier, provide our own implementation for the
2717+
* pad output clock.
2718+
*/
2719+
if (!sor->clk_pad) {
2720+
err = pm_runtime_get_sync(&pdev->dev);
2721+
if (err < 0) {
2722+
dev_err(&pdev->dev, "failed to get runtime PM: %d\n",
2723+
err);
2724+
goto remove;
2725+
}
2726+
2727+
sor->clk_pad = tegra_clk_sor_pad_register(sor,
2728+
"sor1_pad_clkout");
2729+
pm_runtime_put(&pdev->dev);
2730+
}
26672731

2668-
if (IS_ERR(sor->clk_brick)) {
2669-
err = PTR_ERR(sor->clk_brick);
2670-
dev_err(&pdev->dev, "failed to register SOR clock: %d\n", err);
2732+
if (IS_ERR(sor->clk_pad)) {
2733+
err = PTR_ERR(sor->clk_pad);
2734+
dev_err(&pdev->dev, "failed to register SOR pad clock: %d\n",
2735+
err);
26712736
goto remove;
26722737
}
26732738

0 commit comments

Comments
 (0)