diff options
Diffstat (limited to 'drivers')
27 files changed, 927 insertions, 476 deletions
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c index f02cb41d40a4..76de9a762a86 100644 --- a/drivers/clk/hisilicon/clk-hi6220.c +++ b/drivers/clk/hisilicon/clk-hi6220.c @@ -68,6 +68,8 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = { { HI6220_TIMER7_PCLK, "timer7_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 22, 0, }, { HI6220_TIMER8_PCLK, "timer8_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 23, 0, }, { HI6220_UART0_PCLK, "uart0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 24, 0, }, + { HI6220_RTC0_PCLK, "rtc0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 25, 0, }, + { HI6220_RTC1_PCLK, "rtc1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 26, 0, }, }; static void __init hi6220_clk_ao_init(struct device_node *np) diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 2115ce410cfb..41a12d376799 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -1,6 +1,7 @@ config CLK_RENESAS_CPG_MSSR bool default y if ARCH_R8A7795 + default y if ARCH_R8A7796 config CLK_RENESAS_CPG_MSTP bool @@ -11,6 +12,7 @@ config CLK_RENESAS_CPG_MSTP default y if ARCH_R8A7779 default y if ARCH_R8A7790 default y if ARCH_R8A7791 + default y if ARCH_R8A7792 default y if ARCH_R8A7793 default y if ARCH_R8A7794 default y if ARCH_SH73A0 diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index ead8bb843524..90dd0db7d9c6 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -6,9 +6,11 @@ obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-div6.o +obj-$(CONFIG_ARCH_R8A7792) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-div6.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-div6.o -obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o +obj-$(CONFIG_ARCH_R8A7795) += r8a7795-cpg-mssr.o rcar-gen3-cpg.o +obj-$(CONFIG_ARCH_R8A7796) += r8a7796-cpg-mssr.o rcar-gen3-cpg.o obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-div6.o obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o clk-div6.o diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index ca5519c583d4..d359c92e13a6 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -12,22 +12,14 @@ * the Free Software Foundation; version 2 of the License. */ -#include <linux/bug.h> -#include <linux/clk.h> -#include <linux/clk-provider.h> #include <linux/device.h> -#include <linux/err.h> #include <linux/init.h> -#include <linux/io.h> #include <linux/kernel.h> -#include <linux/of.h> -#include <linux/slab.h> #include <dt-bindings/clock/r8a7795-cpg-mssr.h> #include "renesas-cpg-mssr.h" - -#define CPG_RCKCR 0x240 +#include "rcar-gen3-cpg.h" enum clk_ids { /* Core Clock Outputs exported to DT */ @@ -58,20 +50,6 @@ enum clk_ids { MOD_CLK_BASE }; -enum r8a7795_clk_types { - CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM, - CLK_TYPE_GEN3_PLL0, - CLK_TYPE_GEN3_PLL1, - CLK_TYPE_GEN3_PLL2, - CLK_TYPE_GEN3_PLL3, - CLK_TYPE_GEN3_PLL4, - CLK_TYPE_GEN3_SD, - CLK_TYPE_GEN3_R, -}; - -#define DEF_GEN3_SD(_name, _id, _parent, _offset) \ - DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) - static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -129,6 +107,9 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { + DEF_MOD("fdp1-2", 117, R8A7795_CLK_S2D1), + DEF_MOD("fdp1-1", 118, R8A7795_CLK_S2D1), + DEF_MOD("fdp1-0", 119, R8A7795_CLK_S2D1), DEF_MOD("scif5", 202, R8A7795_CLK_S3D4), DEF_MOD("scif4", 203, R8A7795_CLK_S3D4), DEF_MOD("scif3", 204, R8A7795_CLK_S3D4), @@ -157,11 +138,20 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1), DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4), DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4), + DEF_MOD("drif7", 508, R8A7795_CLK_S3D2), + DEF_MOD("drif6", 509, R8A7795_CLK_S3D2), + DEF_MOD("drif5", 510, R8A7795_CLK_S3D2), + DEF_MOD("drif4", 511, R8A7795_CLK_S3D2), + DEF_MOD("drif3", 512, R8A7795_CLK_S3D2), + DEF_MOD("drif2", 513, R8A7795_CLK_S3D2), + DEF_MOD("drif1", 514, R8A7795_CLK_S3D2), + DEF_MOD("drif0", 515, R8A7795_CLK_S3D2), DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1), DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1), DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1), DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1), DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1), + DEF_MOD("thermal", 522, R8A7795_CLK_CP), DEF_MOD("pwm", 523, R8A7795_CLK_S3D4), DEF_MOD("fcpvd3", 600, R8A7795_CLK_S2D1), DEF_MOD("fcpvd2", 601, R8A7795_CLK_S2D1), @@ -199,7 +189,7 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = { DEF_MOD("du2", 722, R8A7795_CLK_S2D1), DEF_MOD("du1", 723, R8A7795_CLK_S2D1), DEF_MOD("du0", 724, R8A7795_CLK_S2D1), - DEF_MOD("lvds", 727, R8A7795_CLK_S2D1), + DEF_MOD("lvds", 727, R8A7795_CLK_S0D4), DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI), DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI), DEF_MOD("vin7", 804, R8A7795_CLK_S2D1), @@ -262,225 +252,6 @@ static const unsigned int r8a7795_crit_mod_clks[] __initconst = { MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; -/* ----------------------------------------------------------------------------- - * SDn Clock - * - */ -#define CPG_SD_STP_HCK BIT(9) -#define CPG_SD_STP_CK BIT(8) - -#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) -#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) - -#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ -{ \ - .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ - ((stp_ck) ? CPG_SD_STP_CK : 0) | \ - ((sd_srcfc) << 2) | \ - ((sd_fc) << 0), \ - .div = (sd_div), \ -} - -struct sd_div_table { - u32 val; - unsigned int div; -}; - -struct sd_clock { - struct clk_hw hw; - void __iomem *reg; - const struct sd_div_table *div_table; - unsigned int div_num; - unsigned int div_min; - unsigned int div_max; -}; - -/* SDn divider - * sd_srcfc sd_fc div - * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc - *------------------------------------------------------------------- - * 0 0 0 (1) 1 (4) 4 - * 0 0 1 (2) 1 (4) 8 - * 1 0 2 (4) 1 (4) 16 - * 1 0 3 (8) 1 (4) 32 - * 1 0 4 (16) 1 (4) 64 - * 0 0 0 (1) 0 (2) 2 - * 0 0 1 (2) 0 (2) 4 - * 1 0 2 (4) 0 (2) 8 - * 1 0 3 (8) 0 (2) 16 - * 1 0 4 (16) 0 (2) 32 - */ -static const struct sd_div_table cpg_sd_div_table[] = { -/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), -}; - -#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) - -static int cpg_sd_clock_enable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - u32 val, sd_fc; - unsigned int i; - - val = clk_readl(clock->reg); - - sd_fc = val & CPG_SD_FC_MASK; - for (i = 0; i < clock->div_num; i++) - if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) - break; - - if (i >= clock->div_num) - return -EINVAL; - - val &= ~(CPG_SD_STP_MASK); - val |= clock->div_table[i].val & CPG_SD_STP_MASK; - - clk_writel(val, clock->reg); - - return 0; -} - -static void cpg_sd_clock_disable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); -} - -static int cpg_sd_clock_is_enabled(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - return !(clk_readl(clock->reg) & CPG_SD_STP_MASK); -} - -static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned long rate = parent_rate; - u32 val, sd_fc; - unsigned int i; - - val = clk_readl(clock->reg); - - sd_fc = val & CPG_SD_FC_MASK; - for (i = 0; i < clock->div_num; i++) - if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) - break; - - if (i >= clock->div_num) - return -EINVAL; - - return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); -} - -static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, - unsigned long rate, - unsigned long parent_rate) -{ - unsigned int div; - - if (!rate) - rate = 1; - - div = DIV_ROUND_CLOSEST(parent_rate, rate); - - return clamp_t(unsigned int, div, clock->div_min, clock->div_max); -} - -static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate); - - return DIV_ROUND_CLOSEST(*parent_rate, div); -} - -static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate); - u32 val; - unsigned int i; - - for (i = 0; i < clock->div_num; i++) - if (div == clock->div_table[i].div) - break; - - if (i >= clock->div_num) - return -EINVAL; - - val = clk_readl(clock->reg); - val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); - val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); - clk_writel(val, clock->reg); - - return 0; -} - -static const struct clk_ops cpg_sd_clock_ops = { - .enable = cpg_sd_clock_enable, - .disable = cpg_sd_clock_disable, - .is_enabled = cpg_sd_clock_is_enabled, - .recalc_rate = cpg_sd_clock_recalc_rate, - .round_rate = cpg_sd_clock_round_rate, - .set_rate = cpg_sd_clock_set_rate, -}; - -static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, - void __iomem *base, - const char *parent_name) -{ - struct clk_init_data init; - struct sd_clock *clock; - struct clk *clk; - unsigned int i; - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) - return ERR_PTR(-ENOMEM); - - init.name = core->name; - init.ops = &cpg_sd_clock_ops; - init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; - init.parent_names = &parent_name; - init.num_parents = 1; - - clock->reg = base + core->offset; - clock->hw.init = &init; - clock->div_table = cpg_sd_div_table; - clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - - clock->div_max = clock->div_table[0].div; - clock->div_min = clock->div_max; - for (i = 1; i < clock->div_num; i++) { - clock->div_max = max(clock->div_max, clock->div_table[i].div); - clock->div_min = min(clock->div_min, clock->div_table[i].div); - } - - clk = clk_register(NULL, &clock->hw); - if (IS_ERR(clk)) - kfree(clock); - - return clk; -} - -#define CPG_PLL0CR 0x00d8 -#define CPG_PLL2CR 0x002c -#define CPG_PLL4CR 0x01f4 /* * CPG Clock Data @@ -512,13 +283,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, (((md) & BIT(19)) >> 18) | \ (((md) & BIT(17)) >> 17)) -struct cpg_pll_config { - unsigned int extal_div; - unsigned int pll1_mult; - unsigned int pll3_mult; -}; - -static const struct cpg_pll_config cpg_pll_configs[16] __initconst = { +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { /* EXTAL div PLL1 mult PLL3 mult */ { 1, 192, 192, }, { 1, 192, 128, }, @@ -538,112 +303,9 @@ static const struct cpg_pll_config cpg_pll_configs[16] __initconst = { { 2, 192, 192, }, }; -static const struct cpg_pll_config *cpg_pll_config __initdata; - -static -struct clk * __init r8a7795_cpg_clk_register(struct device *dev, - const struct cpg_core_clk *core, - const struct cpg_mssr_info *info, - struct clk **clks, - void __iomem *base) -{ - const struct clk *parent; - unsigned int mult = 1; - unsigned int div = 1; - u32 value; - - parent = clks[core->parent]; - if (IS_ERR(parent)) - return ERR_CAST(parent); - - switch (core->type) { - case CLK_TYPE_GEN3_MAIN: - div = cpg_pll_config->extal_div; - break; - - case CLK_TYPE_GEN3_PLL0: - /* - * PLL0 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL0CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_PLL1: - mult = cpg_pll_config->pll1_mult; - break; - - case CLK_TYPE_GEN3_PLL2: - /* - * PLL2 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL2CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_PLL3: - mult = cpg_pll_config->pll3_mult; - break; - - case CLK_TYPE_GEN3_PLL4: - /* - * PLL4 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. - */ - value = readl(base + CPG_PLL4CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - break; - - case CLK_TYPE_GEN3_SD: - return cpg_sd_clk_register(core, base, __clk_get_name(parent)); - - case CLK_TYPE_GEN3_R: - /* RINT is default. Only if EXTALR is populated, we switch to it */ - value = readl(base + CPG_RCKCR) & 0x3f; - - if (clk_get_rate(clks[CLK_EXTALR])) { - parent = clks[CLK_EXTALR]; - value |= BIT(15); - } - - writel(value, base + CPG_RCKCR); - break; - - default: - return ERR_PTR(-EINVAL); - } - - return clk_register_fixed_factor(NULL, core->name, - __clk_get_name(parent), 0, mult, div); -} - -/* - * Reset register definitions. - */ -#define MODEMR 0xe6160060 - -static u32 rcar_gen3_read_mode_pins(void) -{ - void __iomem *modemr = ioremap_nocache(MODEMR, 4); - u32 mode; - - BUG_ON(!modemr); - mode = ioread32(modemr); - iounmap(modemr); - - return mode; -} - static int __init r8a7795_cpg_mssr_init(struct device *dev) { + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; u32 cpg_mode = rcar_gen3_read_mode_pins(); cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; @@ -652,7 +314,7 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev) return -EINVAL; } - return 0; + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR); } const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { @@ -673,5 +335,5 @@ const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = { /* Callbacks */ .init = r8a7795_cpg_mssr_init, - .cpg_clk_register = r8a7795_cpg_clk_register, + .cpg_clk_register = rcar_gen3_cpg_clk_register, }; diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c new file mode 100644 index 000000000000..c84b549c14d2 --- /dev/null +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -0,0 +1,192 @@ +/* + * r8a7796 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2016 Glider bvba + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2015 Renesas Electronics Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/kernel.h> + +#include <dt-bindings/clock/r8a7796-cpg-mssr.h> + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A7796_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL2, + CLK_PLL3, + CLK_PLL4, + CLK_PLL1_DIV2, + CLK_PLL1_DIV4, + CLK_S0, + CLK_S1, + CLK_S2, + CLK_S3, + CLK_SDSRC, + CLK_SSPSRC, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), + DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + + /* Core Clock Outputs */ + DEF_FIXED("ztr", R8A7796_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A7796_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A7796_CLK_ZT, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("zx", R8A7796_CLK_ZX, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED("s0d1", R8A7796_CLK_S0D1, CLK_S0, 1, 1), + DEF_FIXED("s0d2", R8A7796_CLK_S0D2, CLK_S0, 2, 1), + DEF_FIXED("s0d3", R8A7796_CLK_S0D3, CLK_S0, 3, 1), + DEF_FIXED("s0d4", R8A7796_CLK_S0D4, CLK_S0, 4, 1), + DEF_FIXED("s0d6", R8A7796_CLK_S0D6, CLK_S0, 6, 1), + DEF_FIXED("s0d8", R8A7796_CLK_S0D8, CLK_S0, 8, 1), + DEF_FIXED("s0d12", R8A7796_CLK_S0D12, CLK_S0, 12, 1), + DEF_FIXED("s1d1", R8A7796_CLK_S1D1, CLK_S1, 1, 1), + DEF_FIXED("s1d2", R8A7796_CLK_S1D2, CLK_S1, 2, 1), + DEF_FIXED("s1d4", R8A7796_CLK_S1D4, CLK_S1, 4, 1), + DEF_FIXED("s2d1", R8A7796_CLK_S2D1, CLK_S2, 1, 1), + DEF_FIXED("s2d2", R8A7796_CLK_S2D2, CLK_S2, 2, 1), + DEF_FIXED("s2d4", R8A7796_CLK_S2D4, CLK_S2, 4, 1), + DEF_FIXED("s3d1", R8A7796_CLK_S3D1, CLK_S3, 1, 1), + DEF_FIXED("s3d2", R8A7796_CLK_S3D2, CLK_S3, 2, 1), + DEF_FIXED("s3d4", R8A7796_CLK_S3D4, CLK_S3, 4, 1), + + DEF_FIXED("cl", R8A7796_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cp", R8A7796_CLK_CP, CLK_EXTAL, 2, 1), +}; + +static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { + DEF_MOD("scif2", 310, R8A7796_CLK_S3D4), + DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1), +}; + +static const unsigned int r8a7796_crit_mod_clks[] __initconst = { + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 + * 14 13 19 17 (MHz) + *------------------------------------------------------------------- + * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 + * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 + * 0 0 1 0 Prohibited setting + * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 + * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 + * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 + * 0 1 1 0 Prohibited setting + * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 + * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 + * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 + * 1 0 1 0 Prohibited setting + * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 + * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 + * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 + * 1 1 1 0 Prohibited setting + * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \ + (((md) & BIT(13)) >> 11) | \ + (((md) & BIT(19)) >> 18) | \ + (((md) & BIT(17)) >> 17)) + +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { + /* EXTAL div PLL1 mult PLL3 mult */ + { 1, 192, 192, }, + { 1, 192, 128, }, + { 0, /* Prohibited setting */ }, + { 1, 192, 192, }, + { 1, 160, 160, }, + { 1, 160, 106, }, + { 0, /* Prohibited setting */ }, + { 1, 160, 160, }, + { 1, 128, 128, }, + { 1, 128, 84, }, + { 0, /* Prohibited setting */ }, + { 1, 128, 128, }, + { 2, 192, 192, }, + { 2, 192, 128, }, + { 0, /* Prohibited setting */ }, + { 2, 192, 192, }, +}; + +static int __init r8a7796_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; + u32 cpg_mode = rcar_gen3_read_mode_pins(); + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + if (!cpg_pll_config->extal_div) { + dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); + return -EINVAL; + } + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR); +} + +const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a7796_core_clks, + .num_core_clks = ARRAY_SIZE(r8a7796_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a7796_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a7796_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a7796_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a7796_crit_mod_clks), + + /* Callbacks */ + .init = r8a7796_cpg_mssr_init, + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c new file mode 100644 index 000000000000..bb4f2f9a8c2f --- /dev/null +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -0,0 +1,359 @@ +/* + * R-Car Gen3 Clock Pulse Generator + * + * Copyright (C) 2015-2016 Glider bvba + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <linux/bug.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/slab.h> + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +#define CPG_PLL0CR 0x00d8 +#define CPG_PLL2CR 0x002c +#define CPG_PLL4CR 0x01f4 + + +/* + * SDn Clock + */ +#define CPG_SD_STP_HCK BIT(9) +#define CPG_SD_STP_CK BIT(8) + +#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) +#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) + +#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ +{ \ + .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ + ((stp_ck) ? CPG_SD_STP_CK : 0) | \ + ((sd_srcfc) << 2) | \ + ((sd_fc) << 0), \ + .div = (sd_div), \ +} + +struct sd_div_table { + u32 val; + unsigned int div; +}; + +struct sd_clock { + struct clk_hw hw; + void __iomem *reg; + const struct sd_div_table *div_table; + unsigned int div_num; + unsigned int div_min; + unsigned int div_max; +}; + +/* SDn divider + * sd_srcfc sd_fc div + * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc + *------------------------------------------------------------------- + * 0 0 0 (1) 1 (4) 4 + * 0 0 1 (2) 1 (4) 8 + * 1 0 2 (4) 1 (4) 16 + * 1 0 3 (8) 1 (4) 32 + * 1 0 4 (16) 1 (4) 64 + * 0 0 0 (1) 0 (2) 2 + * 0 0 1 (2) 0 (2) 4 + * 1 0 2 (4) 0 (2) 8 + * 1 0 3 (8) 0 (2) 16 + * 1 0 4 (16) 0 (2) 32 + */ +static const struct sd_div_table cpg_sd_div_table[] = { +/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), + CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), + CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), + CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), + CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), + CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), + CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), +}; + +#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) + +static int cpg_sd_clock_enable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + u32 val, sd_fc; + unsigned int i; + + val = clk_readl(clock->reg); + + sd_fc = val & CPG_SD_FC_MASK; + for (i = 0; i < clock->div_num; i++) + if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) + break; + + if (i >= clock->div_num) + return -EINVAL; + + val &= ~(CPG_SD_STP_MASK); + val |= clock->div_table[i].val & CPG_SD_STP_MASK; + + clk_writel(val, clock->reg); + + return 0; +} + +static void cpg_sd_clock_disable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg); +} + +static int cpg_sd_clock_is_enabled(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + return !(clk_readl(clock->reg) & CPG_SD_STP_MASK); +} + +static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned long rate = parent_rate; + u32 val, sd_fc; + unsigned int i; + + val = clk_readl(clock->reg); + + sd_fc = val & CPG_SD_FC_MASK; + for (i = 0; i < clock->div_num; i++) + if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) + break; + + if (i >= clock->div_num) + return -EINVAL; + + return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); +} + +static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, + unsigned long rate, + unsigned long parent_rate) +{ + unsigned int div; + + if (!rate) + rate = 1; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + + return clamp_t(unsigned int, div, clock->div_min, clock->div_max); +} + +static long cpg_sd_clock_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned int div = cpg_sd_clock_calc_div(clock, rate, *parent_rate); + + return DIV_ROUND_CLOSEST(*parent_rate, div); +} + +static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate); + u32 val; + unsigned int i; + + for (i = 0; i < clock->div_num; i++) + if (div == clock->div_table[i].div) + break; + + if (i >= clock->div_num) + return -EINVAL; + + val = clk_readl(clock->reg); + val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); + val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); + clk_writel(val, clock->reg); + + return 0; +} + +static const struct clk_ops cpg_sd_clock_ops = { + .enable = cpg_sd_clock_enable, + .disable = cpg_sd_clock_disable, + .is_enabled = cpg_sd_clock_is_enabled, + .recalc_rate = cpg_sd_clock_recalc_rate, + .round_rate = cpg_sd_clock_round_rate, + .set_rate = cpg_sd_clock_set_rate, +}; + +static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, + void __iomem *base, + const char *parent_name) +{ + struct clk_init_data init; + struct sd_clock *clock; + struct clk *clk; + unsigned int i; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) + return ERR_PTR(-ENOMEM); + + init.name = core->name; + init.ops = &cpg_sd_clock_ops; + init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->reg = base + core->offset; + clock->hw.init = &init; + clock->div_table = cpg_sd_div_table; + clock->div_num = ARRAY_SIZE(cpg_sd_div_table); + + clock->div_max = clock->div_table[0].div; + clock->div_min = clock->div_max; + for (i = 1; i < clock->div_num; i++) { + clock->div_max = max(clock->div_max, clock->div_table[i].div); + clock->div_min = min(clock->div_min, clock->div_table[i].div); + } + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + kfree(clock); + + return clk; +} + + +static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; +static unsigned int cpg_clk_extalr __initdata; + +struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base) +{ + const struct clk *parent; + unsigned int mult = 1; + unsigned int div = 1; + u32 value; + + parent = clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + switch (core->type) { + case CLK_TYPE_GEN3_MAIN: + div = cpg_pll_config->extal_div; + break; + + case CLK_TYPE_GEN3_PLL0: + /* + * PLL0 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL0CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_PLL1: + mult = cpg_pll_config->pll1_mult; + break; + + case CLK_TYPE_GEN3_PLL2: + /* + * PLL2 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL2CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_PLL3: + mult = cpg_pll_config->pll3_mult; + break; + + case CLK_TYPE_GEN3_PLL4: + /* + * PLL4 is a configurable multiplier clock. Register it as a + * fixed factor clock for now as there's no generic multiplier + * clock implementation and we currently have no need to change + * the multiplier value. + */ + value = readl(base + CPG_PLL4CR); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_GEN3_SD: + return cpg_sd_clk_register(core, base, __clk_get_name(parent)); + + case CLK_TYPE_GEN3_R: + /* + * RINT is default. + * Only if EXTALR is populated, we switch to it. + */ + value = readl(base + CPG_RCKCR) & 0x3f; + + if (clk_get_rate(clks[cpg_clk_extalr])) { + parent = clks[cpg_clk_extalr]; + value |= BIT(15); + } + + writel(value, base + CPG_RCKCR); + break; + + default: + return ERR_PTR(-EINVAL); + } + + return clk_register_fixed_factor(NULL, core->name, + __clk_get_name(parent), 0, mult, div); +} + +/* + * Reset register definitions. + */ +#define MODEMR 0xe6160060 + +u32 __init rcar_gen3_read_mode_pins(void) +{ + void __iomem *modemr = ioremap_nocache(MODEMR, 4); + u32 mode; + + BUG_ON(!modemr); + mode = ioread32(modemr); + iounmap(modemr); + + return mode; +} + +int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + unsigned int clk_extalr) +{ + cpg_pll_config = config; + cpg_clk_extalr = clk_extalr; + return 0; +} diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h new file mode 100644 index 000000000000..f699085147d1 --- /dev/null +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -0,0 +1,43 @@ +/* + * R-Car Gen3 Clock Pulse Generator + * + * Copyright (C) 2015-2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#ifndef __CLK_RENESAS_RCAR_GEN3_CPG_H__ +#define __CLK_RENESAS_RCAR_GEN3_CPG_H__ + +enum rcar_gen3_clk_types { + CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM, + CLK_TYPE_GEN3_PLL0, + CLK_TYPE_GEN3_PLL1, + CLK_TYPE_GEN3_PLL2, + CLK_TYPE_GEN3_PLL3, + CLK_TYPE_GEN3_PLL4, + CLK_TYPE_GEN3_SD, + CLK_TYPE_GEN3_R, +}; + +#define DEF_GEN3_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) + +struct rcar_gen3_cpg_pll_config { + unsigned int extal_div; + unsigned int pll1_mult; + unsigned int pll3_mult; +}; + +#define CPG_RCKCR 0x240 + +u32 rcar_gen3_read_mode_pins(void); +struct clk *rcar_gen3_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base); +int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config, + unsigned int clk_extalr); + +#endif diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 210cd744a7a9..e1365e7491ae 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -509,6 +509,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a7795_cpg_mssr_info, }, #endif +#ifdef CONFIG_ARCH_R8A7796 + { + .compatible = "renesas,r8a7796-cpg-mssr", + .data = &r8a7796_cpg_mssr_info, + }, +#endif { /* sentinel */ } }; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 0d1e3e811e79..ee7edfaf1408 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -131,4 +131,5 @@ struct cpg_mssr_info { }; extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; +extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; #endif diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index 36c974916d4f..5738635c5274 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -238,7 +238,6 @@ enum clk_id { tegra_clk_sor0, tegra_clk_sor0_lvds, tegra_clk_sor1, - tegra_clk_sor1_brick, tegra_clk_sor1_src, tegra_clk_spdif, tegra_clk_spdif_2x, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 29d04c663abf..af85c8aeaf5a 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -594,15 +594,17 @@ static u32 mux_pllp_plld_plld2_clkm_idx[] = { [0] = 0, [1] = 2, [2] = 5, [3] = 6 }; -static const char *mux_plldp_sor1_src[] = { - "pll_dp", "clk_sor1_src" -}; -#define mux_plldp_sor1_src_idx NULL - -static const char *mux_clkm_sor1_brick_sor1_src[] = { - "clk_m", "sor1_brick", "sor1_src", "sor1_brick" -}; -#define mux_clkm_sor1_brick_sor1_src_idx NULL +static const char *mux_sor_safe_sor1_brick_sor1_src[] = { + /* + * Bit 0 of the mux selects sor1_brick, irrespective of bit 1, so the + * sor1_brick parent appears twice in the list below. This is merely + * to support clk_get_parent() if firmware happened to set these bits + * to 0b11. While not an invalid setting, code should always set the + * bits to 0b01 to select sor1_brick. + */ + "sor_safe", "sor1_brick", "sor1_src", "sor1_brick" +}; +#define mux_sor_safe_sor1_brick_sor1_src_idx NULL static const char *mux_pllp_pllre_clkm[] = { "pll_p", "pll_re_out1", "clk_m" @@ -778,8 +780,7 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg), MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape), MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock), - NODIV("sor1_brick", mux_plldp_sor1_src, CLK_SOURCE_SOR1, 14, MASK(1), 183, 0, tegra_clk_sor1_brick, &sor1_lock), - NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock), + NODIV("sor1", mux_sor_safe_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 14, MASK(2), 183, 0, tegra_clk_sor1, &sor1_lock), MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy), MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi), I2C("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, tegra_clk_vi_i2c), diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 456cf586d2c2..aab32af77aa2 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -1366,9 +1366,9 @@ static u32 pll_expo_p_to_pdiv(u32 p, u32 *pdiv) static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { /* 1 GHz */ - { 12000000, 1000000000, 166, 1, 1, 0 }, /* actual: 996.0 MHz */ - { 13000000, 1000000000, 153, 1, 1, 0 }, /* actual: 994.0 MHz */ - { 38400000, 1000000000, 156, 3, 1, 0 }, /* actual: 998.4 MHz */ + { 12000000, 1000000000, 166, 1, 2, 0 }, /* actual: 996.0 MHz */ + { 13000000, 1000000000, 153, 1, 2, 0 }, /* actual: 994.0 MHz */ + { 38400000, 1000000000, 156, 3, 2, 0 }, /* actual: 998.4 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1417,9 +1417,9 @@ static struct div_nmp pllc_nmp = { }; static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { - { 12000000, 510000000, 85, 1, 1, 0 }, - { 13000000, 510000000, 78, 1, 1, 0 }, /* actual: 507.0 MHz */ - { 38400000, 510000000, 79, 3, 1, 0 }, /* actual: 505.6 MHz */ + { 12000000, 510000000, 85, 1, 2, 0 }, + { 13000000, 510000000, 78, 1, 2, 0 }, /* actual: 507.0 MHz */ + { 38400000, 510000000, 79, 3, 2, 0 }, /* actual: 505.6 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1532,9 +1532,9 @@ static struct div_nmp pllss_nmp = { }; static struct tegra_clk_pll_freq_table pll_c4_vco_freq_table[] = { - { 12000000, 600000000, 50, 1, 0, 0 }, - { 13000000, 600000000, 46, 1, 0, 0 }, /* actual: 598.0 MHz */ - { 38400000, 600000000, 62, 4, 0, 0 }, /* actual: 595.2 MHz */ + { 12000000, 600000000, 50, 1, 1, 0 }, + { 13000000, 600000000, 46, 1, 1, 0 }, /* actual: 598.0 MHz */ + { 38400000, 600000000, 62, 4, 1, 0 }, /* actual: 595.2 MHz */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1583,19 +1583,19 @@ static struct tegra_clk_pll_params pll_c4_vco_params = { }; static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { - { 12000000, 800000000, 66, 1, 0, 0 }, /* actual: 792.0 MHz */ - { 13000000, 800000000, 61, 1, 0, 0 }, /* actual: 793.0 MHz */ - { 38400000, 297600000, 93, 4, 2, 0 }, - { 38400000, 400000000, 125, 4, 2, 0 }, - { 38400000, 532800000, 111, 4, 1, 0 }, - { 38400000, 665600000, 104, 3, 1, 0 }, - { 38400000, 800000000, 125, 3, 1, 0 }, - { 38400000, 931200000, 97, 4, 0, 0 }, - { 38400000, 1065600000, 111, 4, 0, 0 }, - { 38400000, 1200000000, 125, 4, 0, 0 }, - { 38400000, 1331200000, 104, 3, 0, 0 }, - { 38400000, 1459200000, 76, 2, 0, 0 }, - { 38400000, 1600000000, 125, 3, 0, 0 }, + { 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */ + { 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */ + { 38400000, 297600000, 93, 4, 3, 0 }, + { 38400000, 400000000, 125, 4, 3, 0 }, + { 38400000, 532800000, 111, 4, 2, 0 }, + { 38400000, 665600000, 104, 3, 2, 0 }, + { 38400000, 800000000, 125, 3, 2, 0 }, + { 38400000, 931200000, 97, 4, 1, 0 }, + { 38400000, 1065600000, 111, 4, 1, 0 }, + { 38400000, 1200000000, 125, 4, 1, 0 }, + { 38400000, 1331200000, 104, 3, 1, 0 }, + { 38400000, 1459200000, 76, 2, 1, 0 }, + { 38400000, 1600000000, 125, 3, 1, 0 }, { 0, 0, 0, 0, 0, 0 }, }; @@ -1705,9 +1705,9 @@ static struct tegra_clk_pll_params pll_e_params = { }; static struct tegra_clk_pll_freq_table pll_re_vco_freq_table[] = { - { 12000000, 672000000, 56, 1, 0, 0 }, - { 13000000, 672000000, 51, 1, 0, 0 }, /* actual: 663.0 MHz */ - { 38400000, 672000000, 70, 4, 0, 0 }, + { 12000000, 672000000, 56, 1, 1, 0 }, + { 13000000, 672000000, 51, 1, 1, 0 }, /* actual: 663.0 MHz */ + { 38400000, 672000000, 70, 4, 1, 0 }, { 0, 0, 0, 0, 0, 0 }, }; @@ -1754,8 +1754,8 @@ static struct div_nmp pllp_nmp = { }; static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { - { 12000000, 408000000, 34, 1, 0, 0 }, - { 38400000, 408000000, 85, 8, 0, 0 }, /* cf = 4.8MHz, allowed exception */ + { 12000000, 408000000, 34, 1, 1, 0 }, + { 38400000, 408000000, 85, 8, 1, 0 }, /* cf = 4.8MHz, allowed exception */ { 0, 0, 0, 0, 0, 0 }, }; @@ -1820,14 +1820,14 @@ static struct div_nmp plla_nmp = { }; static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { - { 12000000, 282240000, 47, 1, 1, 1, 0xf148 }, /* actual: 282240234 */ - { 12000000, 368640000, 61, 1, 1, 1, 0xfe15 }, /* actual: 368640381 */ - { 12000000, 240000000, 60, 1, 2, 1, 0 }, - { 13000000, 282240000, 43, 1, 1, 1, 0xfd7d }, /* actual: 282239807 */ - { 13000000, 368640000, 56, 1, 1, 1, 0x06d8 }, /* actual: 368640137 */ - { 13000000, 240000000, 55, 1, 2, 1, 0 }, /* actual: 238.3 MHz */ - { 38400000, 282240000, 44, 3, 1, 1, 0xf333 }, /* actual: 282239844 */ - { 38400000, 368640000, 57, 3, 1, 1, 0x0333 }, /* actual: 368639844 */ + { 12000000, 282240000, 47, 1, 2, 1, 0xf148 }, /* actual: 282240234 */ + { 12000000, 368640000, 61, 1, 2, 1, 0xfe15 }, /* actual: 368640381 */ + { 12000000, 240000000, 60, 1, 3, 1, 0 }, + { 13000000, 282240000, 43, 1, 2, 1, 0xfd7d }, /* actual: 282239807 */ + { 13000000, 368640000, 56, 1, 2, 1, 0x06d8 }, /* actual: 368640137 */ + { 13000000, 240000000, 55, 1, 3, 1, 0 }, /* actual: 238.3 MHz */ + { 38400000, 282240000, 44, 3, 2, 1, 0xf333 }, /* actual: 282239844 */ + { 38400000, 368640000, 57, 3, 2, 1, 0x0333 }, /* actual: 368639844 */ { 38400000, 240000000, 75, 3, 3, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -1873,9 +1873,9 @@ static struct div_nmp plld_nmp = { }; static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { - { 12000000, 594000000, 99, 1, 1, 0, 0 }, - { 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */ - { 38400000, 594000000, 30, 1, 1, 0, 0x0e00 }, + { 12000000, 594000000, 99, 1, 2, 0, 0 }, + { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f }, /* actual: 594000183 */ + { 38400000, 594000000, 30, 1, 2, 0, 0x0e00 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -1911,9 +1911,9 @@ static struct tegra_clk_pll_params pll_d_params = { }; static struct tegra_clk_pll_freq_table tegra210_pll_d2_freq_table[] = { - { 12000000, 594000000, 99, 1, 1, 0, 0xf000 }, - { 13000000, 594000000, 91, 1, 1, 0, 0xfc4f }, /* actual: 594000183 */ - { 38400000, 594000000, 30, 1, 1, 0, 0x0e00 }, + { 12000000, 594000000, 99, 1, 2, 0, 0xf000 }, + { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f }, /* actual: 594000183 */ + { 38400000, 594000000, 30, 1, 2, 0, 0x0e00 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -1935,8 +1935,9 @@ static struct tegra_clk_pll_params pll_d2_params = { .sdm_din_mask = PLLA_SDM_DIN_MASK, .sdm_ctrl_reg = PLLD2_MISC1, .sdm_ctrl_en_mask = PLLD2_SDM_EN_MASK, - .ssc_ctrl_reg = PLLD2_MISC1, - .ssc_ctrl_en_mask = PLLD2_SSC_EN_MASK, + /* disable spread-spectrum for pll_d2 */ + .ssc_ctrl_reg = 0, + .ssc_ctrl_en_mask = 0, .round_p_to_pdiv = pll_qlin_p_to_pdiv, .pdiv_tohw = pll_qlin_pdiv_to_hw, .div_nmp = &pllss_nmp, @@ -1955,9 +1956,9 @@ static struct tegra_clk_pll_params pll_d2_params = { }; static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = { - { 12000000, 270000000, 90, 1, 3, 0, 0xf000 }, - { 13000000, 270000000, 83, 1, 3, 0, 0xf000 }, /* actual: 269.8 MHz */ - { 38400000, 270000000, 28, 1, 3, 0, 0xf400 }, + { 12000000, 270000000, 90, 1, 4, 0, 0xf000 }, + { 13000000, 270000000, 83, 1, 4, 0, 0xf000 }, /* actual: 269.8 MHz */ + { 38400000, 270000000, 28, 1, 4, 0, 0xf400 }, { 0, 0, 0, 0, 0, 0, 0 }, }; @@ -2007,9 +2008,9 @@ static struct div_nmp pllu_nmp = { }; static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { - { 12000000, 480000000, 40, 1, 0, 0 }, - { 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */ - { 38400000, 480000000, 25, 2, 0, 0 }, + { 12000000, 480000000, 40, 1, 1, 0 }, + { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */ + { 38400000, 480000000, 25, 2, 1, 0 }, { 0, 0, 0, 0, 0, 0 }, }; @@ -2154,6 +2155,8 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { [tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .present = true }, [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, + [tegra_clk_sor1] = { .dt_id = TEGRA210_CLK_SOR1, .present = true }, + [tegra_clk_sor1_src] = { .dt_id = TEGRA210_CLK_SOR1_SRC, .present = true }, [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, [tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, }, [tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true }, diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 0b2733db0e9e..ab37f4db9642 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -12,8 +12,12 @@ menuconfig RESET_CONTROLLER If unsure, say no. +if RESET_CONTROLLER + config RESET_OXNAS bool source "drivers/reset/sti/Kconfig" source "drivers/reset/hisilicon/Kconfig" + +endif diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index f173fc3847b4..03dc1bb7649e 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o +obj-$(CONFIG_ARCH_MESON) += reset-meson.o obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o obj-$(CONFIG_ARCH_STI) += sti/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 72b32bd15549..395dc9ce492e 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -93,6 +93,43 @@ void reset_controller_unregister(struct reset_controller_dev *rcdev) } EXPORT_SYMBOL_GPL(reset_controller_unregister); +static void devm_reset_controller_release(struct device *dev, void *res) +{ + reset_controller_unregister(*(struct reset_controller_dev **)res); +} + +/** + * devm_reset_controller_register - resource managed reset_controller_register() + * @dev: device that is registering this reset controller + * @rcdev: a pointer to the initialized reset controller device + * + * Managed reset_controller_register(). For reset controllers registered by + * this function, reset_controller_unregister() is automatically called on + * driver detach. See reset_controller_register() for more information. + */ +int devm_reset_controller_register(struct device *dev, + struct reset_controller_dev *rcdev) +{ + struct reset_controller_dev **rcdevp; + int ret; + + rcdevp = devres_alloc(devm_reset_controller_release, sizeof(*rcdevp), + GFP_KERNEL); + if (!rcdevp) + return -ENOMEM; + + ret = reset_controller_register(rcdev); + if (!ret) { + *rcdevp = rcdev; + devres_add(dev, rcdevp); + } else { + devres_free(rcdevp); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_reset_controller_register); + /** * reset_control_reset - reset the controlled device * @rstc: reset controller diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c index ccb940a8d9fb..16d410cd6146 100644 --- a/drivers/reset/reset-ath79.c +++ b/drivers/reset/reset-ath79.c @@ -112,7 +112,7 @@ static int ath79_reset_probe(struct platform_device *pdev) ath79_reset->rcdev.of_reset_n_cells = 1; ath79_reset->rcdev.nr_resets = 32; - err = reset_controller_register(&ath79_reset->rcdev); + err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev); if (err) return err; @@ -131,7 +131,6 @@ static int ath79_reset_remove(struct platform_device *pdev) struct ath79_reset *ath79_reset = platform_get_drvdata(pdev); unregister_restart_handler(&ath79_reset->restart_nb); - reset_controller_unregister(&ath79_reset->rcdev); return 0; } diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c new file mode 100644 index 000000000000..c32f11a30c5f --- /dev/null +++ b/drivers/reset/reset-meson.c @@ -0,0 +1,136 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright (c) 2016 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + * The full GNU General Public License is included in this distribution + * in the file called COPYING. + * + * BSD LICENSE + * + * Copyright (c) 2016 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <linux/err.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> +#include <linux/types.h> + +#define REG_COUNT 8 +#define BITS_PER_REG 32 + +struct meson_reset { + void __iomem *reg_base; + struct reset_controller_dev rcdev; +}; + +static int meson_reset_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct meson_reset *data = + container_of(rcdev, struct meson_reset, rcdev); + unsigned int bank = id / BITS_PER_REG; + unsigned int offset = id % BITS_PER_REG; + void __iomem *reg_addr = data->reg_base + (bank << 2); + + if (bank >= REG_COUNT) + return -EINVAL; + + writel(BIT(offset), reg_addr); + + return 0; +} + +static const struct reset_control_ops meson_reset_ops = { + .reset = meson_reset_reset, +}; + +static const struct of_device_id meson_reset_dt_ids[] = { + { .compatible = "amlogic,meson8b-reset", }, + { .compatible = "amlogic,meson-gxbb-reset", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, meson_reset_dt_ids); + +static int meson_reset_probe(struct platform_device *pdev) +{ + struct meson_reset *data; + struct resource *res; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->reg_base)) + return PTR_ERR(data->reg_base); + + platform_set_drvdata(pdev, data); + + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG; + data->rcdev.ops = &meson_reset_ops; + data->rcdev.of_node = pdev->dev.of_node; + + return devm_reset_controller_register(&pdev->dev, &data->rcdev); +} + +static struct platform_driver meson_reset_driver = { + .probe = meson_reset_probe, + .driver = { + .name = "meson_reset", + .of_match_table = meson_reset_dt_ids, + }, +}; + +module_platform_driver(meson_reset_driver); + +MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); +MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c index c60fb2dace3e..944980572f79 100644 --- a/drivers/reset/reset-oxnas.c +++ b/drivers/reset/reset-oxnas.c @@ -112,21 +112,11 @@ static int oxnas_reset_probe(struct platform_device *pdev) data->rcdev.ops = &oxnas_reset_ops; data->rcdev.of_node = pdev->dev.of_node; - return reset_controller_register(&data->rcdev); -} - -static int oxnas_reset_remove(struct platform_device *pdev) -{ - struct oxnas_reset *data = platform_get_drvdata(pdev); - - reset_controller_unregister(&data->rcdev); - - return 0; + return devm_reset_controller_register(&pdev->dev, &data->rcdev); } static struct platform_driver oxnas_reset_driver = { .probe = oxnas_reset_probe, - .remove = oxnas_reset_remove, .driver = { .name = "oxnas-reset", .of_match_table = oxnas_reset_dt_ids, diff --git a/drivers/reset/reset-pistachio.c b/drivers/reset/reset-pistachio.c index 72a97a15a4c8..bbc4c06dd33b 100644 --- a/drivers/reset/reset-pistachio.c +++ b/drivers/reset/reset-pistachio.c @@ -121,16 +121,7 @@ static int pistachio_reset_probe(struct platform_device *pdev) rd->rcdev.ops = &pistachio_reset_ops; rd->rcdev.of_node = np; - return reset_controller_register(&rd->rcdev); -} - -static int pistachio_reset_remove(struct platform_device *pdev) -{ - struct pistachio_reset_data *data = platform_get_drvdata(pdev); - - reset_controller_unregister(&data->rcdev); - - return 0; + return devm_reset_controller_register(dev, &rd->rcdev); } static const struct of_device_id pistachio_reset_dt_ids[] = { @@ -141,7 +132,6 @@ MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids); static struct platform_driver pistachio_reset_driver = { .probe = pistachio_reset_probe, - .remove = pistachio_reset_remove, .driver = { .name = "pistachio-reset", .of_match_table = pistachio_reset_dt_ids, diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index cd05a7032b17..12add9b0fa49 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -134,16 +134,7 @@ static int socfpga_reset_probe(struct platform_device *pdev) data->rcdev.ops = &socfpga_reset_ops; data->rcdev.of_node = pdev->dev.of_node; - return reset_controller_register(&data->rcdev); -} - -static int socfpga_reset_remove(struct platform_device *pdev) -{ - struct socfpga_reset_data *data = platform_get_drvdata(pdev); - - reset_controller_unregister(&data->rcdev); - - return 0; + return devm_reset_controller_register(dev, &data->rcdev); } static const struct of_device_id socfpga_reset_dt_ids[] = { @@ -153,7 +144,6 @@ static const struct of_device_id socfpga_reset_dt_ids[] = { static struct platform_driver socfpga_reset_driver = { .probe = socfpga_reset_probe, - .remove = socfpga_reset_remove, .driver = { .name = "socfpga-reset", .of_match_table = socfpga_reset_dt_ids, diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index 677f86555212..3080190b3f90 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -165,21 +165,11 @@ static int sunxi_reset_probe(struct platform_device *pdev) data->rcdev.ops = &sunxi_reset_ops; data->rcdev.of_node = pdev->dev.of_node; - return reset_controller_register(&data->rcdev); -} - -static int sunxi_reset_remove(struct platform_device *pdev) -{ - struct sunxi_reset_data *data = platform_get_drvdata(pdev); - - reset_controller_unregister(&data->rcdev); - - return 0; + return devm_reset_controller_register(&pdev->dev, &data->rcdev); } static struct platform_driver sunxi_reset_driver = { .probe = sunxi_reset_probe, - .remove = sunxi_reset_remove, .driver = { .name = "sunxi-reset", .of_match_table = sunxi_reset_dt_ids, diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c index a7e87bc45885..138f2f205662 100644 --- a/drivers/reset/reset-zynq.c +++ b/drivers/reset/reset-zynq.c @@ -122,16 +122,7 @@ static int zynq_reset_probe(struct platform_device *pdev) priv->rcdev.ops = &zynq_reset_ops; priv->rcdev.of_node = pdev->dev.of_node; - return reset_controller_register(&priv->rcdev); -} - -static int zynq_reset_remove(struct platform_device *pdev) -{ - struct zynq_reset_data *priv = platform_get_drvdata(pdev); - - reset_controller_unregister(&priv->rcdev); - - return 0; + return devm_reset_controller_register(&pdev->dev, &priv->rcdev); } static const struct of_device_id zynq_reset_dt_ids[] = { @@ -141,7 +132,6 @@ static const struct of_device_id zynq_reset_dt_ids[] = { static struct platform_driver zynq_reset_driver = { .probe = zynq_reset_probe, - .remove = zynq_reset_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = zynq_reset_dt_ids, diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig index f8c15a37fb35..613178553612 100644 --- a/drivers/reset/sti/Kconfig +++ b/drivers/reset/sti/Kconfig @@ -2,7 +2,6 @@ if ARCH_STI config STI_RESET_SYSCFG bool - select RESET_CONTROLLER config STIH415_RESET bool diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 151fcd3f025b..cd85cd5e6a01 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_ARCH_R8A7791) += rcar-sysc.o r8a7791-sysc.o obj-$(CONFIG_ARCH_R8A7793) += rcar-sysc.o r8a7791-sysc.o obj-$(CONFIG_ARCH_R8A7794) += rcar-sysc.o r8a7794-sysc.o obj-$(CONFIG_ARCH_R8A7795) += rcar-sysc.o r8a7795-sysc.o +obj-$(CONFIG_ARCH_R8A7796) += rcar-sysc.o r8a7796-sysc.o diff --git a/drivers/soc/renesas/r8a7796-sysc.c b/drivers/soc/renesas/r8a7796-sysc.c new file mode 100644 index 000000000000..f700c842b9e1 --- /dev/null +++ b/drivers/soc/renesas/r8a7796-sysc.c @@ -0,0 +1,48 @@ +/* + * Renesas R-Car M3-W System Controller + * + * Copyright (C) 2016 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <linux/bug.h> +#include <linux/kernel.h> + +#include <dt-bindings/power/r8a7796-sysc.h> + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a7796_areas[] __initconst = { + { "always-on", 0, 0, R8A7796_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca57-scu", 0x1c0, 0, R8A7796_PD_CA57_SCU, R8A7796_PD_ALWAYS_ON, + PD_SCU }, + { "ca57-cpu0", 0x80, 0, R8A7796_PD_CA57_CPU0, R8A7796_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca57-cpu1", 0x80, 1, R8A7796_PD_CA57_CPU1, R8A7796_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca53-scu", 0x140, 0, R8A7796_PD_CA53_SCU, R8A7796_PD_ALWAYS_ON, + PD_SCU }, + { "ca53-cpu0", 0x200, 0, R8A7796_PD_CA53_CPU0, R8A7796_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu1", 0x200, 1, R8A7796_PD_CA53_CPU1, R8A7796_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu2", 0x200, 2, R8A7796_PD_CA53_CPU2, R8A7796_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu3", 0x200, 3, R8A7796_PD_CA53_CPU3, R8A7796_PD_CA53_SCU, + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A7796_PD_CR7, R8A7796_PD_ALWAYS_ON }, + { "a3vc", 0x380, 0, R8A7796_PD_A3VC, R8A7796_PD_ALWAYS_ON }, + { "a2vc0", 0x3c0, 0, R8A7796_PD_A2VC0, R8A7796_PD_A3VC }, + { "a2vc1", 0x3c0, 1, R8A7796_PD_A2VC1, R8A7796_PD_A3VC }, + { "3dg-a", 0x100, 0, R8A7796_PD_3DG_A, R8A7796_PD_ALWAYS_ON }, + { "3dg-b", 0x100, 1, R8A7796_PD_3DG_B, R8A7796_PD_3DG_A }, + { "a3ir", 0x180, 0, R8A7796_PD_A3IR, R8A7796_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a7796_sysc_info __initconst = { + .areas = r8a7796_areas, + .num_areas = ARRAY_SIZE(r8a7796_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 79dbc770895f..fc997d4d2a4a 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -303,6 +303,9 @@ static const struct of_device_id rcar_sysc_matches[] = { #ifdef CONFIG_ARCH_R8A7795 { .compatible = "renesas,r8a7795-sysc", .data = &r8a7795_sysc_info }, #endif +#ifdef CONFIG_ARCH_R8A7796 + { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info }, +#endif { /* sentinel */ } }; diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 5e766174c2f4..4ac3d7bf7f38 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -55,4 +55,5 @@ extern const struct rcar_sysc_info r8a7790_sysc_info; extern const struct rcar_sysc_info r8a7791_sysc_info; extern const struct rcar_sysc_info r8a7794_sysc_info; extern const struct rcar_sysc_info r8a7795_sysc_info; +extern const struct rcar_sysc_info r8a7796_sysc_info; #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */ |