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

clk: tegra: Add DFLL DVCO reset control for Tegra124

The DVCO present in the DFLL IP block has a separate reset line,
exposed via the CAR IP block. This reset line is asserted upon SoC
reset. Unless something (such as the DFLL driver) deasserts this
line, the DVCO will not oscillate, although reads and writes to the
DFLL IP block will complete.

Thanks to Aleksandr Frid <afrid@nvidia.com> for identifying this and
saving hours of debugging time.

Signed-off-by: Paul Walmsley <pwalmsley@nvidia.com>
[ttynkkynen: ported to tegra124 from tegra114]
Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com>
[mikko.perttunen: ported to special reset callback]
Signed-off-by: Mikko Perttunen <mikko.perttunen@kapsi.fi>
Acked-by: Michael Turquette <mturquette@linaro.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>

authored by

Paul Walmsley and committed by
Thierry Reding
a3c83ff2 66b6f3d0

+80
+68
drivers/clk/tegra/clk-tegra124.c
··· 24 24 #include <linux/export.h> 25 25 #include <linux/clk/tegra.h> 26 26 #include <dt-bindings/clock/tegra124-car.h> 27 + #include <dt-bindings/reset/tegra124-car.h> 27 28 28 29 #include "clk.h" 29 30 #include "clk-id.h" ··· 39 38 40 39 #define CLK_SOURCE_CSITE 0x1d4 41 40 #define CLK_SOURCE_EMC 0x19c 41 + 42 + #define RST_DFLL_DVCO 0x2f4 43 + #define DVFS_DFLL_RESET_SHIFT 0 42 44 43 45 #define PLLC_BASE 0x80 44 46 #define PLLC_OUT 0x84 ··· 1419 1415 } 1420 1416 1421 1417 /** 1418 + * tegra124_car_barrier - wait for pending writes to the CAR to complete 1419 + * 1420 + * Wait for any outstanding writes to the CAR MMIO space from this CPU 1421 + * to complete before continuing execution. No return value. 1422 + */ 1423 + static void tegra124_car_barrier(void) 1424 + { 1425 + readl_relaxed(clk_base + RST_DFLL_DVCO); 1426 + } 1427 + 1428 + /** 1429 + * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset 1430 + * 1431 + * Assert the reset line of the DFLL's DVCO. No return value. 1432 + */ 1433 + void tegra124_clock_assert_dfll_dvco_reset(void) 1434 + { 1435 + u32 v; 1436 + 1437 + v = readl_relaxed(clk_base + RST_DFLL_DVCO); 1438 + v |= (1 << DVFS_DFLL_RESET_SHIFT); 1439 + writel_relaxed(v, clk_base + RST_DFLL_DVCO); 1440 + tegra124_car_barrier(); 1441 + } 1442 + 1443 + /** 1444 + * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset 1445 + * 1446 + * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to 1447 + * operate. No return value. 1448 + */ 1449 + void tegra124_clock_deassert_dfll_dvco_reset(void) 1450 + { 1451 + u32 v; 1452 + 1453 + v = readl_relaxed(clk_base + RST_DFLL_DVCO); 1454 + v &= ~(1 << DVFS_DFLL_RESET_SHIFT); 1455 + writel_relaxed(v, clk_base + RST_DFLL_DVCO); 1456 + tegra124_car_barrier(); 1457 + } 1458 + 1459 + int tegra124_reset_assert(unsigned long id) 1460 + { 1461 + if (id == TEGRA124_RST_DFLL_DVCO) 1462 + tegra124_clock_assert_dfll_dvco_reset(); 1463 + else 1464 + return -EINVAL; 1465 + 1466 + return 0; 1467 + } 1468 + 1469 + int tegra124_reset_deassert(unsigned long id) 1470 + { 1471 + if (id == TEGRA124_RST_DFLL_DVCO) 1472 + tegra124_clock_deassert_dfll_dvco_reset(); 1473 + else 1474 + return -EINVAL; 1475 + 1476 + return 0; 1477 + } 1478 + 1479 + /** 1422 1480 * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs 1423 1481 * 1424 1482 * Program an initial clock rate and enable or disable clocks needed ··· 1565 1499 { 1566 1500 tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks, 1567 1501 &pll_x_params); 1502 + tegra_init_special_resets(1, tegra124_reset_assert, 1503 + tegra124_reset_deassert); 1568 1504 tegra_add_of_provider(np); 1569 1505 1570 1506 clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
+12
include/dt-bindings/reset/tegra124-car.h
··· 1 + /* 2 + * This header provides Tegra124-specific constants for binding 3 + * nvidia,tegra124-car. 4 + */ 5 + 6 + #ifndef _DT_BINDINGS_RESET_TEGRA124_CAR_H 7 + #define _DT_BINDINGS_RESET_TEGRA124_CAR_H 8 + 9 + #define TEGRA124_RESET(x) (6 * 32 + (x)) 10 + #define TEGRA124_RST_DFLL_DVCO TEGRA124_RESET(0) 11 + 12 + #endif /* _DT_BINDINGS_RESET_TEGRA124_CAR_H */