Commit 2cd7b043 authored by Michael Turquette's avatar Michael Turquette

Merge tag 'tegra-for-4.2-clk' of...

Merge tag 'tegra-for-4.2-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-next

clk: tegra: Changes for v4.2-rc1

This contains the EMC clock driver that's been exhaustively reviewed and
tested. It also includes a change to the clock core that allows a clock
provider to perform low-level reparenting of clocks. This is required by
the EMC clock driver because the reparenting needs to be done at a very
specific point in time during the EMC frequency switch.
parents 85e88fab 36b7be6d
...@@ -20,15 +20,38 @@ Required properties : ...@@ -20,15 +20,38 @@ Required properties :
- #reset-cells : Should be 1. - #reset-cells : Should be 1.
In clock consumers, this cell represents the bit number in the CAR's In clock consumers, this cell represents the bit number in the CAR's
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers. array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
- nvidia,external-memory-controller : phandle of the EMC driver.
The node should contain a "emc-timings" subnode for each supported RAM type (see
field RAM_CODE in register PMC_STRAPPING_OPT_A).
Required properties for "emc-timings" nodes :
- nvidia,ram-code : Should contain the value of RAM_CODE this timing set
is used for.
Each "emc-timings" node should contain a "timing" subnode for every supported
EMC clock rate.
Required properties for "timing" nodes :
- clock-frequency : Should contain the memory clock rate to which this timing
relates.
- nvidia,parent-clock-frequency : Should contain the rate at which the current
parent of the EMC clock should be running at this timing.
- clocks : Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names : Must include the following entries:
- emc-parent : the clock that should be the parent of the EMC clock at this
timing.
Example SoC include file: Example SoC include file:
/ { / {
tegra_car: clock { tegra_car: clock@60006000 {
compatible = "nvidia,tegra124-car"; compatible = "nvidia,tegra124-car";
reg = <0x60006000 0x1000>; reg = <0x60006000 0x1000>;
#clock-cells = <1>; #clock-cells = <1>;
#reset-cells = <1>; #reset-cells = <1>;
nvidia,external-memory-controller = <&emc>;
}; };
usb@c5004000 { usb@c5004000 {
...@@ -62,4 +85,23 @@ Example board file: ...@@ -62,4 +85,23 @@ Example board file:
&tegra_car { &tegra_car {
clocks = <&clk_32k> <&osc>; clocks = <&clk_32k> <&osc>;
}; };
clock@60006000 {
emc-timings-3 {
nvidia,ram-code = <3>;
timing-12750000 {
clock-frequency = <12750000>;
nvidia,parent-clock-frequency = <408000000>;
clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
clock-names = "emc-parent";
};
timing-20400000 {
clock-frequency = <20400000>;
nvidia,parent-clock-frequency = <408000000>;
clocks = <&tegra_car TEGRA124_CLK_PLL_P>;
clock-names = "emc-parent";
};
};
};
}; };
...@@ -10,3 +10,5 @@ Required properties: ...@@ -10,3 +10,5 @@ Required properties:
The second entry gives the physical address and length of the The second entry gives the physical address and length of the
registers indicating the strapping options. registers indicating the strapping options.
Optional properties:
- nvidia,long-ram-code: If present, the RAM code is long (4 bit). If not, short (2 bit).
...@@ -176,3 +176,4 @@ endmenu ...@@ -176,3 +176,4 @@ endmenu
source "drivers/clk/mvebu/Kconfig" source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/samsung/Kconfig" source "drivers/clk/samsung/Kconfig"
source "drivers/clk/tegra/Kconfig"
...@@ -1660,6 +1660,14 @@ static void clk_core_reparent(struct clk_core *core, ...@@ -1660,6 +1660,14 @@ static void clk_core_reparent(struct clk_core *core,
__clk_recalc_rates(core, POST_RATE_CHANGE); __clk_recalc_rates(core, POST_RATE_CHANGE);
} }
void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
{
if (!hw)
return;
clk_core_reparent(hw->core, !new_parent ? NULL : new_parent->core);
}
/** /**
* clk_has_parent - check if a clock is a possible parent for another * clk_has_parent - check if a clock is a possible parent for another
* @clk: clock source * @clk: clock source
......
config TEGRA_CLK_EMC
def_bool y
depends on TEGRA124_EMC
...@@ -11,6 +11,7 @@ obj-y += clk-tegra-periph.o ...@@ -11,6 +11,7 @@ obj-y += clk-tegra-periph.o
obj-y += clk-tegra-pmc.o obj-y += clk-tegra-pmc.o
obj-y += clk-tegra-fixed.o obj-y += clk-tegra-fixed.o
obj-y += clk-tegra-super-gen4.o obj-y += clk-tegra-super-gen4.o
obj-$(CONFIG_TEGRA_CLK_EMC) += clk-emc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
......
This diff is collapsed.
...@@ -152,11 +152,6 @@ static unsigned long tegra124_input_freq[] = { ...@@ -152,11 +152,6 @@ static unsigned long tegra124_input_freq[] = {
[12] = 260000000, [12] = 260000000,
}; };
static const char *mux_pllmcp_clkm[] = {
"pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
};
#define mux_pllmcp_clkm_idx NULL
static struct div_nmp pllxc_nmp = { static struct div_nmp pllxc_nmp = {
.divm_shift = 0, .divm_shift = 0,
.divm_width = 8, .divm_width = 8,
...@@ -791,7 +786,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = { ...@@ -791,7 +786,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
[tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true }, [tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true },
[tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true }, [tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true },
[tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true }, [tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true },
[tegra_clk_emc] = { .dt_id = TEGRA124_CLK_EMC, .present = true },
[tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true }, [tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true },
[tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true }, [tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true },
[tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true }, [tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true },
...@@ -1127,13 +1121,7 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base, ...@@ -1127,13 +1121,7 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
periph_clk_enb_refcnt); periph_clk_enb_refcnt);
clks[TEGRA124_CLK_DSIB] = clk; clks[TEGRA124_CLK_DSIB] = clk;
/* emc mux */ clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm), 0,
clk_base + CLK_SOURCE_EMC,
29, 3, 0, &emc_lock);
clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
&emc_lock); &emc_lock);
clks[TEGRA124_CLK_MC] = clk; clks[TEGRA124_CLK_MC] = clk;
...@@ -1389,7 +1377,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = { ...@@ -1389,7 +1377,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
{TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0}, {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
{TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0}, {TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
{TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0}, {TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
{TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
{TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1}, {TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
{TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1}, {TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
{TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0}, {TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
...@@ -1513,6 +1500,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np) ...@@ -1513,6 +1500,10 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks, tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
&pll_x_params); &pll_x_params);
tegra_add_of_provider(np); tegra_add_of_provider(np);
clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
&emc_lock);
tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
tegra_cpu_car_ops = &tegra124_cpu_car_ops; tegra_cpu_car_ops = &tegra124_cpu_car_ops;
......
...@@ -679,7 +679,7 @@ static struct tegra_devclk devclks[] __initdata = { ...@@ -679,7 +679,7 @@ static struct tegra_devclk devclks[] __initdata = {
{ .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 }, { .dev_id = "tegra30-dam.1", .dt_id = TEGRA30_CLK_DAM1 },
{ .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 }, { .dev_id = "tegra30-dam.2", .dt_id = TEGRA30_CLK_DAM2 },
{ .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA }, { .con_id = "hda", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA },
{ .con_id = "hda2codec", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X }, { .con_id = "hda2codec_2x", .dev_id = "tegra30-hda", .dt_id = TEGRA30_CLK_HDA2CODEC_2X },
{ .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 }, { .dev_id = "spi_tegra.0", .dt_id = TEGRA30_CLK_SBC1 },
{ .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 }, { .dev_id = "spi_tegra.1", .dt_id = TEGRA30_CLK_SBC2 },
{ .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 }, { .dev_id = "spi_tegra.2", .dt_id = TEGRA30_CLK_SBC3 },
......
...@@ -623,6 +623,18 @@ void tegra_super_clk_gen4_init(void __iomem *clk_base, ...@@ -623,6 +623,18 @@ void tegra_super_clk_gen4_init(void __iomem *clk_base,
void __iomem *pmc_base, struct tegra_clk *tegra_clks, void __iomem *pmc_base, struct tegra_clk *tegra_clks,
struct tegra_clk_pll_params *pll_params); struct tegra_clk_pll_params *pll_params);
#ifdef CONFIG_TEGRA_CLK_EMC
struct clk *tegra_clk_register_emc(void __iomem *base, struct device_node *np,
spinlock_t *lock);
#else
static inline struct clk *tegra_clk_register_emc(void __iomem *base,
struct device_node *np,
spinlock_t *lock)
{
return NULL;
}
#endif
void tegra114_clock_tune_cpu_trimmers_high(void); void tegra114_clock_tune_cpu_trimmers_high(void);
void tegra114_clock_tune_cpu_trimmers_low(void); void tegra114_clock_tune_cpu_trimmers_low(void);
void tegra114_clock_tune_cpu_trimmers_init(void); void tegra114_clock_tune_cpu_trimmers_init(void);
......
...@@ -28,8 +28,15 @@ ...@@ -28,8 +28,15 @@
#define APBMISC_SIZE 0x64 #define APBMISC_SIZE 0x64
#define FUSE_SKU_INFO 0x10 #define FUSE_SKU_INFO 0x10
#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \
(0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \
(0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
static void __iomem *apbmisc_base; static void __iomem *apbmisc_base;
static void __iomem *strapping_base; static void __iomem *strapping_base;
static bool long_ram_code;
u32 tegra_read_chipid(void) u32 tegra_read_chipid(void)
{ {
...@@ -54,6 +61,18 @@ u32 tegra_read_straps(void) ...@@ -54,6 +61,18 @@ u32 tegra_read_straps(void)
return 0; return 0;
} }
u32 tegra_read_ram_code(void)
{
u32 straps = tegra_read_straps();
if (long_ram_code)
straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG;
else
straps &= PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT;
return straps >> PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT;
}
static const struct of_device_id apbmisc_match[] __initconst = { static const struct of_device_id apbmisc_match[] __initconst = {
{ .compatible = "nvidia,tegra20-apbmisc", }, { .compatible = "nvidia,tegra20-apbmisc", },
{}, {},
...@@ -112,4 +131,6 @@ void __init tegra_init_apbmisc(void) ...@@ -112,4 +131,6 @@ void __init tegra_init_apbmisc(void)
strapping_base = of_iomap(np, 1); strapping_base = of_iomap(np, 1);
if (!strapping_base) if (!strapping_base)
pr_err("ioremap tegra strapping_base failed\n"); pr_err("ioremap tegra strapping_base failed\n");
long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
} }
...@@ -592,6 +592,7 @@ long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate, ...@@ -592,6 +592,7 @@ long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
unsigned long max_rate, unsigned long max_rate,
unsigned long *best_parent_rate, unsigned long *best_parent_rate,
struct clk_hw **best_parent_p); struct clk_hw **best_parent_p);
void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src) static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
{ {
......
...@@ -56,6 +56,7 @@ struct tegra_sku_info { ...@@ -56,6 +56,7 @@ struct tegra_sku_info {
}; };
u32 tegra_read_straps(void); u32 tegra_read_straps(void);
u32 tegra_read_ram_code(void);
u32 tegra_read_chipid(void); u32 tegra_read_chipid(void);
int tegra_fuse_readl(unsigned long offset, u32 *value); int tegra_fuse_readl(unsigned long offset, u32 *value);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment