Skip to content

Commit

Permalink
Merge tag 'memory-controller-drv-tegra-5.12' of git://git.kernel.org/…
Browse files Browse the repository at this point in the history
…pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into arm/drivers

Memory controller drivers for v5.12 - Tegra SoC

1. Make the tegra124-emc driver modular.
2. Add interconnect support to Tegra124 memory controller drivers.
3. Minor fixes.

* tag 'memory-controller-drv-tegra-5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
  memory: tegra: Remove calls to dev_pm_opp_set_clkname()
  memory: tegra: Check whether reset is already asserted
  memory: tegra124: Support interconnect framework
  memory: tegra124-emc: Continue probing if timings are missing in device-tree
  memory: tegra124-emc: Make driver modular

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
  • Loading branch information
arndb committed Feb 2, 2021
2 parents 993fd7d + 25d9877 commit 4d29b82
Show file tree
Hide file tree
Showing 13 changed files with 508 additions and 93 deletions.
3 changes: 3 additions & 0 deletions drivers/clk/tegra/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ config TEGRA_CLK_DFLL
depends on ARCH_TEGRA_124_SOC || ARCH_TEGRA_210_SOC
select PM_OPP
def_bool y

config TEGRA124_CLK_EMC
bool
2 changes: 1 addition & 1 deletion drivers/clk/tegra/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra20-emc.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
obj-$(CONFIG_TEGRA_CLK_DFLL) += clk-tegra124-dfll-fcpu.o
obj-$(CONFIG_TEGRA124_EMC) += clk-tegra124-emc.o
obj-$(CONFIG_TEGRA124_CLK_EMC) += clk-tegra124-emc.o
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
obj-y += cvb.o
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
Expand Down
41 changes: 36 additions & 5 deletions drivers/clk/tegra/clk-tegra124-emc.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk/tegra.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
Expand All @@ -21,7 +23,6 @@
#include <linux/string.h>

#include <soc/tegra/fuse.h>
#include <soc/tegra/emc.h>

#include "clk.h"

Expand Down Expand Up @@ -80,6 +81,9 @@ struct tegra_clk_emc {
int num_timings;
struct emc_timing *timings;
spinlock_t *lock;

tegra124_emc_prepare_timing_change_cb *prepare_timing_change;
tegra124_emc_complete_timing_change_cb *complete_timing_change;
};

/* Common clock framework callback implementations */
Expand Down Expand Up @@ -176,6 +180,9 @@ static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra)
if (tegra->emc)
return tegra->emc;

if (!tegra->prepare_timing_change || !tegra->complete_timing_change)
return NULL;

if (!tegra->emc_node)
return NULL;

Expand Down Expand Up @@ -241,7 +248,7 @@ static int emc_set_timing(struct tegra_clk_emc *tegra,

div = timing->parent_rate / (timing->rate / 2) - 2;

err = tegra_emc_prepare_timing_change(emc, timing->rate);
err = tegra->prepare_timing_change(emc, timing->rate);
if (err)
return err;

Expand All @@ -259,7 +266,7 @@ static int emc_set_timing(struct tegra_clk_emc *tegra,

spin_unlock_irqrestore(tegra->lock, flags);

tegra_emc_complete_timing_change(emc, timing->rate);
tegra->complete_timing_change(emc, timing->rate);

clk_hw_reparent(&tegra->hw, __clk_get_hw(timing->parent));
clk_disable_unprepare(tegra->prev_parent);
Expand Down Expand Up @@ -473,8 +480,8 @@ static const struct clk_ops tegra_clk_emc_ops = {
.get_parent = emc_get_parent,
};

struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
spinlock_t *lock)
struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np,
spinlock_t *lock)
{
struct tegra_clk_emc *tegra;
struct clk_init_data init;
Expand Down Expand Up @@ -538,3 +545,27 @@ struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,

return clk;
};

