aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Walmsley <pwalmsley@nvidia.com>2015-05-19 07:43:30 -0400
committerThierry Reding <treding@nvidia.com>2015-07-16 03:32:48 -0400
commita3c83ff20c64a0ea3580aa7ed2953ff1602334dd (patch)
tree430475bf09ce175b8d6e1436693da8401b865ea9
parent66b6f3d07454a66ec029543c653d3bce7e6cb3c1 (diff)
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>
-rw-r--r--drivers/clk/tegra/clk-tegra124.c68
-rw-r--r--include/dt-bindings/reset/tegra124-car.h12
2 files changed, 80 insertions, 0 deletions
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index e8cca3eac007..106ec458c945 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -24,6 +24,7 @@
24#include <linux/export.h> 24#include <linux/export.h>
25#include <linux/clk/tegra.h> 25#include <linux/clk/tegra.h>
26#include <dt-bindings/clock/tegra124-car.h> 26#include <dt-bindings/clock/tegra124-car.h>
27#include <dt-bindings/reset/tegra124-car.h>
27 28
28#include "clk.h" 29#include "clk.h"
29#include "clk-id.h" 30#include "clk-id.h"
@@ -39,6 +40,9 @@
39#define CLK_SOURCE_CSITE 0x1d4 40#define CLK_SOURCE_CSITE 0x1d4
40#define CLK_SOURCE_EMC 0x19c 41#define CLK_SOURCE_EMC 0x19c
41 42
43#define RST_DFLL_DVCO 0x2f4
44#define DVFS_DFLL_RESET_SHIFT 0
45
42#define PLLC_BASE 0x80 46#define PLLC_BASE 0x80
43#define PLLC_OUT 0x84 47#define PLLC_OUT 0x84
44#define PLLC_MISC2 0x88 48#define PLLC_MISC2 0x88
@@ -1415,6 +1419,68 @@ static void __init tegra124_clock_apply_init_table(void)
1415} 1419}
1416 1420
1417/** 1421/**
1422 * tegra124_car_barrier - wait for pending writes to the CAR to complete
1423 *
1424 * Wait for any outstanding writes to the CAR MMIO space from this CPU
1425 * to complete before continuing execution. No return value.
1426 */
1427static void tegra124_car_barrier(void)
1428{
1429 readl_relaxed(clk_base + RST_DFLL_DVCO);
1430}
1431
1432/**
1433 * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
1434 *
1435 * Assert the reset line of the DFLL's DVCO. No return value.
1436 */
1437void tegra124_clock_assert_dfll_dvco_reset(void)
1438{
1439 u32 v;
1440
1441 v = readl_relaxed(clk_base + RST_DFLL_DVCO);
1442 v |= (1 << DVFS_DFLL_RESET_SHIFT);
1443 writel_relaxed(v, clk_base + RST_DFLL_DVCO);
1444 tegra124_car_barrier();
1445}
1446
1447/**
1448 * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
1449 *
1450 * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
1451 * operate. No return value.
1452 */
1453void tegra124_clock_deassert_dfll_dvco_reset(void)
1454{
1455 u32 v;
1456
1457 v = readl_relaxed(clk_base + RST_DFLL_DVCO);
1458 v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
1459 writel_relaxed(v, clk_base + RST_DFLL_DVCO);
1460 tegra124_car_barrier();
1461}
1462
1463int tegra124_reset_assert(unsigned long id)
1464{
1465 if (id == TEGRA124_RST_DFLL_DVCO)
1466 tegra124_clock_assert_dfll_dvco_reset();
1467 else
1468 return -EINVAL;
1469
1470 return 0;
1471}
1472
1473int tegra124_reset_deassert(unsigned long id)
1474{
1475 if (id == TEGRA124_RST_DFLL_DVCO)
1476 tegra124_clock_deassert_dfll_dvco_reset();
1477 else
1478 return -EINVAL;
1479
1480 return 0;
1481}
1482
1483/**
1418 * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs 1484 * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
1419 * 1485 *
1420 * Program an initial clock rate and enable or disable clocks needed 1486 * Program an initial clock rate and enable or disable clocks needed
@@ -1499,6 +1565,8 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
1499{ 1565{
1500 tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks, 1566 tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
1501 &pll_x_params); 1567 &pll_x_params);
1568 tegra_init_special_resets(1, tegra124_reset_assert,
1569 tegra124_reset_deassert);
1502 tegra_add_of_provider(np); 1570 tegra_add_of_provider(np);
1503 1571
1504 clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np, 1572 clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
diff --git a/include/dt-bindings/reset/tegra124-car.h b/include/dt-bindings/reset/tegra124-car.h
new file mode 100644
index 000000000000..070e4f6e7486
--- /dev/null
+++ b/include/dt-bindings/reset/tegra124-car.h
@@ -0,0 +1,12 @@
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 */