ARM: tegra: split tegra_pmc_init() in two
Tegra's board file currently initializes clocks much earlier than those for most other ARM SoCs. The reason is: * The PMC HW block is involved in the path of some interrupts (i.e. it inverts, or not, the IRQ input pin dedicated to the PMIC). * So, that part of the PMC must be initialized early so that the IRQ polarity is correct. * The PMC initialization is currently monolithic, and the PMC has some clock inputs, so the init routine ends up calling of_clk_get_by_name(), and hence clocks must be set up early too. In order to defer clock initialization to the more typical location, split out the portions of tegra_pmc_init() that are truly IRQ-related into a separate tegra_pmc_init_irq(), which can be called from the machine descriptor's .init_irq() function, and defer the rest until the machine descriptor's .init_machine() function. This allows the clock initiliazation to happen from the machine descriptor's .init_time() function, as is typical. Signed-off-by: Stephen Warren <swarren@nvidia.com>
This commit is contained in:
Родитель
272b98c645
Коммит
d2207071b3
|
@ -24,7 +24,6 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
|
||||
|
@ -61,8 +60,7 @@ u32 tegra_uart_config[4] = {
|
|||
#ifdef CONFIG_OF
|
||||
void __init tegra_dt_init_irq(void)
|
||||
{
|
||||
of_clk_init(NULL);
|
||||
tegra_pmc_init();
|
||||
tegra_pmc_init_irq();
|
||||
tegra_init_irq();
|
||||
irqchip_init();
|
||||
tegra_legacy_irq_syscore_init();
|
||||
|
|
|
@ -285,7 +285,28 @@ static const struct of_device_id matches[] __initconst = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static void __init tegra_pmc_parse_dt(void)
|
||||
void __init tegra_pmc_init_irq(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 val;
|
||||
|
||||
np = of_find_matching_node(NULL, matches);
|
||||
BUG_ON(!np);
|
||||
|
||||
tegra_pmc_base = of_iomap(np, 0);
|
||||
|
||||
tegra_pmc_invert_interrupt = of_property_read_bool(np,
|
||||
"nvidia,invert-interrupt");
|
||||
|
||||
val = tegra_pmc_readl(PMC_CTRL);
|
||||
if (tegra_pmc_invert_interrupt)
|
||||
val |= PMC_CTRL_INTR_LOW;
|
||||
else
|
||||
val &= ~PMC_CTRL_INTR_LOW;
|
||||
tegra_pmc_writel(val, PMC_CTRL);
|
||||
}
|
||||
|
||||
void __init tegra_pmc_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 prop;
|
||||
|
@ -296,10 +317,6 @@ static void __init tegra_pmc_parse_dt(void)
|
|||
np = of_find_matching_node(NULL, matches);
|
||||
BUG_ON(!np);
|
||||
|
||||
tegra_pmc_base = of_iomap(np, 0);
|
||||
|
||||
tegra_pmc_invert_interrupt = of_property_read_bool(np,
|
||||
"nvidia,invert-interrupt");
|
||||
tegra_pclk = of_clk_get_by_name(np, "pclk");
|
||||
WARN_ON(IS_ERR(tegra_pclk));
|
||||
|
||||
|
@ -365,17 +382,3 @@ static void __init tegra_pmc_parse_dt(void)
|
|||
|
||||
pmc_pm_data.suspend_mode = suspend_mode;
|
||||
}
|
||||
|
||||
void __init tegra_pmc_init(void)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
tegra_pmc_parse_dt();
|
||||
|
||||
val = tegra_pmc_readl(PMC_CTRL);
|
||||
if (tegra_pmc_invert_interrupt)
|
||||
val |= PMC_CTRL_INTR_LOW;
|
||||
else
|
||||
val &= ~PMC_CTRL_INTR_LOW;
|
||||
tegra_pmc_writel(val, PMC_CTRL);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ bool tegra_pmc_cpu_is_powered(int cpuid);
|
|||
int tegra_pmc_cpu_power_on(int cpuid);
|
||||
int tegra_pmc_cpu_remove_clamping(int cpuid);
|
||||
|
||||
void tegra_pmc_init_irq(void);
|
||||
void tegra_pmc_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/sys_soc.h>
|
||||
#include <linux/usb/tegra_usb_phy.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
@ -44,6 +45,7 @@
|
|||
#include "common.h"
|
||||
#include "fuse.h"
|
||||
#include "iomap.h"
|
||||
#include "pmc.h"
|
||||
|
||||
static void __init tegra_dt_init(void)
|
||||
{
|
||||
|
@ -51,6 +53,8 @@ static void __init tegra_dt_init(void)
|
|||
struct soc_device *soc_dev;
|
||||
struct device *parent = NULL;
|
||||
|
||||
tegra_pmc_init();
|
||||
|
||||
tegra_clocks_apply_init_table();
|
||||
|
||||
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
|
||||
|
@ -80,6 +84,12 @@ out:
|
|||
of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
|
||||
}
|
||||
|
||||
static void __init tegra_dt_init_time(void)
|
||||
{
|
||||
of_clk_init(NULL);
|
||||
clocksource_of_init();
|
||||
}
|
||||
|
||||
static void __init paz00_init(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
|
||||
|
@ -119,7 +129,7 @@ DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
|
|||
.smp = smp_ops(tegra_smp_ops),
|
||||
.init_early = tegra_init_early,
|
||||
.init_irq = tegra_dt_init_irq,
|
||||
.init_time = clocksource_of_init,
|
||||
.init_time = tegra_dt_init_time,
|
||||
.init_machine = tegra_dt_init,
|
||||
.init_late = tegra_dt_init_late,
|
||||
.restart = tegra_assert_system_reset,
|
||||
|
|
Загрузка…
Ссылка в новой задаче