clk: tegra: Add Tegra210 special resets
Tegra210 has 2 special resets which don't follow the normal pattern: DVCO and ADSP. Add them in this patch. Changelog: v2: add DT bindings file Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
e745f992cf
commit
68d724cedc
|
@ -24,6 +24,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <dt-bindings/clock/tegra210-car.h>
|
||||
#include <dt-bindings/reset/tegra210-car.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
@ -218,6 +219,12 @@
|
|||
#define CLK_M_DIVISOR_SHIFT 2
|
||||
#define CLK_M_DIVISOR_MASK 0x3
|
||||
|
||||
#define RST_DFLL_DVCO 0x2f4
|
||||
#define DVFS_DFLL_RESET_SHIFT 0
|
||||
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
|
||||
#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
|
||||
|
||||
/*
|
||||
* SDM fractional divisor is 16-bit 2's complement signed number within
|
||||
* (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
|
||||
|
@ -2982,6 +2989,81 @@ static void __init tegra210_clock_apply_init_table(void)
|
|||
tegra_init_from_table(init_table, clks, TEGRA210_CLK_CLK_MAX);
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_car_barrier - wait for pending writes to the CAR to complete
|
||||
*
|
||||
* Wait for any outstanding writes to the CAR MMIO space from this CPU
|
||||
* to complete before continuing execution. No return value.
|
||||
*/
|
||||
static void tegra210_car_barrier(void)
|
||||
{
|
||||
readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
|
||||
*
|
||||
* Assert the reset line of the DFLL's DVCO. No return value.
|
||||
*/
|
||||
static void tegra210_clock_assert_dfll_dvco_reset(void)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||
v |= (1 << DVFS_DFLL_RESET_SHIFT);
|
||||
writel_relaxed(v, clk_base + RST_DFLL_DVCO);
|
||||
tegra210_car_barrier();
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
|
||||
*
|
||||
* Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
|
||||
* operate. No return value.
|
||||
*/
|
||||
static void tegra210_clock_deassert_dfll_dvco_reset(void)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||
v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
|
||||
writel_relaxed(v, clk_base + RST_DFLL_DVCO);
|
||||
tegra210_car_barrier();
|
||||
}
|
||||
|
||||
static int tegra210_reset_assert(unsigned long id)
|
||||
{
|
||||
if (id == TEGRA210_RST_DFLL_DVCO)
|
||||
tegra210_clock_assert_dfll_dvco_reset();
|
||||
else if (id == TEGRA210_RST_ADSP)
|
||||
writel(GENMASK(26, 21) | BIT(7),
|
||||
clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_SET);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra210_reset_deassert(unsigned long id)
|
||||
{
|
||||
if (id == TEGRA210_RST_DFLL_DVCO)
|
||||
tegra210_clock_deassert_dfll_dvco_reset();
|
||||
else if (id == TEGRA210_RST_ADSP) {
|
||||
writel(BIT(21), clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR);
|
||||
/*
|
||||
* Considering adsp cpu clock (min: 12.5MHZ, max: 1GHz)
|
||||
* a delay of 5us ensures that it's at least
|
||||
* 6 * adsp_cpu_cycle_period long.
|
||||
*/
|
||||
udelay(5);
|
||||
writel(GENMASK(26, 22) | BIT(7),
|
||||
clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR);
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tegra210_clock_init - Tegra210-specific clock initialization
|
||||
* @np: struct device_node * of the DT node for the SoC CAR IP block
|
||||
|
@ -3046,6 +3128,9 @@ static void __init tegra210_clock_init(struct device_node *np)
|
|||
|
||||
tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks,
|
||||
&pll_x_params);
|
||||
tegra_init_special_resets(2, tegra210_reset_assert,
|
||||
tegra210_reset_deassert);
|
||||
|
||||
tegra_add_of_provider(np);
|
||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* This header provides Tegra210-specific constants for binding
|
||||
* nvidia,tegra210-car.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_TEGRA210_CAR_H
|
||||
#define _DT_BINDINGS_RESET_TEGRA210_CAR_H
|
||||
|
||||
#define TEGRA210_RESET(x) (7 * 32 + (x))
|
||||
#define TEGRA210_RST_DFLL_DVCO TEGRA210_RESET(0)
|
||||
#define TEGRA210_RST_ADSP TEGRA210_RESET(1)
|
||||
|
||||
#endif /* _DT_BINDINGS_RESET_TEGRA210_CAR_H */
|
Loading…
Reference in New Issue