void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb,
tegra124_emc_complete_timing_change_cb *complete_cb)
{
struct clk *clk = __clk_lookup("emc");
struct tegra_clk_emc *tegra;
struct clk_hw *hw;

if (clk) {
hw = __clk_get_hw(clk);
tegra = container_of(hw, struct tegra_clk_emc, hw);

tegra->prepare_timing_change = prep_cb;
tegra->complete_timing_change = complete_cb;
}
}
EXPORT_SYMBOL_GPL(tegra124_clk_set_emc_callbacks);

bool tegra124_clk_emc_driver_available(struct clk_hw *hw)
{
struct tegra_clk_emc *tegra = container_of(hw, struct tegra_clk_emc, hw);

return tegra->prepare_timing_change && tegra->complete_timing_change;
}
26 changes: 23 additions & 3 deletions drivers/clk/tegra/clk-tegra124.c
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,26 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
writel(plld_base, clk_base + PLLD_BASE);
}

static struct clk *tegra124_clk_src_onecell_get(struct of_phandle_args *clkspec,
void *data)
{
struct clk_hw *hw;
struct clk *clk;

clk = of_clk_src_onecell_get(clkspec, data);
if (IS_ERR(clk))
return clk;

hw = __clk_get_hw(clk);

if (clkspec->args[0] == TEGRA124_CLK_EMC) {
if (!tegra124_clk_emc_driver_available(hw))
return ERR_PTR(-EPROBE_DEFER);
}

return clk;
}

/**
* tegra124_132_clock_init_post - clock initialization postamble for T124/T132
* @np: struct device_node * of the DT node for the SoC CAR IP block
Expand All @@ -1516,10 +1536,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
&pll_x_params);
tegra_init_special_resets(1, tegra124_reset_assert,
tegra124_reset_deassert);
tegra_add_of_provider(np, of_clk_src_onecell_get);
tegra_add_of_provider(np, tegra124_clk_src_onecell_get);

clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
&emc_lock);
clks[TEGRA124_CLK_EMC] = tegra124_clk_register_emc(clk_base, np,
&emc_lock);

tegra_register_devclks(devclks, ARRAY_SIZE(devclks));

Expand Down
18 changes: 12 additions & 6 deletions drivers/clk/tegra/clk.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,16 +881,22 @@ void tegra_super_clk_gen5_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params);

#ifdef CONFIG_TEGRA124_EMC
struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
spinlock_t *lock);
#ifdef CONFIG_TEGRA124_CLK_EMC
struct clk *tegra124_clk_register_emc(void __iomem *base, struct device_node *np,
spinlock_t *lock);
bool tegra124_clk_emc_driver_available(struct clk_hw *emc_hw);
#else
static inline struct clk *tegra_clk_register_emc(void __iomem *base,
struct device_node *np,
spinlock_t *lock)
static inline struct clk *
tegra124_clk_register_emc(void __iomem *base, struct device_node *np,
spinlock_t *lock)
{
return NULL;
}

static inline bool tegra124_clk_emc_driver_available(struct clk_hw *emc_hw)
{
return false;
}
#endif

void tegra114_clock_tune_cpu_trimmers_high(void);
Expand Down
4 changes: 3 additions & 1 deletion drivers/memory/tegra/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ config TEGRA30_EMC
external memory.

config TEGRA124_EMC
bool "NVIDIA Tegra124 External Memory Controller driver"
tristate "NVIDIA Tegra124 External Memory Controller driver"
default y
depends on TEGRA_MC && ARCH_TEGRA_124_SOC
select TEGRA124_CLK_EMC
select PM_OPP
help
This driver is for the External Memory Controller (EMC) found on
Tegra124 chips. The EMC controls the external DRAM on the board.
Expand Down
7 changes: 7 additions & 0 deletions drivers/memory/tegra/mc.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev,
if (!rst_ops)
return -ENODEV;

/* DMA flushing will fail if reset is already asserted */
if (rst_ops->reset_status) {
/* check whether reset is asserted */
if (rst_ops->reset_status(mc, rst))
return 0;
}

if (rst_ops->block_dma) {
/* block clients DMA requests */
err = rst_ops->block_dma(mc, rst);
Expand Down
Loading

0 comments on commit 4d29b82

Please sign in to comment.