mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 08:26:59 +00:00
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
2 changed files with 98 additions and 0 deletions
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/clk/tegra.h>
|
#include <linux/clk/tegra.h>
|
||||||
#include <dt-bindings/clock/tegra210-car.h>
|
#include <dt-bindings/clock/tegra210-car.h>
|
||||||
|
#include <dt-bindings/reset/tegra210-car.h>
|
||||||
#include <linux/iopoll.h>
|
#include <linux/iopoll.h>
|
||||||
|
|
||||||
#include "clk.h"
|
#include "clk.h"
|
||||||
|
@ -218,6 +219,12 @@
|
||||||
#define CLK_M_DIVISOR_SHIFT 2
|
#define CLK_M_DIVISOR_SHIFT 2
|
||||||
#define CLK_M_DIVISOR_MASK 0x3
|
#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
|
* 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
|
* (-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);
|
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
|
* tegra210_clock_init - Tegra210-specific clock initialization
|
||||||
* @np: struct device_node * of the DT node for the SoC CAR IP block
|
* @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,
|
tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks,
|
||||||
&pll_x_params);
|
&pll_x_params);
|
||||||
|
tegra_init_special_resets(2, tegra210_reset_assert,
|
||||||
|
tegra210_reset_deassert);
|
||||||
|
|
||||||
tegra_add_of_provider(np);
|
tegra_add_of_provider(np);
|
||||||
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||||
|
|
||||||
|
|
13
include/dt-bindings/reset/tegra210-car.h
Normal file
13
include/dt-bindings/reset/tegra210-car.h
Normal file
|
@ -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 a new issue