diff options
59 files changed, 1740 insertions, 505 deletions
diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt index 786dc39ca904..3a880528030e 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt +++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt @@ -9,6 +9,7 @@ Required Properties: - GXBB (S905) : "amlogic,meson-gxbb-aoclkc" - GXL (S905X, S905D) : "amlogic,meson-gxl-aoclkc" - GXM (S912) : "amlogic,meson-gxm-aoclkc" + - AXG (A113D, A113X) : "amlogic,meson-axg-aoclkc" followed by the common "amlogic,meson-gx-aoclkc" - #clock-cells: should be 1. diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt index 773a5226342f..db542abadb75 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt @@ -15,6 +15,7 @@ Required Properties: - compatible: Must be one of: - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M) - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E) + - "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C) - "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2) - "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W) - "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H) @@ -25,6 +26,7 @@ Required Properties: - "renesas,r8a77965-cpg-mssr" for the r8a77965 SoC (R-Car M3-N) - "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M) - "renesas,r8a77980-cpg-mssr" for the r8a77980 SoC (R-Car V3H) + - "renesas,r8a77990-cpg-mssr" for the r8a77990 SoC (R-Car E3) - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3) - reg: Base address and length of the memory resource used by the CPG/MSSR @@ -33,10 +35,12 @@ Required Properties: - clocks: References to external parent clocks, one entry for each entry in clock-names - clock-names: List of external parent clock names. Valid names are: - - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794, - r8a7795, r8a7796, r8a77965, r8a77970, r8a77980, r8a77995) + - "extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7792, + r8a7793, r8a7794, r8a7795, r8a7796, r8a77965, r8a77970, + r8a77980, r8a77990, r8a77995) - "extalr" (r8a7795, r8a7796, r8a77965, r8a77970, r8a77980) - - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794) + - "usb_extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7793, + r8a7794) - #clock-cells: Must be 2 - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index 7d3223fc7161..72b6091eb7b9 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -132,19 +132,8 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll *pll = to_clk_pll(hw); - unsigned int pllr; - u16 mul; - u8 div; - - regmap_read(pll->regmap, PLL_REG(pll->id), &pllr); - - div = PLL_DIV(pllr); - mul = PLL_MUL(pllr, pll->layout); - - if (!div || !mul) - return 0; - return (parent_rate / div) * (mul + 1); + return (parent_rate / pll->div) * (pll->mul + 1); } static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, diff --git a/drivers/clk/davinci/pll-da830.c b/drivers/clk/davinci/pll-da830.c index 929a3d3a9adb..0a0d06fb25fd 100644 --- a/drivers/clk/davinci/pll-da830.c +++ b/drivers/clk/davinci/pll-da830.c @@ -6,6 +6,7 @@ */ #include <linux/clkdev.h> +#include <linux/clk/davinci.h> #include <linux/bitops.h> #include <linux/init.h> #include <linux/types.h> @@ -36,11 +37,11 @@ SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0); SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_FIXED_DIV); SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0); -int da830_pll_init(struct device *dev, void __iomem *base) +int da830_pll_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &da830_pll_info, "ref_clk", base); + davinci_pll_clk_register(dev, &da830_pll_info, "ref_clk", base, cfgchip); clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base); clk_register_clkdev(clk, "pll0_sysclk2", "da830-psc0"); diff --git a/drivers/clk/davinci/pll-da850.c b/drivers/clk/davinci/pll-da850.c index 2a038b7908cc..0f7198191ea2 100644 --- a/drivers/clk/davinci/pll-da850.c +++ b/drivers/clk/davinci/pll-da850.c @@ -7,10 +7,14 @@ #include <linux/bitops.h> #include <linux/clk-provider.h> +#include <linux/clk/davinci.h> #include <linux/clkdev.h> +#include <linux/device.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/mfd/da8xx-cfgchip.h> +#include <linux/mfd/syscon.h> +#include <linux/of_address.h> #include <linux/of.h> #include <linux/types.h> @@ -81,11 +85,11 @@ static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info = { .ocsrc_mask = GENMASK(4, 0), }; -int da850_pll0_init(struct device *dev, void __iomem *base) +int da850_pll0_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base); + davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base, cfgchip); clk = davinci_pll_sysclk_register(dev, &pll0_sysclk1, base); clk_register_clkdev(clk, "pll0_sysclk1", "da850-psc0"); @@ -134,11 +138,22 @@ static const struct davinci_pll_sysclk_info *da850_pll0_sysclk_info[] = { NULL }; -int of_da850_pll0_init(struct device *dev, void __iomem *base) +void of_da850_pll0_init(struct device_node *node) { - return of_davinci_pll_init(dev, &da850_pll0_info, - &da850_pll0_obsclk_info, - da850_pll0_sysclk_info, 7, base); + void __iomem *base; + struct regmap *cfgchip; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s: ioremap failed\n", __func__); + return; + } + + cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); + + of_davinci_pll_init(NULL, node, &da850_pll0_info, + &da850_pll0_obsclk_info, + da850_pll0_sysclk_info, 7, base, cfgchip); } static const struct davinci_pll_clk_info da850_pll1_info = { @@ -179,11 +194,11 @@ static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info = { .ocsrc_mask = GENMASK(4, 0), }; -int da850_pll1_init(struct device *dev, void __iomem *base) +int da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base); + davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base, cfgchip); davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); @@ -204,9 +219,9 @@ static const struct davinci_pll_sysclk_info *da850_pll1_sysclk_info[] = { NULL }; -int of_da850_pll1_init(struct device *dev, void __iomem *base) +int of_da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { - return of_davinci_pll_init(dev, &da850_pll1_info, + return of_davinci_pll_init(dev, dev->of_node, &da850_pll1_info, &da850_pll1_obsclk_info, - da850_pll1_sysclk_info, 3, base); + da850_pll1_sysclk_info, 3, base, cfgchip); } diff --git a/drivers/clk/davinci/pll-dm355.c b/drivers/clk/davinci/pll-dm355.c index 5345f8286c50..505aed80be9a 100644 --- a/drivers/clk/davinci/pll-dm355.c +++ b/drivers/clk/davinci/pll-dm355.c @@ -6,6 +6,7 @@ */ #include <linux/bitops.h> +#include <linux/clk/davinci.h> #include <linux/clkdev.h> #include <linux/init.h> #include <linux/types.h> @@ -22,16 +23,16 @@ static const struct davinci_pll_clk_info dm355_pll1_info = { PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV, }; -SYSCLK(1, pll1_sysclk1, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED); -SYSCLK(2, pll1_sysclk2, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED); -SYSCLK(3, pll1_sysclk3, pll1, 5, SYSCLK_ALWAYS_ENABLED); -SYSCLK(4, pll1_sysclk4, pll1, 5, SYSCLK_ALWAYS_ENABLED); +SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED); +SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED); +SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED); +SYSCLK(4, pll1_sysclk4, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED); -int dm355_pll1_init(struct device *dev, void __iomem *base) +int dm355_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &dm355_pll1_info, "ref_clk", base); + davinci_pll_clk_register(dev, &dm355_pll1_info, "ref_clk", base, cfgchip); clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); clk_register_clkdev(clk, "pll1_sysclk1", "dm355-psc"); @@ -62,17 +63,14 @@ static const struct davinci_pll_clk_info dm355_pll2_info = { PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV, }; -SYSCLK(1, pll2_sysclk1, pll2, 5, SYSCLK_FIXED_DIV); -SYSCLK(2, pll2_sysclk2, pll2, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED); +SYSCLK(1, pll2_sysclk1, pll2_pllen, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED); -int dm355_pll2_init(struct device *dev, void __iomem *base) +int dm355_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { - davinci_pll_clk_register(dev, &dm355_pll2_info, "oscin", base); + davinci_pll_clk_register(dev, &dm355_pll2_info, "oscin", base, cfgchip); davinci_pll_sysclk_register(dev, &pll2_sysclk1, base); - davinci_pll_sysclk_register(dev, &pll2_sysclk2, base); - davinci_pll_sysclkbp_clk_register(dev, "pll2_sysclkbp", base); return 0; diff --git a/drivers/clk/davinci/pll-dm365.c b/drivers/clk/davinci/pll-dm365.c index 5f8d9f42d0f3..2d29712753a3 100644 --- a/drivers/clk/davinci/pll-dm365.c +++ b/drivers/clk/davinci/pll-dm365.c @@ -7,6 +7,7 @@ #include <linux/bitops.h> #include <linux/clkdev.h> +#include <linux/clk/davinci.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/types.h> @@ -56,11 +57,11 @@ static const struct davinci_pll_obsclk_info dm365_pll1_obsclk_info = { .ocsrc_mask = BIT(4), }; -int dm365_pll1_init(struct device *dev, void __iomem *base) +int dm365_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base); + davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base, cfgchip); clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); clk_register_clkdev(clk, "pll1_sysclk1", "dm365-psc"); @@ -119,11 +120,11 @@ static const struct davinci_pll_obsclk_info dm365_pll2_obsclk_info = { .ocsrc_mask = BIT(4), }; -int dm365_pll2_init(struct device *dev, void __iomem *base) +int dm365_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base); + davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base, cfgchip); davinci_pll_sysclk_register(dev, &pll2_sysclk1, base); diff --git a/drivers/clk/davinci/pll-dm644x.c b/drivers/clk/davinci/pll-dm644x.c index 69bf785377cf..7650fadfaac8 100644 --- a/drivers/clk/davinci/pll-dm644x.c +++ b/drivers/clk/davinci/pll-dm644x.c @@ -6,6 +6,7 @@ */ #include <linux/bitops.h> +#include <linux/clk/davinci.h> #include <linux/clkdev.h> #include <linux/init.h> #include <linux/types.h> @@ -27,11 +28,11 @@ SYSCLK(2, pll1_sysclk2, pll1_pllen, 4, SYSCLK_FIXED_DIV); SYSCLK(3, pll1_sysclk3, pll1_pllen, 4, SYSCLK_FIXED_DIV); SYSCLK(5, pll1_sysclk5, pll1_pllen, 4, SYSCLK_FIXED_DIV); -int dm644x_pll1_init(struct device *dev, void __iomem *base) +int dm644x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &dm644x_pll1_info, "ref_clk", base); + davinci_pll_clk_register(dev, &dm644x_pll1_info, "ref_clk", base, cfgchip); clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); clk_register_clkdev(clk, "pll1_sysclk1", "dm644x-psc"); @@ -66,9 +67,9 @@ static const struct davinci_pll_clk_info dm644x_pll2_info = { SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, 0); SYSCLK(2, pll2_sysclk2, pll2_pllen, 4, 0); -int dm644x_pll2_init(struct device *dev, void __iomem *base) +int dm644x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { - davinci_pll_clk_register(dev, &dm644x_pll2_info, "oscin", base); + davinci_pll_clk_register(dev, &dm644x_pll2_info, "oscin", base, cfgchip); davinci_pll_sysclk_register(dev, &pll2_sysclk1, base); diff --git a/drivers/clk/davinci/pll-dm646x.c b/drivers/clk/davinci/pll-dm646x.c index a61cc3256418..26982970df0e 100644 --- a/drivers/clk/davinci/pll-dm646x.c +++ b/drivers/clk/davinci/pll-dm646x.c @@ -6,6 +6,7 @@ */ #include <linux/clk-provider.h> +#include <linux/clk/davinci.h> #include <linux/clkdev.h> #include <linux/init.h> #include <linux/types.h> @@ -29,11 +30,11 @@ SYSCLK(6, pll1_sysclk6, pll1_pllen, 4, 0); SYSCLK(8, pll1_sysclk8, pll1_pllen, 4, 0); SYSCLK(9, pll1_sysclk9, pll1_pllen, 4, 0); -int dm646x_pll1_init(struct device *dev, void __iomem *base) +int dm646x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { struct clk *clk; - davinci_pll_clk_register(dev, &dm646x_pll1_info, "ref_clk", base); + davinci_pll_clk_register(dev, &dm646x_pll1_info, "ref_clk", base, cfgchip); clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); clk_register_clkdev(clk, "pll1_sysclk1", "dm646x-psc"); @@ -72,11 +73,11 @@ static const struct davinci_pll_clk_info dm646x_pll2_info = { .flags = 0, }; -SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, 0); +SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, SYSCLK_ALWAYS_ENABLED); -int dm646x_pll2_init(struct device *dev, void __iomem *base) +int dm646x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) { - davinci_pll_clk_register(dev, &dm646x_pll2_info, "oscin", base); + davinci_pll_clk_register(dev, &dm646x_pll2_info, "oscin", base, cfgchip); davinci_pll_sysclk_register(dev, &pll2_sysclk1, base); diff --git a/drivers/clk/davinci/pll.c b/drivers/clk/davinci/pll.c index 5a5b853dde8a..1c99e992d638 100644 --- a/drivers/clk/davinci/pll.c +++ b/drivers/clk/davinci/pll.c @@ -11,6 +11,7 @@ #include <linux/clk-provider.h> #include <linux/clk.h> +#include <linux/clk/davinci.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> @@ -223,6 +224,7 @@ static const struct clk_ops dm365_pll_ops = { /** * davinci_pll_div_register - common *DIV clock implementation + * @dev: The PLL platform device or NULL * @name: the clock name * @parent_name: the parent clock name * @reg: the *DIV register @@ -240,17 +242,21 @@ static struct clk *davinci_pll_div_register(struct device *dev, const struct clk_ops *divider_ops = &clk_divider_ops; struct clk_gate *gate; struct clk_divider *divider; + struct clk *clk; + int ret; - gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL); + gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) return ERR_PTR(-ENOMEM); gate->reg = reg; gate->bit_idx = DIV_ENABLE_SHIFT; - divider = devm_kzalloc(dev, sizeof(*divider), GFP_KERNEL); - if (!divider) - return ERR_PTR(-ENOMEM); + divider = kzalloc(sizeof(*divider), GFP_KERNEL); + if (!divider) { + ret = -ENOMEM; + goto err_free_gate; + } divider->reg = reg; divider->shift = DIV_RATIO_SHIFT; @@ -261,9 +267,22 @@ static struct clk *davinci_pll_div_register(struct device *dev, divider_ops = &clk_divider_ro_ops; } - return clk_register_composite(dev, name, parent_names, num_parents, - NULL, NULL, ÷r->hw, divider_ops, - &gate->hw, &clk_gate_ops, flags); + clk = clk_register_composite(dev, name, parent_names, num_parents, + NULL, NULL, ÷r->hw, divider_ops, + &gate->hw, &clk_gate_ops, flags); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto err_free_divider; + } + + return clk; + +err_free_divider: + kfree(divider); +err_free_gate: + kfree(gate); + + return ERR_PTR(ret); } struct davinci_pllen_clk { @@ -321,36 +340,17 @@ static int davinci_pllen_rate_change(struct notifier_block *nb, return NOTIFY_OK; } -static struct davinci_pll_platform_data *davinci_pll_get_pdata(struct device *dev) -{ - struct davinci_pll_platform_data *pdata = dev_get_platdata(dev); - - /* - * Platform data is optional, so allocate a new struct if one was not - * provided. For device tree, this will always be the case. - */ - if (!pdata) - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; - - /* for device tree, we need to fill in the struct */ - if (dev->of_node) - pdata->cfgchip = - syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); - - return pdata; -} - static struct notifier_block davinci_pllen_notifier = { .notifier_call = davinci_pllen_rate_change, }; /** * davinci_pll_clk_register - Register a PLL clock + * @dev: The PLL platform device or NULL * @info: The device-specific clock info * @parent_name: The parent clock name * @base: The PLL's memory region + * @cfgchip: CFGCHIP syscon regmap for info->unlock_reg or NULL * * This creates a series of clocks that represent the PLL. * @@ -366,9 +366,9 @@ static struct notifier_block davinci_pllen_notifier = { struct clk *davinci_pll_clk_register(struct device *dev, const struct davinci_pll_clk_info *info, const char *parent_name, - void __iomem *base) + void __iomem *base, + struct regmap *cfgchip) { - struct davinci_pll_platform_data *pdata; char prediv_name[MAX_NAME_SIZE]; char pllout_name[MAX_NAME_SIZE]; char postdiv_name[MAX_NAME_SIZE]; @@ -376,11 +376,12 @@ struct clk *davinci_pll_clk_register(struct device *dev, struct clk_init_data init; struct davinci_pll_clk *pllout; struct davinci_pllen_clk *pllen; - struct clk *pllout_clk, *clk; - - pdata = davinci_pll_get_pdata(dev); - if (!pdata) - return ERR_PTR(-ENOMEM); + struct clk *oscin_clk = NULL; + struct clk *prediv_clk = NULL; + struct clk *pllout_clk; + struct clk *postdiv_clk = NULL; + struct clk *pllen_clk; + int ret; if (info->flags & PLL_HAS_CLKMODE) { /* @@ -392,10 +393,10 @@ struct clk *davinci_pll_clk_register(struct device *dev, * a number of different things. In this driver we use it to * mean the signal after the PLLCTL[CLKMODE] switch. */ - clk = clk_register_fixed_factor(dev, OSCIN_CLK_NAME, - parent_name, 0, 1, 1); - if (IS_ERR(clk)) - return clk; + oscin_clk = clk_register_fixed_factor(dev, OSCIN_CLK_NAME, + parent_name, 0, 1, 1); + if (IS_ERR(oscin_clk)) + return oscin_clk; parent_name = OSCIN_CLK_NAME; } @@ -411,30 +412,34 @@ struct clk *davinci_pll_clk_register(struct device *dev, /* Some? DM355 chips don't correctly report the PREDIV value */ if (info->flags & PLL_PREDIV_FIXED8) - clk = clk_register_fixed_factor(dev, prediv_name, - parent_name, flags, 1, 8); + prediv_clk = clk_register_fixed_factor(dev, prediv_name, + parent_name, flags, 1, 8); else - clk = davinci_pll_div_register(dev, prediv_name, + prediv_clk = davinci_pll_div_register(dev, prediv_name, parent_name, base + PREDIV, fixed, flags); - if (IS_ERR(clk)) - return clk; + if (IS_ERR(prediv_clk)) { + ret = PTR_ERR(prediv_clk); + goto err_unregister_oscin; + } parent_name = prediv_name; } /* Unlock writing to PLL registers */ if (info->unlock_reg) { - if (IS_ERR_OR_NULL(pdata->cfgchip)) + if (IS_ERR_OR_NULL(cfgchip)) dev_warn(dev, "Failed to get CFGCHIP (%ld)\n", - PTR_ERR(pdata->cfgchip)); + PTR_ERR(cfgchip)); else - regmap_write_bits(pdata->cfgchip, info->unlock_reg, + regmap_write_bits(cfgchip, info->unlock_reg, info->unlock_mask, 0); } - pllout = devm_kzalloc(dev, sizeof(*pllout), GFP_KERNEL); - if (!pllout) - return ERR_PTR(-ENOMEM); + pllout = kzalloc(sizeof(*pllout), GFP_KERNEL); + if (!pllout) { + ret = -ENOMEM; + goto err_unregister_prediv; + } snprintf(pllout_name, MAX_NAME_SIZE, "%s_pllout", info->name); @@ -456,9 +461,11 @@ struct clk *davinci_pll_clk_register(struct device *dev, pllout->pllm_min = info->pllm_min; pllout->pllm_max = info->pllm_max; - pllout_clk = devm_clk_register(dev, &pllout->hw); - if (IS_ERR(pllout_clk)) - return pllout_clk; + pllout_clk = clk_register(dev, &pllout->hw); + if (IS_ERR(pllout_clk)) { + ret = PTR_ERR(pllout_clk); + goto err_free_pllout; + } clk_hw_set_rate_range(&pllout->hw, info->pllout_min_rate, info->pllout_max_rate); @@ -474,17 +481,21 @@ struct clk *davinci_pll_clk_register(struct device *dev, if (info->flags & PLL_POSTDIV_ALWAYS_ENABLED) flags |= CLK_IS_CRITICAL; - clk = davinci_pll_div_register(dev, postdiv_name, parent_name, - base + POSTDIV, fixed, flags); - if (IS_ERR(clk)) - return clk; + postdiv_clk = davinci_pll_div_register(dev, postdiv_name, + parent_name, base + POSTDIV, fixed, flags); + if (IS_ERR(postdiv_clk)) { + ret = PTR_ERR(postdiv_clk); + goto err_unregister_pllout; + } parent_name = postdiv_name; } - pllen = devm_kzalloc(dev, sizeof(*pllout), GFP_KERNEL); - if (!pllen) - return ERR_PTR(-ENOMEM); + pllen = kzalloc(sizeof(*pllout), GFP_KERNEL); + if (!pllen) { + ret = -ENOMEM; + goto err_unregister_postdiv; + } snprintf(pllen_name, MAX_NAME_SIZE, "%s_pllen", info->name); @@ -497,17 +508,35 @@ struct clk *davinci_pll_clk_register(struct device *dev, pllen->hw.init = &init; pllen->base = base; - clk = devm_clk_register(dev, &pllen->hw); - if (IS_ERR(clk)) - return clk; + pllen_clk = clk_register(dev, &pllen->hw); + if (IS_ERR(pllen_clk)) { + ret = PTR_ERR(pllen_clk); + goto err_free_pllen; + } - clk_notifier_register(clk, &davinci_pllen_notifier); + clk_notifier_register(pllen_clk, &davinci_pllen_notifier); return pllout_clk; + +err_free_pllen: + kfree(pllen); +err_unregister_postdiv: + clk_unregister(postdiv_clk); +err_unregister_pllout: + clk_unregister(pllout_clk); +err_free_pllout: + kfree(pllout); +err_unregister_prediv: + clk_unregister(prediv_clk); +err_unregister_oscin: + clk_unregister(oscin_clk); + + return ERR_PTR(ret); } /** * davinci_pll_auxclk_register - Register bypass clock (AUXCLK) + * @dev: The PLL platform device or NULL * @name: The clock name * @base: The PLL memory region */ @@ -521,6 +550,7 @@ struct clk *davinci_pll_auxclk_register(struct device *dev, /** * davinci_pll_sysclkbp_clk_register - Register bypass divider clock (SYSCLKBP) + * @dev: The PLL platform device or NULL * @name: The clock name * @base: The PLL memory region */ @@ -535,6 +565,7 @@ struct clk *davinci_pll_sysclkbp_clk_register(struct device *dev, /** * davinci_pll_obsclk_register - Register oscillator divider clock (OBSCLK) + * @dev: The PLL platform device or NULL * @info: The clock info * @base: The PLL memory region */ @@ -546,9 +577,11 @@ davinci_pll_obsclk_register(struct device *dev, struct clk_mux *mux; struct clk_gate *gate; struct clk_divider *divider; + struct clk *clk; u32 oscdiv; + int ret; - mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); + mux = kzalloc(sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); @@ -556,16 +589,20 @@ davinci_pll_obsclk_register(struct device *dev, mux->table = info->table; mux->mask = info->ocsrc_mask; - gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL); - if (!gate) - return ERR_PTR(-ENOMEM); + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + ret = -ENOMEM; + goto err_free_mux; + } gate->reg = base + CKEN; gate->bit_idx = CKEN_OBSCLK_SHIFT; - divider = devm_kzalloc(dev, sizeof(*divider), GFP_KERNEL); - if (!divider) - return ERR_PTR(-ENOMEM); + divider = kzalloc(sizeof(*divider), GFP_KERNEL); + if (!divider) { + ret = -ENOMEM; + goto err_free_gate; + } divider->reg = base + OSCDIV; divider->shift = DIV_RATIO_SHIFT; @@ -576,11 +613,27 @@ davinci_pll_obsclk_register(struct device *dev, oscdiv |= BIT(DIV_ENABLE_SHIFT); writel(oscdiv, base + OSCDIV); - return clk_register_composite(dev, info->name, info->parent_names, - info->num_parents, - &mux->hw, &clk_mux_ops, - ÷r->hw, &clk_divider_ops, - &gate->hw, &clk_gate_ops, 0); + clk = clk_register_composite(dev, info->name, info->parent_names, + info->num_parents, + &mux->hw, &clk_mux_ops, + ÷r->hw, &clk_divider_ops, + &gate->hw, &clk_gate_ops, 0); + + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto err_free_divider; + } + + return clk; + +err_free_divider: + kfree(divider); +err_free_gate: + kfree(gate); +err_free_mux: + kfree(mux); + + return ERR_PTR(ret); } /* The PLL SYSCLKn clocks have a mechanism for synchronizing rate changes. */ @@ -616,6 +669,7 @@ static struct notifier_block davinci_pll_sysclk_notifier = { /** * davinci_pll_sysclk_register - Register divider clocks (SYSCLKn) + * @dev: The PLL platform device or NULL * @info: The clock info * @base: The PLL memory region */ @@ -630,6 +684,7 @@ davinci_pll_sysclk_register(struct device *dev, struct clk *clk; u32 reg; u32 flags = 0; + int ret; /* PLLDIVn registers are not entirely consecutive */ if (info->id < 4) @@ -637,16 +692,18 @@ davinci_pll_sysclk_register(struct device *dev, else reg = PLLDIV4 + 4 * (info->id - 4); - gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL); + gate = kzalloc(sizeof(*gate), GFP_KERNEL); if (!gate) return ERR_PTR(-ENOMEM); gate->reg = base + reg; gate->bit_idx = DIV_ENABLE_SHIFT; - divider = devm_kzalloc(dev, sizeof(*divider), GFP_KERNEL); - if (!divider) - return ERR_PTR(-ENOMEM); + divider = kzalloc(sizeof(*divider), GFP_KERNEL); + if (!divider) { + ret = -ENOMEM; + goto err_free_gate; + } divider->reg = base + reg; divider->shift = DIV_RATIO_SHIFT; @@ -668,22 +725,31 @@ davinci_pll_sysclk_register(struct device *dev, clk = clk_register_composite(dev, info->name, &info->parent_name, 1, NULL, NULL, ÷r->hw, divider_ops, &gate->hw, &clk_gate_ops, flags); - if (IS_ERR(clk)) - return clk; + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto err_free_divider; + } clk_notifier_register(clk, &davinci_pll_sysclk_notifier); return clk; + +err_free_divider: + kfree(divider); +err_free_gate: + kfree(gate); + + return ERR_PTR(ret); } -int of_davinci_pll_init(struct device *dev, +int of_davinci_pll_init(struct device *dev, struct device_node *node, const struct davinci_pll_clk_info *info, const struct davinci_pll_obsclk_info *obsclk_info, const struct davinci_pll_sysclk_info **div_info, u8 max_sysclk_id, - void __iomem *base) + void __iomem *base, + struct regmap *cfgchip) { - struct device_node *node = dev->of_node; struct device_node *child; const char *parent_name; struct clk *clk; @@ -693,7 +759,7 @@ int of_davinci_pll_init(struct device *dev, else parent_name = OSCIN_CLK_NAME; - clk = davinci_pll_clk_register(dev, info, parent_name, base); + clk = davinci_pll_clk_register(dev, info, parent_name, base, cfgchip); if (IS_ERR(clk)) { dev_err(dev, "failed to register %s\n", info->name); return PTR_ERR(clk); @@ -711,13 +777,15 @@ int of_davinci_pll_init(struct device *dev, int n_clks = max_sysclk_id + 1; int i; - clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL); + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); if (!clk_data) return -ENOMEM; - clks = devm_kmalloc_array(dev, n_clks, sizeof(*clks), GFP_KERNEL); - if (!clks) + clks = kmalloc_array(n_clks, sizeof(*clks), GFP_KERNEL); + if (!clks) { + kfree(clk_data); return -ENOMEM; + } clk_data->clks = clks; clk_data->clk_num = n_clks; @@ -770,32 +838,73 @@ int of_davinci_pll_init(struct device *dev, return 0; } +static struct davinci_pll_platform_data *davinci_pll_get_pdata(struct device *dev) +{ + struct davinci_pll_platform_data *pdata = dev_get_platdata(dev); + + /* + * Platform data is optional, so allocate a new struct if one was not + * provided. For device tree, this will always be the case. + */ + if (!pdata) + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return NULL; + + /* for device tree, we need to fill in the struct */ + if (dev->of_node) + pdata->cfgchip = + syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); + + return pdata; +} + +/* needed in early boot for clocksource/clockevent */ +#ifdef CONFIG_ARCH_DAVINCI_DA850 +CLK_OF_DECLARE(da850_pll0, "ti,da850-pll0", of_da850_pll0_init); +#endif + static const struct of_device_id davinci_pll_of_match[] = { - { .compatible = "ti,da850-pll0", .data = of_da850_pll0_init }, +#ifdef CONFIG_ARCH_DAVINCI_DA850 { .compatible = "ti,da850-pll1", .data = of_da850_pll1_init }, +#endif { } }; static const struct platform_device_id davinci_pll_id_table[] = { +#ifdef CONFIG_ARCH_DAVINCI_DA830 { .name = "da830-pll", .driver_data = (kernel_ulong_t)da830_pll_init }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DA850 { .name = "da850-pll0", .driver_data = (kernel_ulong_t)da850_pll0_init }, { .name = "da850-pll1", .driver_data = (kernel_ulong_t)da850_pll1_init }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM355 { .name = "dm355-pll1", .driver_data = (kernel_ulong_t)dm355_pll1_init }, { .name = "dm355-pll2", .driver_data = (kernel_ulong_t)dm355_pll2_init }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM365 { .name = "dm365-pll1", .driver_data = (kernel_ulong_t)dm365_pll1_init }, { .name = "dm365-pll2", .driver_data = (kernel_ulong_t)dm365_pll2_init }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM644x { .name = "dm644x-pll1", .driver_data = (kernel_ulong_t)dm644x_pll1_init }, { .name = "dm644x-pll2", .driver_data = (kernel_ulong_t)dm644x_pll2_init }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM646x { .name = "dm646x-pll1", .driver_data = (kernel_ulong_t)dm646x_pll1_init }, { .name = "dm646x-pll2", .driver_data = (kernel_ulong_t)dm646x_pll2_init }, +#endif { } }; -typedef int (*davinci_pll_init)(struct device *dev, void __iomem *base); +typedef int (*davinci_pll_init)(struct device *dev, void __iomem *base, + struct regmap *cfgchip); static int davinci_pll_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct davinci_pll_platform_data *pdata; const struct of_device_id *of_id; davinci_pll_init pll_init = NULL; struct resource *res; @@ -812,12 +921,18 @@ static int davinci_pll_probe(struct platform_device *pdev) return -EINVAL; } + pdata = davinci_pll_get_pdata(dev); + if (!pdata) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(dev, res); if (IS_ERR(base)) return PTR_ERR(base); - return pll_init(dev, base); + return pll_init(dev, base, pdata->cfgchip); } static struct platform_driver davinci_pll_driver = { diff --git a/drivers/clk/davinci/pll.h b/drivers/clk/davinci/pll.h index b1b6fb23f972..7cc354dd29e2 100644 --- a/drivers/clk/davinci/pll.h +++ b/drivers/clk/davinci/pll.h @@ -11,6 +11,7 @@ #include <linux/bitops.h> #include <linux/clk-provider.h> #include <linux/of.h> +#include <linux/regmap.h> #include <linux/types.h> #define PLL_HAS_CLKMODE BIT(0) /* PLL has PLLCTL[CLKMODE] */ @@ -94,7 +95,8 @@ struct davinci_pll_obsclk_info { struct clk *davinci_pll_clk_register(struct device *dev, const struct davinci_pll_clk_info *info, const char *parent_name, - void __iomem *base); + void __iomem *base, + struct regmap *cfgchip); struct clk *davinci_pll_auxclk_register(struct device *dev, const char *name, void __iomem *base); @@ -110,32 +112,29 @@ davinci_pll_sysclk_register(struct device *dev, const struct davinci_pll_sysclk_info *info, void __iomem *base); -int of_davinci_pll_init(struct device *dev, +int of_davinci_pll_init(struct device *dev, struct device_node *node, const struct davinci_pll_clk_info *info, const struct davinci_pll_obsclk_info *obsclk_info, const struct davinci_pll_sysclk_info **div_info, u8 max_sysclk_id, - void __iomem *base); + void __iomem *base, + struct regmap *cfgchip); /* Platform-specific callbacks */ -int da830_pll_init(struct device *dev, void __iomem *base); - -int da850_pll0_init(struct device *dev, void __iomem *base); -int da850_pll1_init(struct device *dev, void __iomem *base); -int of_da850_pll0_init(struct device *dev, void __iomem *base); -int of_da850_pll1_init(struct device *dev, void __iomem *base); - -int dm355_pll1_init(struct device *dev, void __iomem *base); -int dm355_pll2_init(struct device *dev, void __iomem *base); - -int dm365_pll1_init(struct device *dev, void __iomem *base); -int dm365_pll2_init(struct device *dev, void __iomem *base); - -int dm644x_pll1_init(struct device *dev, void __iomem *base); -int dm644x_pll2_init(struct device *dev, void __iomem *base); - -int dm646x_pll1_init(struct device *dev, void __iomem *base); -int dm646x_pll2_init(struct device *dev, void __iomem *base); +#ifdef CONFIG_ARCH_DAVINCI_DA850 +int da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +void of_da850_pll0_init(struct device_node *node); +int of_da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM355 +int dm355_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM644x +int dm644x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM646x +int dm646x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +#endif #endif /* __CLK_DAVINCI_PLL_H___ */ diff --git a/drivers/clk/davinci/psc-da830.c b/drivers/clk/davinci/psc-da830.c index f61abf5632ff..081b039fcb02 100644 --- a/drivers/clk/davinci/psc-da830.c +++ b/drivers/clk/davinci/psc-da830.c @@ -55,7 +55,8 @@ const struct davinci_psc_init_data da830_psc0_init_data = { .psc_init = &da830_psc0_init, }; -LPSC_CLKDEV2(usb0_clkdev, NULL, "musb-da8xx", +LPSC_CLKDEV3(usb0_clkdev, "fck", "da830-usb-phy-clks", + NULL, "musb-da8xx", NULL, "cppi41-dmaengine"); LPSC_CLKDEV1(usb1_clkdev, NULL, "ohci-da8xx"); /* REVISIT: gpio-davinci.c should be modified to drop con_id */ diff --git a/drivers/clk/davinci/psc-dm355.c b/drivers/clk/davinci/psc-dm355.c index 6995ecea2677..ddd250107c4e 100644 --- a/drivers/clk/davinci/psc-dm355.c +++ b/drivers/clk/davinci/psc-dm355.c @@ -6,6 +6,7 @@ */ #include <linux/clk-provider.h> +#include <linux/clk/davinci.h> #include <linux/clk.h> #include <linux/clkdev.h> #include <linux/init.h> @@ -41,14 +42,14 @@ static const struct davinci_lpsc_clk_info dm355_psc_info[] = { LPSC(5, 0, timer3, pll1_auxclk, NULL, 0), LPSC(6, 0, spi1, pll1_sysclk2, spi1_clkdev, 0), LPSC(7, 0, mmcsd1, pll1_sysclk2, mmcsd1_clkdev, 0), - LPSC(8, 0, asp1, pll1_sysclk2, NULL, 0), + LPSC(8, 0, asp1, pll1_sysclk2, mcbsp1_clkdev, 0), LPSC(9, 0, usb, pll1_sysclk2, usb_clkdev, 0), LPSC(10, 0, pwm3, pll1_auxclk, NULL, 0), LPSC(11, 0, spi2, pll1_sysclk2, spi2_clkdev, 0), LPSC(12, 0, rto, pll1_auxclk, NULL, 0), LPSC(14, 0, aemif, pll1_sysclk2, aemif_clkdev, 0), LPSC(15, 0, mmcsd0, pll1_sysclk2, mmcsd0_clkdev, 0), - LPSC(17, 0, asp0, pll1_sysclk2, NULL, 0), + LPSC(17, 0, asp0, pll1_sysclk2, mcbsp0_clkdev, 0), LPSC(18, 0, i2c, pll1_auxclk, i2c_clkdev, 0), LPSC(19, 0, uart0, pll1_auxclk, uart0_clkdev, 0), LPSC(20, 0, uart1, pll1_auxclk, uart1_clkdev, 0), @@ -68,7 +69,7 @@ static const struct davinci_lpsc_clk_info dm355_psc_info[] = { { } }; -static int dm355_psc_init(struct device *dev, void __iomem *base) +int dm355_psc_init(struct device *dev, void __iomem *base) { return davinci_psc_register_clocks(dev, dm355_psc_info, 42, base); } diff --git a/drivers/clk/davinci/psc-dm365.c b/drivers/clk/davinci/psc-dm365.c index 3ad915f37376..8c73086cc676 100644 --- a/drivers/clk/davinci/psc-dm365.c +++ b/drivers/clk/davinci/psc-dm365.c @@ -6,6 +6,7 @@ */ #include <linux/clk-provider.h> +#include <linux/clk/davinci.h> #include <linux/clk.h> #include <linux/clkdev.h> #include <linux/init.h> @@ -65,15 +66,28 @@ static const struct davinci_lpsc_clk_info dm365_psc_info[] = { LPSC(31, 0, arm, pll2_sysclk2, NULL, LPSC_ALWAYS_ENABLED), LPSC(38, 0, spi3, pll1_sysclk4, spi3_clkdev, 0), LPSC(39, 0, spi4, pll1_auxclk, spi4_clkdev, 0), - LPSC(40, 0, emac, pll2_sysclk4, emac_clkdev, 0), - LPSC(44, 1, voice_codec, pll1_sysclk3, voice_codec_clkdev, 0), - LPSC(46, 1, vpss_dac, pll1_sysclk3, vpss_dac_clkdev, 0), + LPSC(40, 0, emac, pll1_sysclk4, emac_clkdev, 0), + /* + * The TRM (ARM Subsystem User's Guide) shows two clocks input into + * voice codec module (PLL2 SYSCLK4 with a DIV2 and PLL1 SYSCLK4). Its + * not fully clear from documentation which clock should be considered + * as parent for PSC. The clock chosen here is to maintain + * compatibility with existing code in arch/arm/mach-davinci/dm365.c + */ + LPSC(44, 0, voice_codec, pll2_sysclk4, voice_codec_clkdev, 0), + /* + * Its not fully clear from TRM (ARM Subsystem User's Guide) as to what + * the parent of VPSS DAC LPSC should actually be. PLL1 SYSCLK3 feeds + * into HDVICP and MJCP. The clock chosen here is to remain compatible + * with code existing in arch/arm/mach-davinci/dm365.c + */ + LPSC(46, 0, vpss_dac, pll1_sysclk3, vpss_dac_clkdev, 0), LPSC(47, 0, vpss_master, pll1_sysclk5, vpss_master_clkdev, 0), LPSC(50, 0, mjcp, pll1_sysclk3, NULL, 0), { } }; -static int dm365_psc_init(struct device *dev, void __iomem *base) +int dm365_psc_init(struct device *dev, void __iomem *base) { return davinci_psc_register_clocks(dev, dm365_psc_info, 52, base); } diff --git a/drivers/clk/davinci/psc-dm644x.c b/drivers/clk/davinci/psc-dm644x.c index c22367baa46f..fc0230e3a3d6 100644 --- a/drivers/clk/davinci/psc-dm644x.c +++ b/drivers/clk/davinci/psc-dm644x.c @@ -6,6 +6,7 @@ */ #include <linux/clk-provider.h> +#include <linux/clk/davinci.h> #include <linux/clk.h> #include <linux/clkdev.h> #include <linux/init.h> @@ -63,7 +64,7 @@ static const struct davinci_lpsc_clk_info dm644x_psc_info[] = { { } }; -static int dm644x_psc_init(struct device *dev, void __iomem *base) +int dm644x_psc_init(struct device *dev, void __iomem *base) { return davinci_psc_register_clocks(dev, dm644x_psc_info, 41, base); } diff --git a/drivers/clk/davinci/psc-dm646x.c b/drivers/clk/davinci/psc-dm646x.c index 468ef86ea40b..c3f82ed70a80 100644 --- a/drivers/clk/davinci/psc-dm646x.c +++ b/drivers/clk/davinci/psc-dm646x.c @@ -6,6 +6,7 @@ */ #include <linux/clk-provider.h> +#include <linux/clk/davinci.h> #include <linux/clk.h> #include <linux/clkdev.h> #include <linux/init.h> @@ -58,7 +59,7 @@ static const struct davinci_lpsc_clk_info dm646x_psc_info[] = { { } }; -static int dm646x_psc_init(struct device *dev, void __iomem *base) +int dm646x_psc_init(struct device *dev, void __iomem *base) { return davinci_psc_register_clocks(dev, dm646x_psc_info, 46, base); } diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c index ce170e600f09..fffbed5e263b 100644 --- a/drivers/clk/davinci/psc.c +++ b/drivers/clk/davinci/psc.c @@ -15,6 +15,7 @@ #include <linux/clk-provider.h> #include <linux/clk.h> +#include <linux/clk/davinci.h> #include <linux/clkdev.h> #include <linux/err.h> #include <linux/of_address.h> @@ -63,7 +64,7 @@ struct davinci_psc_data { /** * struct davinci_lpsc_clk - LPSC clock structure - * @dev: the device that provides this LPSC + * @dev: the device that provides this LPSC or NULL * @hw: clk_hw for the LPSC * @pm_domain: power domain for the LPSC * @genpd_clk: clock reference owned by @pm_domain @@ -221,6 +222,7 @@ static void davinci_psc_genpd_detach_dev(struct generic_pm_domain *pm_domain, /** * davinci_lpsc_clk_register - register LPSC clock + * @dev: the clocks's device or NULL * @name: name of this clock * @parent_name: name of clock's parent * @regmap: PSC MMIO region @@ -238,7 +240,7 @@ davinci_lpsc_clk_register(struct device *dev, const char *name, int ret; bool is_on; - lpsc = devm_kzalloc(dev, sizeof(*lpsc), GFP_KERNEL); + lpsc = kzalloc(sizeof(*lpsc), GFP_KERNEL); if (!lpsc) return ERR_PTR(-ENOMEM); @@ -261,9 +263,15 @@ davinci_lpsc_clk_register(struct device *dev, const char *name, lpsc->pd = pd; lpsc->flags = flags; - ret = devm_clk_hw_register(dev, &lpsc->hw); - if (ret < 0) + ret = clk_hw_register(dev, &lpsc->hw); + if (ret < 0) { + kfree(lpsc); return ERR_PTR(ret); + } + + /* for now, genpd is only registered when using device-tree */ + if (!dev || !dev->of_node) + return lpsc; /* genpd attach needs a way to look up this clock */ ret = clk_hw_register_clkdev(&lpsc->hw, name, best_dev_name(dev)); @@ -378,13 +386,15 @@ __davinci_psc_register_clocks(struct device *dev, struct regmap *regmap; int i, ret; - psc = devm_kzalloc(dev, sizeof(*psc), GFP_KERNEL); + psc = kzalloc(sizeof(*psc), GFP_KERNEL); if (!psc) return ERR_PTR(-ENOMEM); - clks = devm_kmalloc_array(dev, num_clks, sizeof(*clks), GFP_KERNEL); - if (!clks) - return ERR_PTR(-ENOMEM); + clks = kmalloc_array(num_clks, sizeof(*clks), GFP_KERNEL); + if (!clks) { + ret = -ENOMEM; + goto err_free_psc; + } psc->clk_data.clks = clks; psc->clk_data.clk_num = num_clks; @@ -396,16 +406,20 @@ __davinci_psc_register_clocks(struct device *dev, for (i = 0; i < num_clks; i++) clks[i] = ERR_PTR(-ENOENT); - pm_domains = devm_kcalloc(dev, num_clks, sizeof(*pm_domains), GFP_KERNEL); - if (!pm_domains) - return ERR_PTR(-ENOMEM); + pm_domains = kcalloc(num_clks, sizeof(*pm_domains), GFP_KERNEL); + if (!pm_domains) { + ret = -ENOMEM; + goto err_free_clks; + } psc->pm_data.domains = pm_domains; psc->pm_data.num_domains = num_clks; - regmap = devm_regmap_init_mmio(dev, base, &davinci_psc_regmap_config); - if (IS_ERR(regmap)) - return ERR_CAST(regmap); + regmap = regmap_init_mmio(dev, base, &davinci_psc_regmap_config); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + goto err_free_pm_domains; + } for (; info->name; info++) { struct davinci_lpsc_clk *lpsc; @@ -423,6 +437,13 @@ __davinci_psc_register_clocks(struct device *dev, pm_domains[info->md] = &lpsc->pm_domain; } + /* + * for now, a reset controller is only registered when there is a device + * to associate it with. + */ + if (!dev) + return psc; + psc->rcdev.ops = &davinci_psc_reset_ops; psc->rcdev.owner = THIS_MODULE; psc->rcdev.dev = dev; @@ -436,6 +457,15 @@ __davinci_psc_register_clocks(struct device *dev, dev_warn(dev, "Failed to register reset controller (%d)\n", ret); return psc; + +err_free_pm_domains: + kfree(pm_domains); +err_free_clks: + kfree(clks); +err_free_psc: + kfree(psc); + + return ERR_PTR(ret); } int davinci_psc_register_clocks(struct device *dev, @@ -483,20 +513,34 @@ int of_davinci_psc_clk_init(struct device *dev, } static const struct of_device_id davinci_psc_of_match[] = { +#ifdef CONFIG_ARCH_DAVINCI_DA850 { .compatible = "ti,da850-psc0", .data = &of_da850_psc0_init_data }, { .compatible = "ti,da850-psc1", .data = &of_da850_psc1_init_data }, +#endif { } }; static const struct platform_device_id davinci_psc_id_table[] = { +#ifdef CONFIG_ARCH_DAVINCI_DA830 { .name = "da830-psc0", .driver_data = (kernel_ulong_t)&da830_psc0_init_data }, { .name = "da830-psc1", .driver_data = (kernel_ulong_t)&da830_psc1_init_data }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DA850 { .name = "da850-psc0", .driver_data = (kernel_ulong_t)&da850_psc0_init_data }, { .name = "da850-psc1", .driver_data = (kernel_ulong_t)&da850_psc1_init_data }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM355 { .name = "dm355-psc", .driver_data = (kernel_ulong_t)&dm355_psc_init_data }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM365 { .name = "dm365-psc", .driver_data = (kernel_ulong_t)&dm365_psc_init_data }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM644x { .name = "dm644x-psc", .driver_data = (kernel_ulong_t)&dm644x_psc_init_data }, +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM646x { .name = "dm646x-psc", .driver_data = (kernel_ulong_t)&dm646x_psc_init_data }, +#endif { } }; diff --git a/drivers/clk/davinci/psc.h b/drivers/clk/davinci/psc.h index c2a7df6413fe..6a42529d31a9 100644 --- a/drivers/clk/davinci/psc.h +++ b/drivers/clk/davinci/psc.h @@ -94,15 +94,27 @@ struct davinci_psc_init_data { int (*psc_init)(struct device *dev, void __iomem *base); }; +#ifdef CONFIG_ARCH_DAVINCI_DA830 extern const struct davinci_psc_init_data da830_psc0_init_data; extern const struct davinci_psc_init_data da830_psc1_init_data; +#endif +#ifdef CONFIG_ARCH_DAVINCI_DA850 extern const struct davinci_psc_init_data da850_psc0_init_data; extern const struct davinci_psc_init_data da850_psc1_init_data; extern const struct davinci_psc_init_data of_da850_psc0_init_data; extern const struct davinci_psc_init_data of_da850_psc1_init_data; +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM355 extern const struct davinci_psc_init_data dm355_psc_init_data; +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM356 extern const struct davinci_psc_init_data dm365_psc_init_data; +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM644x extern const struct davinci_psc_init_data dm644x_psc_init_data; +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM646x extern const struct davinci_psc_init_data dm646x_psc_init_data; +#endif #endif /* __CLK_DAVINCI_PSC_H__ */ diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index d5cbec522aec..815659eebea3 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -3,6 +3,12 @@ config COMMON_CLK_AMLOGIC depends on OF depends on ARCH_MESON || COMPILE_TEST +config COMMON_CLK_MESON_AO + bool + depends on OF + depends on ARCH_MESON || COMPILE_TEST + select COMMON_CLK_REGMAP_MESON + config COMMON_CLK_REGMAP_MESON bool select REGMAP @@ -21,6 +27,7 @@ config COMMON_CLK_GXBB bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER + select COMMON_CLK_MESON_AO select COMMON_CLK_REGMAP_MESON select MFD_SYSCON help @@ -31,6 +38,7 @@ config COMMON_CLK_AXG bool depends on COMMON_CLK_AMLOGIC select RESET_CONTROLLER + select COMMON_CLK_MESON_AO select COMMON_CLK_REGMAP_MESON select MFD_SYSCON help diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index ffee82e60b7a..d0d13aeb369a 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -3,7 +3,8 @@ # obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-audio-divider.o +obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o -obj-$(CONFIG_COMMON_CLK_AXG) += axg.o +obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c new file mode 100644 index 000000000000..29e088542387 --- /dev/null +++ b/drivers/clk/meson/axg-aoclk.c @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Amlogic Meson-AXG Clock Controller Driver + * + * Copyright (c) 2016 Baylibre SAS. + * Author: Michael Turquette <mturquette@baylibre.com> + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai <qiufang.dai@amlogic.com> + */ +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/mfd/syscon.h> +#include "clk-regmap.h" +#include "meson-aoclk.h" +#include "axg-aoclk.h" + +#define AXG_AO_GATE(_name, _bit) \ +static struct clk_regmap axg_aoclk_##_name = { \ + .data = &(struct clk_regmap_gate_data) { \ + .offset = (AO_RTI_GEN_CNTL_REG0), \ + .bit_idx = (_bit), \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = "axg_ao_" #_name, \ + .ops = &clk_regmap_gate_ops, \ + .parent_names = (const char *[]){ "clk81" }, \ + .num_parents = 1, \ + .flags = CLK_IGNORE_UNUSED, \ + }, \ +} + +AXG_AO_GATE(remote, 0); +AXG_AO_GATE(i2c_master, 1); +AXG_AO_GATE(i2c_slave, 2); +AXG_AO_GATE(uart1, 3); +AXG_AO_GATE(uart2, 5); +AXG_AO_GATE(ir_blaster, 6); +AXG_AO_GATE(saradc, 7); + +static struct clk_regmap axg_aoclk_clk81 = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_RTI_PWR_CNTL_REG0, + .mask = 0x1, + .shift = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "axg_ao_clk81", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "clk81", "ao_alt_xtal"}, + .num_parents = 2, + }, +}; + +static struct clk_regmap axg_aoclk_saradc_mux = { + .data = &(struct clk_regmap_mux_data) { + .offset = AO_SAR_CLK, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "axg_ao_saradc_mux", + .ops = &clk_regmap_mux_ops, + .parent_names = (const char *[]){ "xtal", "axg_ao_clk81" }, + .num_parents = 2, + }, +}; + +static struct clk_regmap axg_aoclk_saradc_div = { + .data = &(struct clk_regmap_div_data) { + .offset = AO_SAR_CLK, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "axg_ao_saradc_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "axg_ao_saradc_mux" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap axg_aoclk_saradc_gate = { + .data = &(struct clk_regmap_gate_data) { + .offset = AO_SAR_CLK, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "axg_ao_saradc_gate", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "axg_ao_saradc_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const unsigned int axg_aoclk_reset[] = { + [RESET_AO_REMOTE] = 16, + [RESET_AO_I2C_MASTER] = 18, + [RESET_AO_I2C_SLAVE] = 19, + [RESET_AO_UART1] = 17, + [RESET_AO_UART2] = 22, + [RESET_AO_IR_BLASTER] = 23, +}; + +static struct clk_regmap *axg_aoclk_regmap[] = { + [CLKID_AO_REMOTE] = &axg_aoclk_remote, + [CLKID_AO_I2C_MASTER] = &axg_aoclk_i2c_master, + [CLKID_AO_I2C_SLAVE] = &axg_aoclk_i2c_slave, + [CLKID_AO_UART1] = &axg_aoclk_uart1, + [CLKID_AO_UART2] = &axg_aoclk_uart2, + [CLKID_AO_IR_BLASTER] = &axg_aoclk_ir_blaster, + [CLKID_AO_SAR_ADC] = &axg_aoclk_saradc, + [CLKID_AO_CLK81] = &axg_aoclk_clk81, + [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux, + [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div, + [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate, +}; + +static const struct clk_hw_onecell_data axg_aoclk_onecell_data = { + .hws = { + [CLKID_AO_REMOTE] = &axg_aoclk_remote.hw, + [CLKID_AO_I2C_MASTER] = &axg_aoclk_i2c_master.hw, + [CLKID_AO_I2C_SLAVE] = &axg_aoclk_i2c_slave.hw, + [CLKID_AO_UART1] = &axg_aoclk_uart1.hw, + [CLKID_AO_UART2] = &axg_aoclk_uart2.hw, + [CLKID_AO_IR_BLASTER] = &axg_aoclk_ir_blaster.hw, + [CLKID_AO_SAR_ADC] = &axg_aoclk_saradc.hw, + [CLKID_AO_CLK81] = &axg_aoclk_clk81.hw, + [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux.hw, + [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div.hw, + [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate.hw, + }, + .num = NR_CLKS, +}; + +static const struct meson_aoclk_data axg_aoclkc_data = { + .reset_reg = AO_RTI_GEN_CNTL_REG0, + .num_reset = ARRAY_SIZE(axg_aoclk_reset), + .reset = axg_aoclk_reset, + .num_clks = ARRAY_SIZE(axg_aoclk_regmap), + .clks = axg_aoclk_regmap, + .hw_data = &axg_aoclk_onecell_data, +}; + +static const struct of_device_id axg_aoclkc_match_table[] = { + { + .compatible = "amlogic,meson-axg-aoclkc", + .data = &axg_aoclkc_data, + }, + { } +}; + +static struct platform_driver axg_aoclkc_driver = { + .probe = meson_aoclkc_probe, + .driver = { + .name = "axg-aoclkc", + .of_match_table = axg_aoclkc_match_table, + }, +}; + +builtin_platform_driver(axg_aoclkc_driver); diff --git a/drivers/clk/meson/axg-aoclk.h b/drivers/clk/meson/axg-aoclk.h new file mode 100644 index 000000000000..91384d8dd844 --- /dev/null +++ b/drivers/clk/meson/axg-aoclk.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2017 BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai <qiufang.dai@amlogic.com> + */ + +#ifndef __AXG_AOCLKC_H +#define __AXG_AOCLKC_H + +#define NR_CLKS 11 +/* AO Configuration Clock registers offsets + * Register offsets from the data sheet must be multiplied by 4. + */ +#define AO_RTI_PWR_CNTL_REG1 0x0C +#define AO_RTI_PWR_CNTL_REG0 0x10 +#define AO_RTI_GEN_CNTL_REG0 0x40 +#define AO_OSCIN_CNTL 0x58 +#define AO_CRT_CLK_CNTL1 0x68 +#define AO_SAR_CLK 0x90 +#define AO_RTC_ALT_CLK_CNTL0 0x94 +#define AO_RTC_ALT_CLK_CNTL1 0x98 + +#include <dt-bindings/clock/axg-aoclkc.h> +#include <dt-bindings/reset/axg-aoclkc.h> + +#endif /* __AXG_AOCLKC_H */ diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 5f5d468c1efe..bd4dbc696b88 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -461,6 +461,7 @@ static struct clk_regmap axg_mpll0_div = { .width = 1, }, .lock = &meson_clk_lock, + .flags = CLK_MESON_MPLL_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "mpll0_div", @@ -507,6 +508,7 @@ static struct clk_regmap axg_mpll1_div = { .width = 1, }, .lock = &meson_clk_lock, + .flags = CLK_MESON_MPLL_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "mpll1_div", @@ -553,6 +555,7 @@ static struct clk_regmap axg_mpll2_div = { .width = 1, }, .lock = &meson_clk_lock, + .flags = CLK_MESON_MPLL_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "mpll2_div", @@ -599,6 +602,7 @@ static struct clk_regmap axg_mpll3_div = { .width = 1, }, .lock = &meson_clk_lock, + .flags = CLK_MESON_MPLL_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "mpll3_div", diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c index f7ab5b1db342..58f546e04807 100644 --- a/drivers/clk/meson/clk-audio-divider.c +++ b/drivers/clk/meson/clk-audio-divider.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2017 AmLogic, Inc. * Author: Jerome Brunet <jbrunet@baylibre.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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/>. */ /* diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 0df1227b65b3..650f75cc15a9 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -1,57 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* - * 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 AmLogic, Inc. - * Author: Michael Turquette <mturquette@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, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called COPYING - * - * BSD LICENSE - * * Copyright (c) 2016 AmLogic, Inc. * Author: Michael Turquette <mturquette@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. */ /* @@ -89,10 +39,23 @@ static long rate_from_params(unsigned long parent_rate, static void params_from_rate(unsigned long requested_rate, unsigned long parent_rate, unsigned int *sdm, - unsigned int *n2) + unsigned int *n2, + u8 flags) { uint64_t div = parent_rate; - unsigned long rem = do_div(div, requested_rate); + uint64_t frac = do_div(div, requested_rate); + + frac *= SDM_DEN; + + if (flags & CLK_MESON_MPLL_ROUND_CLOSEST) + *sdm = DIV_ROUND_CLOSEST_ULL(frac, requested_rate); + else + *sdm = DIV_ROUND_UP_ULL(frac, requested_rate); + + if (*sdm == SDM_DEN) { + *sdm = 0; + div += 1; + } if (div < N2_MIN) { *n2 = N2_MIN; @@ -102,7 +65,6 @@ static void params_from_rate(unsigned long requested_rate, *sdm = SDM_DEN - 1; } else { *n2 = div; - *sdm = DIV_ROUND_UP_ULL((u64)rem * SDM_DEN, requested_rate); } } @@ -125,9 +87,11 @@ static long mpll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk); unsigned int sdm, n2; - params_from_rate(rate, *parent_rate, &sdm, &n2); + params_from_rate(rate, *parent_rate, &sdm, &n2, mpll->flags); return rate_from_params(*parent_rate, sdm, n2); } @@ -140,7 +104,7 @@ static int mpll_set_rate(struct clk_hw *hw, unsigned int sdm, n2; unsigned long flags = 0; - params_from_rate(rate, parent_rate, &sdm, &n2); + params_from_rate(rate, parent_rate, &sdm, &n2, mpll->flags); if (mpll->lock) spin_lock_irqsave(mpll->lock, flags); diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 65a7bd903551..3e04617ac47f 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -1,21 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione <carlo@endlessm.com> * * Copyright (c) 2018 Baylibre, SAS. * Author: Jerome Brunet <jbrunet@baylibre.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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/>. */ /* diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c index 3645fdb62343..bd8dbcbdc73c 100644 --- a/drivers/clk/meson/clk-regmap.c +++ b/drivers/clk/meson/clk-regmap.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2018 BayLibre, SAS. -// Author: Jerome Brunet <jbrunet@baylibre.com> +/* + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet <jbrunet@baylibre.com> + */ #include "clk-regmap.h" diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h index 627c888026d7..ed2d4348dbe2 100644 --- a/drivers/clk/meson/clk-regmap.h +++ b/drivers/clk/meson/clk-regmap.h @@ -1,6 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2018 BayLibre, SAS. -// Author: Jerome Brunet <jbrunet@baylibre.com> +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 BayLibre, SAS. + * Author: Jerome Brunet <jbrunet@baylibre.com> + */ #ifndef __CLK_REGMAP_H #define __CLK_REGMAP_H diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index 8fe73c4edca8..2fb084330ee9 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -1,18 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione <carlo@endlessm.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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/>. */ #ifndef __CLKC_H @@ -97,8 +86,11 @@ struct meson_clk_mpll_data { struct parm ssen; struct parm misc; spinlock_t *lock; + u8 flags; }; +#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0) + struct meson_clk_audio_div_data { struct parm div; u8 flags; diff --git a/drivers/clk/meson/gxbb-aoclk-32k.c b/drivers/clk/meson/gxbb-aoclk-32k.c index 491634dbc985..680467141a1d 100644 --- a/drivers/clk/meson/gxbb-aoclk-32k.c +++ b/drivers/clk/meson/gxbb-aoclk-32k.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2017 BayLibre, SAS. * Author: Neil Armstrong <narmstrong@baylibre.com> - * - * SPDX-License-Identifier: GPL-2.0+ */ #include <linux/clk-provider.h> diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c index 9ec23ae9a219..42ed61d3c3fb 100644 --- a/drivers/clk/meson/gxbb-aoclk.c +++ b/drivers/clk/meson/gxbb-aoclk.c @@ -1,90 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* - * 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/clk-provider.h> -#include <linux/of_address.h> #include <linux/platform_device.h> -#include <linux/reset-controller.h> #include <linux/mfd/syscon.h> -#include <linux/regmap.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <dt-bindings/clock/gxbb-aoclkc.h> -#include <dt-bindings/reset/gxbb-aoclkc.h> #include "clk-regmap.h" +#include "meson-aoclk.h" #include "gxbb-aoclk.h" -struct gxbb_aoclk_reset_controller { - struct reset_controller_dev reset; - unsigned int *data; - struct regmap *regmap; -}; - -static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, - unsigned long id) -{ - struct gxbb_aoclk_reset_controller *reset = - container_of(rcdev, struct gxbb_aoclk_reset_controller, reset); - - return regmap_write(reset->regmap, AO_RTI_GEN_CNTL_REG0, - BIT(reset->data[id])); -} - -static const struct reset_control_ops gxbb_aoclk_reset_ops = { - .reset = gxbb_aoclk_do_reset, -}; - #define GXBB_AO_GATE(_name, _bit) \ static struct clk_regmap _name##_ao = { \ .data = &(struct clk_regmap_gate_data) { \ @@ -96,7 +20,7 @@ static struct clk_regmap _name##_ao = { \ .ops = &clk_regmap_gate_ops, \ .parent_names = (const char *[]){ "clk81" }, \ .num_parents = 1, \ - .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ + .flags = CLK_IGNORE_UNUSED, \ }, \ } @@ -117,7 +41,7 @@ static struct aoclk_cec_32k cec_32k_ao = { }, }; -static unsigned int gxbb_aoclk_reset[] = { +static const unsigned int gxbb_aoclk_reset[] = { [RESET_AO_REMOTE] = 16, [RESET_AO_I2C_MASTER] = 18, [RESET_AO_I2C_SLAVE] = 19, @@ -135,7 +59,7 @@ static struct clk_regmap *gxbb_aoclk_gate[] = { [CLKID_AO_IR_BLASTER] = &ir_blaster_ao, }; -static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { +static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { .hws = { [CLKID_AO_REMOTE] = &remote_ao.hw, [CLKID_AO_I2C_MASTER] = &i2c_master_ao.hw, @@ -145,58 +69,55 @@ static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw, [CLKID_AO_CEC_32K] = &cec_32k_ao.hw, }, - .num = 7, + .num = NR_CLKS, }; -static int gxbb_aoclkc_probe(struct platform_device *pdev) +static int gxbb_register_cec_ao_32k(struct platform_device *pdev) { - struct gxbb_aoclk_reset_controller *rstc; struct device *dev = &pdev->dev; struct regmap *regmap; - int ret, clkid; - - rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL); - if (!rstc) - return -ENOMEM; + int ret; regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); if (IS_ERR(regmap)) { dev_err(dev, "failed to get regmap\n"); - return -ENODEV; - } - - /* Reset Controller */ - rstc->regmap = regmap; - rstc->data = gxbb_aoclk_reset; - rstc->reset.ops = &gxbb_aoclk_reset_ops; - rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset); - rstc->reset.of_node = dev->of_node; - ret = devm_reset_controller_register(dev, &rstc->reset); - - /* - * Populate regmap and register all clks - */ - for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) { - gxbb_aoclk_gate[clkid]->map = regmap; - - ret = devm_clk_hw_register(dev, - gxbb_aoclk_onecell_data.hws[clkid]); - if (ret) - return ret; + return PTR_ERR(regmap); } /* Specific clocks */ cec_32k_ao.regmap = regmap; ret = devm_clk_hw_register(dev, &cec_32k_ao.hw); + if (ret) { + dev_err(&pdev->dev, "clk cec_32k_ao register failed.\n"); + return ret; + } + + return 0; +} + +static const struct meson_aoclk_data gxbb_aoclkc_data = { + .reset_reg = AO_RTI_GEN_CNTL_REG0, + .num_reset = ARRAY_SIZE(gxbb_aoclk_reset), + .reset = gxbb_aoclk_reset, + .num_clks = ARRAY_SIZE(gxbb_aoclk_gate), + .clks = gxbb_aoclk_gate, + .hw_data = &gxbb_aoclk_onecell_data, +}; + +static int gxbb_aoclkc_probe(struct platform_device *pdev) +{ + int ret = gxbb_register_cec_ao_32k(pdev); if (ret) return ret; - return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, - &gxbb_aoclk_onecell_data); + return meson_aoclkc_probe(pdev); } static const struct of_device_id gxbb_aoclkc_match_table[] = { - { .compatible = "amlogic,meson-gx-aoclkc" }, + { + .compatible = "amlogic,meson-gx-aoclkc", + .data = &gxbb_aoclkc_data, + }, { } }; diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h index 0be78383f257..3aa638d4ed21 100644 --- a/drivers/clk/meson/gxbb-aoclk.h +++ b/drivers/clk/meson/gxbb-aoclk.h @@ -1,13 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (c) 2017 BayLibre, SAS * Author: Neil Armstrong <narmstrong@baylibre.com> - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef __GXBB_AOCLKC_H #define __GXBB_AOCLKC_H +#define NR_CLKS 7 + /* AO Configuration Clock registers offsets */ #define AO_RTI_PWR_CNTL_REG1 0x0c #define AO_RTI_PWR_CNTL_REG0 0x10 @@ -28,4 +29,7 @@ struct aoclk_cec_32k { extern const struct clk_ops meson_aoclk_cec_32k_ops; +#include <dt-bindings/clock/gxbb-aoclkc.h> +#include <dt-bindings/reset/gxbb-aoclkc.h> + #endif /* __GXBB_AOCLKC_H */ diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index b1e4d9557610..240658404367 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -1,20 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * AmLogic S905 / GXBB Clock Controller Driver - * * Copyright (c) 2016 AmLogic, Inc. * Michael Turquette <mturquette@baylibre.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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/>. */ #include <linux/clk.h> @@ -1543,6 +1530,102 @@ static struct clk_regmap gxbb_vapb = { }, }; +/* VDEC clocks */ + +static const char * const gxbb_vdec_parent_names[] = { + "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7" +}; + +static struct clk_regmap gxbb_vdec_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VDEC_CLK_CNTL, + .mask = 0x3, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_1_sel", + .ops = &clk_regmap_mux_ops, + .parent_names = gxbb_vdec_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_vdec_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VDEC_CLK_CNTL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_1_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "vdec_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_vdec_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VDEC_CLK_CNTL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_1", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "vdec_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_vdec_hevc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .mask = 0x3, + .shift = 25, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevc_sel", + .ops = &clk_regmap_mux_ops, + .parent_names = gxbb_vdec_parent_names, + .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_vdec_hevc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevc_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "vdec_hevc_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gxbb_vdec_hevc = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_hevc", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "vdec_hevc_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + /* Everything Else (EE) domain gates */ static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); @@ -1786,6 +1869,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw, [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw, [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw, + [CLKID_VDEC_1_SEL] = &gxbb_vdec_1_sel.hw, + [CLKID_VDEC_1_DIV] = &gxbb_vdec_1_div.hw, + [CLKID_VDEC_1] = &gxbb_vdec_1.hw, + [CLKID_VDEC_HEVC_SEL] = &gxbb_vdec_hevc_sel.hw, + [CLKID_VDEC_HEVC_DIV] = &gxbb_vdec_hevc_div.hw, + [CLKID_VDEC_HEVC] = &gxbb_vdec_hevc.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -1942,6 +2031,12 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { [CLKID_FCLK_DIV4_DIV] = &gxbb_fclk_div4_div.hw, [CLKID_FCLK_DIV5_DIV] = &gxbb_fclk_div5_div.hw, [CLKID_FCLK_DIV7_DIV] = &gxbb_fclk_div7_div.hw, + [CLKID_VDEC_1_SEL] = &gxbb_vdec_1_sel.hw, + [CLKID_VDEC_1_DIV] = &gxbb_vdec_1_div.hw, + [CLKID_VDEC_1] = &gxbb_vdec_1.hw, + [CLKID_VDEC_HEVC_SEL] = &gxbb_vdec_hevc_sel.hw, + [CLKID_VDEC_HEVC_DIV] = &gxbb_vdec_hevc_div.hw, + [CLKID_VDEC_HEVC] = &gxbb_vdec_hevc.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -2100,6 +2195,12 @@ static struct clk_regmap *const gx_clk_regmaps[] = { &gxbb_fclk_div4, &gxbb_fclk_div5, &gxbb_fclk_div7, + &gxbb_vdec_1_sel, + &gxbb_vdec_1_div, + &gxbb_vdec_1, + &gxbb_vdec_hevc_sel, + &gxbb_vdec_hevc_div, + &gxbb_vdec_hevc, }; struct clkc_data { diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 9febf3f03739..ec1a812bf1fd 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -1,57 +1,7 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* - * 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 AmLogic, Inc. * Author: Michael Turquette <mturquette@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, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * The full GNU General Public License is included in this distribution - * in the file called COPYING - * - * BSD LICENSE - * - * Copyright (c) 2016 BayLibre, Inc. - * Author: Michael Turquette <mturquette@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. */ #ifndef __GXBB_H @@ -204,8 +154,12 @@ #define CLKID_FCLK_DIV4_DIV 148 #define CLKID_FCLK_DIV5_DIV 149 #define CLKID_FCLK_DIV7_DIV 150 +#define CLKID_VDEC_1_SEL 151 +#define CLKID_VDEC_1_DIV 152 +#define CLKID_VDEC_HEVC_SEL 154 +#define CLKID_VDEC_HEVC_DIV 155 -#define NR_CLKS 151 +#define NR_CLKS 157 /* include the CLKIDs that have been made part of the DT binding */ #include <dt-bindings/clock/gxbb-clkc.h> diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c new file mode 100644 index 000000000000..f965845917e3 --- /dev/null +++ b/drivers/clk/meson/meson-aoclk.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Amlogic Meson-AXG Clock Controller Driver + * + * Copyright (c) 2016 BayLibre, SAS. + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai <qiufang.dai@amlogic.com> + * Author: Yixun Lan <yixun.lan@amlogic.com> + */ + +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/mfd/syscon.h> +#include <linux/of_device.h> +#include "clk-regmap.h" +#include "meson-aoclk.h" + +static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct meson_aoclk_reset_controller *rstc = + container_of(rcdev, struct meson_aoclk_reset_controller, reset); + + return regmap_write(rstc->regmap, rstc->data->reset_reg, + BIT(rstc->data->reset[id])); +} + +static const struct reset_control_ops meson_aoclk_reset_ops = { + .reset = meson_aoclk_do_reset, +}; + +int meson_aoclkc_probe(struct platform_device *pdev) +{ + struct meson_aoclk_reset_controller *rstc; + struct meson_aoclk_data *data; + struct device *dev = &pdev->dev; + struct regmap *regmap; + int ret, clkid; + + data = (struct meson_aoclk_data *) of_device_get_match_data(dev); + if (!data) + return -ENODEV; + + rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL); + if (!rstc) + return -ENOMEM; + + regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to get regmap\n"); + return PTR_ERR(regmap); + } + + /* Reset Controller */ + rstc->data = data; + rstc->regmap = regmap; + rstc->reset.ops = &meson_aoclk_reset_ops; + rstc->reset.nr_resets = data->num_reset, + rstc->reset.of_node = dev->of_node; + ret = devm_reset_controller_register(dev, &rstc->reset); + if (ret) { + dev_err(dev, "failed to register reset controller\n"); + return ret; + } + + /* + * Populate regmap and register all clks + */ + for (clkid = 0; clkid < data->num_clks; clkid++) { + data->clks[clkid]->map = regmap; + + ret = devm_clk_hw_register(dev, data->hw_data->hws[clkid]); + if (ret) + return ret; + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + (void *) data->hw_data); +} diff --git a/drivers/clk/meson/meson-aoclk.h b/drivers/clk/meson/meson-aoclk.h new file mode 100644 index 000000000000..ab2819e88922 --- /dev/null +++ b/drivers/clk/meson/meson-aoclk.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright (c) 2017 BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai <qiufang.dai@amlogic.com> + * Author: Yixun Lan <yixun.lan@amlogic.com> + */ + +#ifndef __MESON_AOCLK_H__ +#define __MESON_AOCLK_H__ + +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include "clk-regmap.h" + +struct meson_aoclk_data { + const unsigned int reset_reg; + const int num_reset; + const unsigned int *reset; + int num_clks; + struct clk_regmap **clks; + const struct clk_hw_onecell_data *hw_data; +}; + +struct meson_aoclk_reset_controller { + struct reset_controller_dev reset; + const struct meson_aoclk_data *data; + struct regmap *regmap; +}; + +int meson_aoclkc_probe(struct platform_device *pdev); +#endif diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index cc2992493e0b..98f96d801de6 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -1,24 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * AmLogic S802 (Meson8) / S805 (Meson8b) / S812 (Meson8m2) Clock Controller - * Driver - * * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione <carlo@endlessm.com> * * Copyright (c) 2016 BayLibre, Inc. * Michael Turquette <mturquette@baylibre.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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/>. */ #include <linux/clk.h> @@ -246,6 +232,13 @@ static struct clk_regmap meson8b_fclk_div2 = { .ops = &clk_regmap_gate_ops, .parent_names = (const char *[]){ "fclk_div2_div" }, .num_parents = 1, + /* + * FIXME: Ethernet with a RGMII PHYs is not working if + * fclk_div2 is disabled. it is currently unclear why this + * is. keep it enabled until the Ethernet driver knows how + * to manage this clock. + */ + .flags = CLK_IS_CRITICAL, }, }; @@ -639,6 +632,54 @@ static struct clk_regmap meson8b_cpu_clk = { }, }; +static struct clk_regmap meson8b_nand_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_NAND_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "nand_clk_sel", + .ops = &clk_regmap_mux_ops, + /* FIXME all other parents are unknown: */ + .parent_names = (const char *[]){ "fclk_div4", "fclk_div3", + "fclk_div5", "fclk_div7", "xtal" }, + .num_parents = 5, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap meson8b_nand_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_NAND_CLK_CNTL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "nand_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "nand_clk_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap meson8b_nand_clk_gate = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_NAND_CLK_CNTL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "nand_clk_gate", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "nand_clk_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + /* Everything Else (EE) domain gates */ static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0); @@ -834,6 +875,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_FCLK_DIV4_DIV] = &meson8b_fclk_div4_div.hw, [CLKID_FCLK_DIV5_DIV] = &meson8b_fclk_div5_div.hw, [CLKID_FCLK_DIV7_DIV] = &meson8b_fclk_div7_div.hw, + [CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw, + [CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw, + [CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw, [CLK_NR_CLKS] = NULL, }, .num = CLK_NR_CLKS, @@ -939,6 +983,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_fclk_div4, &meson8b_fclk_div5, &meson8b_fclk_div7, + &meson8b_nand_clk_sel, + &meson8b_nand_clk_div, + &meson8b_nand_clk_gate, }; static const struct meson8b_clk_reset_line { diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index 6e414bd36981..5d09412b5084 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -1,21 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2015 Endless Mobile, Inc. * Author: Carlo Caione <carlo@endlessm.com> * * Copyright (c) 2016 BayLibre, Inc. * Michael Turquette <mturquette@baylibre.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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/>. */ #ifndef __MESON8B_H @@ -40,6 +29,7 @@ #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ #define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */ #define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ +#define HHI_NAND_CLK_CNTL 0x25c /* 0x97 offset in data sheet */ #define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ #define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ @@ -83,8 +73,10 @@ #define CLKID_FCLK_DIV4_DIV 107 #define CLKID_FCLK_DIV5_DIV 108 #define CLKID_FCLK_DIV7_DIV 109 +#define CLKID_NAND_SEL 110 +#define CLKID_NAND_DIV 111 -#define CLK_NR_CLKS 110 +#define CLK_NR_CLKS 113 /* * include the CLKID and RESETID that have diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index ef76c861ec84..f9ba71311727 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -7,6 +7,7 @@ config CLK_RENESAS select CLK_R8A7740 if ARCH_R8A7740 select CLK_R8A7743 if ARCH_R8A7743 select CLK_R8A7745 if ARCH_R8A7745 + select CLK_R8A77470 if ARCH_R8A77470 select CLK_R8A7778 if ARCH_R8A7778 select CLK_R8A7779 if ARCH_R8A7779 select CLK_R8A7790 if ARCH_R8A7790 @@ -18,6 +19,7 @@ config CLK_RENESAS select CLK_R8A77965 if ARCH_R8A77965 select CLK_R8A77970 if ARCH_R8A77970 select CLK_R8A77980 if ARCH_R8A77980 + select CLK_R8A77990 if ARCH_R8A77990 select CLK_R8A77995 if ARCH_R8A77995 select CLK_SH73A0 if ARCH_SH73A0 @@ -60,6 +62,10 @@ config CLK_R8A7745 bool "RZ/G1E clock support" if COMPILE_TEST select CLK_RCAR_GEN2_CPG +config CLK_R8A77470 + bool "RZ/G1C clock support" if COMPILE_TEST + select CLK_RCAR_GEN2_CPG + config CLK_R8A7778 bool "R-Car M1A clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP @@ -111,6 +117,10 @@ config CLK_R8A77980 bool "R-Car V3H clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG +config CLK_R8A77990 + bool "R-Car E3 clock support" if COMPILE_TEST + select CLK_RCAR_GEN3_CPG + config CLK_R8A77995 bool "R-Car D3 clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 6c0f19636e3e..fe5bac9215e5 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_CLK_R8A73A4) += clk-r8a73a4.o obj-$(CONFIG_CLK_R8A7740) += clk-r8a7740.o obj-$(CONFIG_CLK_R8A7743) += r8a7743-cpg-mssr.o obj-$(CONFIG_CLK_R8A7745) += r8a7745-cpg-mssr.o +obj-$(CONFIG_CLK_R8A77470) += r8a77470-cpg-mssr.o obj-$(CONFIG_CLK_R8A7778) += clk-r8a7778.o obj-$(CONFIG_CLK_R8A7779) += clk-r8a7779.o obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o @@ -17,6 +18,7 @@ obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o obj-$(CONFIG_CLK_R8A77965) += r8a77965-cpg-mssr.o obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o obj-$(CONFIG_CLK_R8A77980) += r8a77980-cpg-mssr.o +obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o diff --git a/drivers/clk/renesas/r8a7743-cpg-mssr.c b/drivers/clk/renesas/r8a7743-cpg-mssr.c index d3c8b1e2969f..011c170ec3f9 100644 --- a/drivers/clk/renesas/r8a7743-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7743-cpg-mssr.c @@ -52,7 +52,6 @@ static const struct cpg_core_clk r8a7743_core_clks[] __initconst = { /* Core Clock Outputs */ DEF_BASE("z", R8A7743_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0), - DEF_BASE("lb", R8A7743_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1), DEF_BASE("sdh", R8A7743_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1), DEF_BASE("sd0", R8A7743_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1), DEF_BASE("qspi", R8A7743_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2), @@ -63,6 +62,7 @@ static const struct cpg_core_clk r8a7743_core_clks[] __initconst = { DEF_FIXED("zs", R8A7743_CLK_ZS, CLK_PLL1, 6, 1), DEF_FIXED("hp", R8A7743_CLK_HP, CLK_PLL1, 12, 1), DEF_FIXED("b", R8A7743_CLK_B, CLK_PLL1, 12, 1), + DEF_FIXED("lb", R8A7743_CLK_LB, CLK_PLL1, 24, 1), DEF_FIXED("p", R8A7743_CLK_P, CLK_PLL1, 24, 1), DEF_FIXED("cl", R8A7743_CLK_CL, CLK_PLL1, 48, 1), DEF_FIXED("m2", R8A7743_CLK_M2, CLK_PLL1, 8, 1), diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c index 87f5a3619e4f..4b0a9243b748 100644 --- a/drivers/clk/renesas/r8a7745-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c @@ -51,7 +51,6 @@ static const struct cpg_core_clk r8a7745_core_clks[] __initconst = { DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), /* Core Clock Outputs */ - DEF_BASE("lb", R8A7745_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1), DEF_BASE("sdh", R8A7745_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1), DEF_BASE("sd0", R8A7745_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1), DEF_BASE("qspi", R8A7745_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2), @@ -63,6 +62,7 @@ static const struct cpg_core_clk r8a7745_core_clks[] __initconst = { DEF_FIXED("zs", R8A7745_CLK_ZS, CLK_PLL1, 6, 1), DEF_FIXED("hp", R8A7745_CLK_HP, CLK_PLL1, 12, 1), DEF_FIXED("b", R8A7745_CLK_B, CLK_PLL1, 12, 1), + DEF_FIXED("lb", R8A7745_CLK_LB, CLK_PLL1, 24, 1), DEF_FIXED("p", R8A7745_CLK_P, CLK_PLL1, 24, 1), DEF_FIXED("cl", R8A7745_CLK_CL, CLK_PLL1, 48, 1), DEF_FIXED("cp", R8A7745_CLK_CP, CLK_PLL1, 48, 1), diff --git a/drivers/clk/renesas/r8a77470-cpg-mssr.c b/drivers/clk/renesas/r8a77470-cpg-mssr.c new file mode 100644 index 000000000000..ab0fb10b6bf0 --- /dev/null +++ b/drivers/clk/renesas/r8a77470-cpg-mssr.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * r8a77470 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2018 Renesas Electronics Corp. + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/soc/renesas/rcar-rst.h> + +#include <dt-bindings/clock/r8a77470-cpg-mssr.h> + +#include "renesas-cpg-mssr.h" +#include "rcar-gen2-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A77470_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_USB_EXTAL, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL3, + CLK_PLL1_DIV2, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a77470_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("usb_extal", CLK_USB_EXTAL), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + + /* Core Clock Outputs */ + DEF_BASE("sdh", R8A77470_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1), + DEF_BASE("sd0", R8A77470_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1), + DEF_BASE("sd1", R8A77470_CLK_SD1, CLK_TYPE_GEN2_SD1, CLK_PLL1), + DEF_BASE("qspi", R8A77470_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2), + DEF_BASE("rcan", R8A77470_CLK_RCAN, CLK_TYPE_GEN2_RCAN, CLK_USB_EXTAL), + + DEF_FIXED("z2", R8A77470_CLK_Z2, CLK_PLL0, 1, 1), + DEF_FIXED("zx", R8A77470_CLK_ZX, CLK_PLL1, 3, 1), + DEF_FIXED("zs", R8A77470_CLK_ZS, CLK_PLL1, 6, 1), + DEF_FIXED("hp", R8A77470_CLK_HP, CLK_PLL1, 12, 1), + DEF_FIXED("b", R8A77470_CLK_B, CLK_PLL1, 12, 1), + DEF_FIXED("lb", R8A77470_CLK_LB, CLK_PLL1, 24, 1), + DEF_FIXED("p", R8A77470_CLK_P, CLK_PLL1, 24, 1), + DEF_FIXED("cl", R8A77470_CLK_CL, CLK_PLL1, 48, 1), + DEF_FIXED("cp", R8A77470_CLK_CP, CLK_PLL1, 48, 1), + DEF_FIXED("m2", R8A77470_CLK_M2, CLK_PLL1, 8, 1), + DEF_FIXED("zb3", R8A77470_CLK_ZB3, CLK_PLL3, 4, 1), + DEF_FIXED("mp", R8A77470_CLK_MP, CLK_PLL1_DIV2, 15, 1), + DEF_FIXED("cpex", R8A77470_CLK_CPEX, CLK_EXTAL, 2, 1), + DEF_FIXED("r", R8A77470_CLK_R, CLK_PLL1, 49152, 1), + DEF_FIXED("osc", R8A77470_CLK_OSC, CLK_PLL1, 12288, 1), + + DEF_DIV6P1("sd2", R8A77470_CLK_SD2, CLK_PLL1_DIV2, 0x078), +}; + +static const struct mssr_mod_clk r8a77470_mod_clks[] __initconst = { + DEF_MOD("msiof0", 0, R8A77470_CLK_MP), + DEF_MOD("vcp0", 101, R8A77470_CLK_ZS), + DEF_MOD("vpc0", 103, R8A77470_CLK_ZS), + DEF_MOD("tmu1", 111, R8A77470_CLK_P), + DEF_MOD("3dg", 112, R8A77470_CLK_ZS), + DEF_MOD("2d-dmac", 115, R8A77470_CLK_ZS), + DEF_MOD("fdp1-0", 119, R8A77470_CLK_ZS), + DEF_MOD("tmu3", 121, R8A77470_CLK_P), + DEF_MOD("tmu2", 122, R8A77470_CLK_P), + DEF_MOD("cmt0", 124, R8A77470_CLK_R), + DEF_MOD("vsp1du0", 128, R8A77470_CLK_ZS), + DEF_MOD("vsp1-sy", 131, R8A77470_CLK_ZS), + DEF_MOD("msiof2", 205, R8A77470_CLK_MP), + DEF_MOD("msiof1", 208, R8A77470_CLK_MP), + DEF_MOD("sys-dmac1", 218, R8A77470_CLK_ZS), + DEF_MOD("sys-dmac0", 219, R8A77470_CLK_ZS), + DEF_MOD("sdhi2", 312, R8A77470_CLK_SD2), + DEF_MOD("sdhi1", 313, R8A77470_CLK_SD1), + DEF_MOD("sdhi0", 314, R8A77470_CLK_SD0), + DEF_MOD("usbhs-dmac0-ch1", 326, R8A77470_CLK_HP), + DEF_MOD("usbhs-dmac1-ch1", 327, R8A77470_CLK_HP), + DEF_MOD("cmt1", 329, R8A77470_CLK_R), + DEF_MOD("usbhs-dmac0-ch0", 330, R8A77470_CLK_HP), + DEF_MOD("usbhs-dmac1-ch0", 331, R8A77470_CLK_HP), + DEF_MOD("rwdt", 402, R8A77470_CLK_R), + DEF_MOD("irqc", 407, R8A77470_CLK_CP), + DEF_MOD("intc-sys", 408, R8A77470_CLK_ZS), + DEF_MOD("audio-dmac0", 502, R8A77470_CLK_HP), + DEF_MOD("pwm", 523, R8A77470_CLK_P), + DEF_MOD("usb-ehci-0", 703, R8A77470_CLK_MP), + DEF_MOD("usbhs-0", 704, R8A77470_CLK_HP), + DEF_MOD("usb-ehci-1", 705, R8A77470_CLK_MP), + DEF_MOD("usbhs-1", 706, R8A77470_CLK_HP), + DEF_MOD("hscif2", 713, R8A77470_CLK_ZS), + DEF_MOD("scif5", 714, R8A77470_CLK_P), + DEF_MOD("scif4", 715, R8A77470_CLK_P), + DEF_MOD("hscif1", 716, R8A77470_CLK_ZS), + DEF_MOD("hscif0", 717, R8A77470_CLK_ZS), + DEF_MOD("scif3", 718, R8A77470_CLK_P), + DEF_MOD("scif2", 719, R8A77470_CLK_P), + DEF_MOD("scif1", 720, R8A77470_CLK_P), + DEF_MOD("scif0", 721, R8A77470_CLK_P), + DEF_MOD("du1", 723, R8A77470_CLK_ZX), + DEF_MOD("du0", 724, R8A77470_CLK_ZX), + DEF_MOD("ipmmu-sgx", 800, R8A77470_CLK_ZX), + DEF_MOD("etheravb", 812, R8A77470_CLK_HP), + DEF_MOD("ether", 813, R8A77470_CLK_P), + DEF_MOD("gpio5", 907, R8A77470_CLK_CP), + DEF_MOD("gpio4", 908, R8A77470_CLK_CP), + DEF_MOD("gpio3", 909, R8A77470_CLK_CP), + DEF_MOD("gpio2", 910, R8A77470_CLK_CP), + DEF_MOD("gpio1", 911, R8A77470_CLK_CP), + DEF_MOD("gpio0", 912, R8A77470_CLK_CP), + DEF_MOD("can1", 915, R8A77470_CLK_P), + DEF_MOD("can0", 916, R8A77470_CLK_P), + DEF_MOD("qspi_mod-1", 917, R8A77470_CLK_QSPI), + DEF_MOD("qspi_mod-0", 918, R8A77470_CLK_QSPI), + DEF_MOD("i2c4", 927, R8A77470_CLK_HP), + DEF_MOD("i2c3", 928, R8A77470_CLK_HP), + DEF_MOD("i2c2", 929, R8A77470_CLK_HP), + DEF_MOD("i2c1", 930, R8A77470_CLK_HP), + DEF_MOD("i2c0", 931, R8A77470_CLK_HP), + DEF_MOD("ssi-all", 1005, R8A77470_CLK_P), + DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)), + DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)), + DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)), + DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)), + DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)), + DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), + DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), + DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)), + DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)), + DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)), + DEF_MOD("scu-all", 1017, R8A77470_CLK_P), + DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), + DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), + DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), + DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), + DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)), + DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)), + DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)), + DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)), +}; + +static const unsigned int r8a77470_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ + MOD_CLK_ID(408), /* INTC-SYS (GIC) */ +}; + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL3 + * 14 13 (MHz) *1 *2 + *--------------------------------------------------- + * 0 0 20 x80 x78 x50 + * 0 1 26 x60 x60 x56 + * 1 0 Prohibitted setting + * 1 1 30 x52 x52 x50 + * + * *1 : Table 7.4 indicates VCO output (PLL0 = VCO) + * *2 : Table 7.4 indicates VCO output (PLL1 = VCO) + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \ + (((md) & BIT(13)) >> 13)) + +static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[4] __initconst = { + /* EXTAL div PLL1 mult x2 PLL3 mult */ + { 1, 156, 50, }, + { 1, 120, 56, }, + { /* Invalid*/ }, + { 1, 104, 50, }, +}; + +static int __init r8a77470_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen2_cpg_pll_config *cpg_pll_config; + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode); +} + +const struct cpg_mssr_info r8a77470_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a77470_core_clks, + .num_core_clks = ARRAY_SIZE(r8a77470_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a77470_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a77470_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a77470_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a77470_crit_mod_clks), + + /* Callbacks */ + .init = r8a77470_cpg_mssr_init, + .cpg_clk_register = rcar_gen2_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/r8a7791-cpg-mssr.c b/drivers/clk/renesas/r8a7791-cpg-mssr.c index 820b220b09cc..1b91f03b7598 100644 --- a/drivers/clk/renesas/r8a7791-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7791-cpg-mssr.c @@ -57,7 +57,6 @@ static struct cpg_core_clk r8a7791_core_clks[] __initdata = { /* Core Clock Outputs */ DEF_BASE("z", R8A7791_CLK_Z, CLK_TYPE_GEN2_Z, CLK_PLL0), - DEF_BASE("lb", R8A7791_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1), DEF_BASE("adsp", R8A7791_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1), DEF_BASE("sdh", R8A7791_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1), DEF_BASE("sd0", R8A7791_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1), @@ -70,6 +69,7 @@ static struct cpg_core_clk r8a7791_core_clks[] __initdata = { DEF_FIXED("hp", R8A7791_CLK_HP, CLK_PLL1, 12, 1), DEF_FIXED("i", R8A7791_CLK_I, CLK_PLL1, 2, 1), DEF_FIXED("b", R8A7791_CLK_B, CLK_PLL1, 12, 1), + DEF_FIXED("lb", R8A7791_CLK_LB, CLK_PLL1, 24, 1), DEF_FIXED("p", R8A7791_CLK_P, CLK_PLL1, 24, 1), DEF_FIXED("cl", R8A7791_CLK_CL, CLK_PLL1, 48, 1), DEF_FIXED("m2", R8A7791_CLK_M2, CLK_PLL1, 8, 1), diff --git a/drivers/clk/renesas/r8a7792-cpg-mssr.c b/drivers/clk/renesas/r8a7792-cpg-mssr.c index 609a54080496..493e07859f5f 100644 --- a/drivers/clk/renesas/r8a7792-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7792-cpg-mssr.c @@ -53,7 +53,6 @@ static const struct cpg_core_clk r8a7792_core_clks[] __initconst = { DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), /* Core Clock Outputs */ - DEF_BASE("lb", R8A7792_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1), DEF_BASE("qspi", R8A7792_CLK_QSPI, CLK_TYPE_GEN2_QSPI, CLK_PLL1_DIV2), DEF_FIXED("z", R8A7792_CLK_Z, CLK_PLL0, 1, 1), @@ -63,6 +62,7 @@ static const struct cpg_core_clk r8a7792_core_clks[] __initconst = { DEF_FIXED("hp", R8A7792_CLK_HP, CLK_PLL1, 12, 1), DEF_FIXED("i", R8A7792_CLK_I, CLK_PLL1, 3, 1), DEF_FIXED("b", R8A7792_CLK_B, CLK_PLL1, 12, 1), + DEF_FIXED("lb", R8A7792_CLK_LB, CLK_PLL1, 24, 1), DEF_FIXED("p", R8A7792_CLK_P, CLK_PLL1, 24, 1), DEF_FIXED("cl", R8A7792_CLK_CL, CLK_PLL1, 48, 1), DEF_FIXED("m2", R8A7792_CLK_M2, CLK_PLL1, 8, 1), diff --git a/drivers/clk/renesas/r8a7794-cpg-mssr.c b/drivers/clk/renesas/r8a7794-cpg-mssr.c index 2a40bbeaeeaf..088f4b79fdfc 100644 --- a/drivers/clk/renesas/r8a7794-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7794-cpg-mssr.c @@ -55,7 +55,6 @@ static const struct cpg_core_clk r8a7794_core_clks[] __initconst = { DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), /* Core Clock Outputs */ - DEF_BASE("lb", R8A7794_CLK_LB, CLK_TYPE_GEN2_LB, CLK_PLL1), DEF_BASE("adsp", R8A7794_CLK_ADSP, CLK_TYPE_GEN2_ADSP, CLK_PLL1), DEF_BASE("sdh", R8A7794_CLK_SDH, CLK_TYPE_GEN2_SDH, CLK_PLL1), DEF_BASE("sd0", R8A7794_CLK_SD0, CLK_TYPE_GEN2_SD0, CLK_PLL1), @@ -69,6 +68,7 @@ static const struct cpg_core_clk r8a7794_core_clks[] __initconst = { DEF_FIXED("hp", R8A7794_CLK_HP, CLK_PLL1, 12, 1), DEF_FIXED("i", R8A7794_CLK_I, CLK_PLL1, 2, 1), DEF_FIXED("b", R8A7794_CLK_B, CLK_PLL1, 12, 1), + DEF_FIXED("lb", R8A7794_CLK_LB, CLK_PLL1, 24, 1), DEF_FIXED("p", R8A7794_CLK_P, CLK_PLL1, 24, 1), DEF_FIXED("cl", R8A7794_CLK_CL, CLK_PLL1, 48, 1), DEF_FIXED("cp", R8A7794_CLK_CP, CLK_PLL1, 48, 1), diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index b1acfb60351c..8fae5e9c4a77 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -116,6 +116,10 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("scif3", 204, R8A77965_CLK_S3D4), DEF_MOD("scif1", 206, R8A77965_CLK_S3D4), DEF_MOD("scif0", 207, R8A77965_CLK_S3D4), + DEF_MOD("msiof3", 208, R8A77965_CLK_MSO), + DEF_MOD("msiof2", 209, R8A77965_CLK_MSO), + DEF_MOD("msiof1", 210, R8A77965_CLK_MSO), + DEF_MOD("msiof0", 211, R8A77965_CLK_MSO), DEF_MOD("sys-dmac2", 217, R8A77965_CLK_S0D3), DEF_MOD("sys-dmac1", 218, R8A77965_CLK_S0D3), DEF_MOD("sys-dmac0", 219, R8A77965_CLK_S0D3), diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c index 7aaae73a321a..d7ebd9ec0059 100644 --- a/drivers/clk/renesas/r8a77980-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c @@ -116,7 +116,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { DEF_MOD("sys-dmac1", 218, R8A77980_CLK_S0D3), DEF_MOD("tpu0", 304, R8A77980_CLK_S3D4), DEF_MOD("sdif", 314, R8A77980_CLK_SD0), - DEF_MOD("pciec0", 319, R8A77980_CLK_S3D1), + DEF_MOD("pciec0", 319, R8A77980_CLK_S2D2), DEF_MOD("intc-ex", 407, R8A77980_CLK_CP), DEF_MOD("intc-ap", 408, R8A77980_CLK_S0D3), DEF_MOD("hscif3", 517, R8A77980_CLK_S3D1), diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c new file mode 100644 index 000000000000..9e14f1486fbb --- /dev/null +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * r8a77990 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2018 Renesas Electronics Corp. + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/soc/renesas/rcar-rst.h> + +#include <dt-bindings/clock/r8a77990-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 = R8A77990_CLK_CPEX, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL3, + CLK_PLL0D4, + CLK_PLL0D6, + CLK_PLL0D8, + CLK_PLL0D20, + CLK_PLL0D24, + CLK_PLL1D2, + CLK_PE, + CLK_S0, + CLK_S1, + CLK_S2, + CLK_S3, + CLK_SDSRC, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + + DEF_FIXED(".pll0", CLK_PLL0, CLK_MAIN, 1, 100), + DEF_FIXED(".pll0d4", CLK_PLL0D4, CLK_PLL0, 4, 1), + DEF_FIXED(".pll0d6", CLK_PLL0D6, CLK_PLL0, 6, 1), + DEF_FIXED(".pll0d8", CLK_PLL0D8, CLK_PLL0, 8, 1), + DEF_FIXED(".pll0d20", CLK_PLL0D20, CLK_PLL0, 20, 1), + DEF_FIXED(".pll0d24", CLK_PLL0D24, CLK_PLL0, 24, 1), + DEF_FIXED(".pll1d2", CLK_PLL1D2, CLK_PLL1, 2, 1), + DEF_FIXED(".pe", CLK_PE, CLK_PLL0D20, 1, 1), + DEF_FIXED(".s0", CLK_S0, CLK_PLL1, 2, 1), + DEF_FIXED(".s1", CLK_S1, CLK_PLL1, 3, 1), + DEF_FIXED(".s2", CLK_S2, CLK_PLL1, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), + + /* Core Clock Outputs */ + DEF_FIXED("za2", R8A77990_CLK_ZA2, CLK_PLL0D24, 1, 1), + DEF_FIXED("za8", R8A77990_CLK_ZA8, CLK_PLL0D8, 1, 1), + DEF_FIXED("ztr", R8A77990_CLK_ZTR, CLK_PLL1, 6, 1), + DEF_FIXED("zt", R8A77990_CLK_ZT, CLK_PLL1, 4, 1), + DEF_FIXED("zx", R8A77990_CLK_ZX, CLK_PLL1, 3, 1), + DEF_FIXED("s0d1", R8A77990_CLK_S0D1, CLK_S0, 1, 1), + DEF_FIXED("s0d3", R8A77990_CLK_S0D3, CLK_S0, 3, 1), + DEF_FIXED("s0d6", R8A77990_CLK_S0D6, CLK_S0, 6, 1), + DEF_FIXED("s0d12", R8A77990_CLK_S0D12, CLK_S0, 12, 1), + DEF_FIXED("s0d24", R8A77990_CLK_S0D24, CLK_S0, 24, 1), + DEF_FIXED("s1d1", R8A77990_CLK_S1D1, CLK_S1, 1, 1), + DEF_FIXED("s1d2", R8A77990_CLK_S1D2, CLK_S1, 2, 1), + DEF_FIXED("s1d4", R8A77990_CLK_S1D4, CLK_S1, 4, 1), + DEF_FIXED("s2d1", R8A77990_CLK_S2D1, CLK_S2, 1, 1), + DEF_FIXED("s2d2", R8A77990_CLK_S2D2, CLK_S2, 2, 1), + DEF_FIXED("s2d4", R8A77990_CLK_S2D4, CLK_S2, 4, 1), + DEF_FIXED("s3d1", R8A77990_CLK_S3D1, CLK_S3, 1, 1), + DEF_FIXED("s3d2", R8A77990_CLK_S3D2, CLK_S3, 2, 1), + DEF_FIXED("s3d4", R8A77990_CLK_S3D4, CLK_S3, 4, 1), + + DEF_GEN3_SD("sd0", R8A77990_CLK_SD0, CLK_SDSRC, 0x0074), + DEF_GEN3_SD("sd1", R8A77990_CLK_SD1, CLK_SDSRC, 0x0078), + DEF_GEN3_SD("sd3", R8A77990_CLK_SD3, CLK_SDSRC, 0x026c), + + DEF_FIXED("cl", R8A77990_CLK_CL, CLK_PLL1, 48, 1), + DEF_FIXED("cp", R8A77990_CLK_CP, CLK_EXTAL, 2, 1), + DEF_FIXED("cpex", R8A77990_CLK_CPEX, CLK_EXTAL, 4, 1), + DEF_FIXED("osc", R8A77990_CLK_OSC, CLK_EXTAL, 384, 1), + DEF_FIXED("r", R8A77990_CLK_R, CLK_EXTAL, 1536, 1), + + DEF_GEN3_PE("s0d6c", R8A77990_CLK_S0D6C, CLK_S0, 6, CLK_PE, 2), + DEF_GEN3_PE("s3d1c", R8A77990_CLK_S3D1C, CLK_S3, 1, CLK_PE, 1), + DEF_GEN3_PE("s3d2c", R8A77990_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2), + DEF_GEN3_PE("s3d4c", R8A77990_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4), + + DEF_DIV6P1("canfd", R8A77990_CLK_CANFD, CLK_PLL0D6, 0x244), + DEF_DIV6P1("csi0", R8A77990_CLK_CSI0, CLK_PLL1D2, 0x00c), + DEF_DIV6P1("mso", R8A77990_CLK_MSO, CLK_PLL1D2, 0x014), +}; + +static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { + DEF_MOD("scif5", 202, R8A77990_CLK_S3D4C), + DEF_MOD("scif4", 203, R8A77990_CLK_S3D4C), + DEF_MOD("scif3", 204, R8A77990_CLK_S3D4C), + DEF_MOD("scif1", 206, R8A77990_CLK_S3D4C), + DEF_MOD("scif0", 207, R8A77990_CLK_S3D4C), + DEF_MOD("msiof3", 208, R8A77990_CLK_MSO), + DEF_MOD("msiof2", 209, R8A77990_CLK_MSO), + DEF_MOD("msiof1", 210, R8A77990_CLK_MSO), + DEF_MOD("msiof0", 211, R8A77990_CLK_MSO), + DEF_MOD("sys-dmac2", 217, R8A77990_CLK_S3D1), + DEF_MOD("sys-dmac1", 218, R8A77990_CLK_S3D1), + DEF_MOD("sys-dmac0", 219, R8A77990_CLK_S3D1), + + DEF_MOD("cmt3", 300, R8A77990_CLK_R), + DEF_MOD("cmt2", 301, R8A77990_CLK_R), + DEF_MOD("cmt1", 302, R8A77990_CLK_R), + DEF_MOD("cmt0", 303, R8A77990_CLK_R), + DEF_MOD("scif2", 310, R8A77990_CLK_S3D4C), + DEF_MOD("sdif3", 311, R8A77990_CLK_SD3), + DEF_MOD("sdif1", 313, R8A77990_CLK_SD1), + DEF_MOD("sdif0", 314, R8A77990_CLK_SD0), + DEF_MOD("pcie0", 319, R8A77990_CLK_S3D1), + DEF_MOD("usb3-if0", 328, R8A77990_CLK_S3D1), + DEF_MOD("usb-dmac0", 330, R8A77990_CLK_S3D1), + DEF_MOD("usb-dmac1", 331, R8A77990_CLK_S3D1), + + DEF_MOD("rwdt", 402, R8A77990_CLK_R), + DEF_MOD("intc-ex", 407, R8A77990_CLK_CP), + DEF_MOD("intc-ap", 408, R8A77990_CLK_S0D3), + + DEF_MOD("audmac0", 502, R8A77990_CLK_S3D4), + DEF_MOD("drif7", 508, R8A77990_CLK_S3D2), + DEF_MOD("drif6", 509, R8A77990_CLK_S3D2), + DEF_MOD("drif5", 510, R8A77990_CLK_S3D2), + DEF_MOD("drif4", 511, R8A77990_CLK_S3D2), + DEF_MOD("drif3", 512, R8A77990_CLK_S3D2), + DEF_MOD("drif2", 513, R8A77990_CLK_S3D2), + DEF_MOD("drif1", 514, R8A77990_CLK_S3D2), + DEF_MOD("drif0", 515, R8A77990_CLK_S3D2), + DEF_MOD("hscif4", 516, R8A77990_CLK_S3D1C), + DEF_MOD("hscif3", 517, R8A77990_CLK_S3D1C), + DEF_MOD("hscif2", 518, R8A77990_CLK_S3D1C), + DEF_MOD("hscif1", 519, R8A77990_CLK_S3D1C), + DEF_MOD("hscif0", 520, R8A77990_CLK_S3D1C), + DEF_MOD("thermal", 522, R8A77990_CLK_CP), + DEF_MOD("pwm", 523, R8A77990_CLK_S3D4C), + + DEF_MOD("fcpvd1", 602, R8A77990_CLK_S1D2), + DEF_MOD("fcpvd0", 603, R8A77990_CLK_S1D2), + DEF_MOD("fcpvb0", 607, R8A77990_CLK_S0D1), + DEF_MOD("fcpvi0", 611, R8A77990_CLK_S0D1), + DEF_MOD("fcpf0", 615, R8A77990_CLK_S0D1), + DEF_MOD("fcpcs", 619, R8A77990_CLK_S0D1), + DEF_MOD("vspd1", 622, R8A77990_CLK_S1D2), + DEF_MOD("vspd0", 623, R8A77990_CLK_S1D2), + DEF_MOD("vspb", 626, R8A77990_CLK_S0D1), + DEF_MOD("vspi0", 631, R8A77990_CLK_S0D1), + + DEF_MOD("ehci0", 703, R8A77990_CLK_S3D4), + DEF_MOD("hsusb", 704, R8A77990_CLK_S3D4), + DEF_MOD("csi40", 716, R8A77990_CLK_CSI0), + DEF_MOD("du1", 723, R8A77990_CLK_S2D1), + DEF_MOD("du0", 724, R8A77990_CLK_S2D1), + DEF_MOD("lvds", 727, R8A77990_CLK_S2D1), + + DEF_MOD("vin5", 806, R8A77990_CLK_S1D2), + DEF_MOD("vin4", 807, R8A77990_CLK_S1D2), + DEF_MOD("etheravb", 812, R8A77990_CLK_S3D2), + + DEF_MOD("gpio6", 906, R8A77990_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A77990_CLK_S3D4), + DEF_MOD("gpio4", 908, R8A77990_CLK_S3D4), + DEF_MOD("gpio3", 909, R8A77990_CLK_S3D4), + DEF_MOD("gpio2", 910, R8A77990_CLK_S3D4), + DEF_MOD("gpio1", 911, R8A77990_CLK_S3D4), + DEF_MOD("gpio0", 912, R8A77990_CLK_S3D4), + DEF_MOD("can-fd", 914, R8A77990_CLK_S3D2), + DEF_MOD("can-if1", 915, R8A77990_CLK_S3D4), + DEF_MOD("can-if0", 916, R8A77990_CLK_S3D4), + DEF_MOD("i2c6", 918, R8A77990_CLK_S3D2), + DEF_MOD("i2c5", 919, R8A77990_CLK_S3D2), + DEF_MOD("i2c-dvfs", 926, R8A77990_CLK_CP), + DEF_MOD("i2c4", 927, R8A77990_CLK_S3D2), + DEF_MOD("i2c3", 928, R8A77990_CLK_S3D2), + DEF_MOD("i2c2", 929, R8A77990_CLK_S3D2), + DEF_MOD("i2c1", 930, R8A77990_CLK_S3D2), + DEF_MOD("i2c0", 931, R8A77990_CLK_S3D2), + + DEF_MOD("ssi-all", 1005, R8A77990_CLK_S3D4), + DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)), + DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)), + DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)), + DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)), + DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)), + DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), + DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), + DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)), + DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)), + DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)), + DEF_MOD("scu-all", 1017, R8A77990_CLK_S3D4), + DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), + DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), + DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)), + DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)), + DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)), + DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), + DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), + DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)), + DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)), + DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)), + DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)), + DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)), +}; + +static const unsigned int r8a77990_crit_mod_clks[] __initconst = { + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + +/* + * CPG Clock Data + */ + +/* + * MD19 EXTAL (MHz) PLL0 PLL1 PLL3 + *-------------------------------------------------------------------- + * 0 48 x 1 x100/4 x100/3 x100/3 + * 1 48 x 1 x100/4 x100/3 x58/3 + */ +#define CPG_PLL_CONFIG_INDEX(md) (((md) & BIT(19)) >> 19) + +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[2] __initconst = { + /* EXTAL div PLL1 mult/div PLL3 mult/div */ + { 1, 100, 3, 100, 3, }, + { 1, 100, 3, 58, 3, }, +}; + +static int __init r8a77990_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + + return rcar_gen3_cpg_init(cpg_pll_config, 0, cpg_mode); +} + +const struct cpg_mssr_info r8a77990_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a77990_core_clks, + .num_core_clks = ARRAY_SIZE(r8a77990_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a77990_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a77990_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a77990_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a77990_crit_mod_clks), + + /* Callbacks */ + .init = r8a77990_cpg_mssr_init, + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/rcar-gen2-cpg.c b/drivers/clk/renesas/rcar-gen2-cpg.c index feb14579a71b..daf88bc2cdae 100644 --- a/drivers/clk/renesas/rcar-gen2-cpg.c +++ b/drivers/clk/renesas/rcar-gen2-cpg.c @@ -16,6 +16,7 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/sys_soc.h> #include "renesas-cpg-mssr.h" #include "rcar-gen2-cpg.h" @@ -260,6 +261,17 @@ static const struct clk_div_table cpg_sd01_div_table[] = { static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_pll0_div __initdata; static u32 cpg_mode __initdata; +static u32 cpg_quirks __initdata; + +#define SD_SKIP_FIRST BIT(0) /* Skip first clock in SD table */ + +static const struct soc_device_attribute cpg_quirks_match[] __initconst = { + { + .soc_id = "r8a77470", + .data = (void *)SD_SKIP_FIRST, + }, + { /* sentinel */ } +}; struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, @@ -327,11 +339,17 @@ struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN2_SD0: table = cpg_sd01_div_table; + if (cpg_quirks & SD_SKIP_FIRST) + table++; + shift = 4; break; case CLK_TYPE_GEN2_SD1: table = cpg_sd01_div_table; + if (cpg_quirks & SD_SKIP_FIRST) + table++; + shift = 0; break; @@ -360,9 +378,15 @@ struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev, int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config, unsigned int pll0_div, u32 mode) { + const struct soc_device_attribute *attr; + cpg_pll_config = config; cpg_pll0_div = pll0_div; cpg_mode = mode; + attr = soc_device_match(cpg_quirks_match); + if (attr) + cpg_quirks = (uintptr_t)attr->data; + pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks); spin_lock_init(&cpg_lock); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 4e88e980fb76..49e510691eee 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -652,6 +652,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a7745_cpg_mssr_info, }, #endif +#ifdef CONFIG_CLK_R8A77470 + { + .compatible = "renesas,r8a77470-cpg-mssr", + .data = &r8a77470_cpg_mssr_info, + }, +#endif #ifdef CONFIG_CLK_R8A7790 { .compatible = "renesas,r8a7790-cpg-mssr", @@ -711,6 +717,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a77980_cpg_mssr_info, }, #endif +#ifdef CONFIG_CLK_R8A77990 + { + .compatible = "renesas,r8a77990-cpg-mssr", + .data = &r8a77990_cpg_mssr_info, + }, +#endif #ifdef CONFIG_CLK_R8A77995 { .compatible = "renesas,r8a77995-cpg-mssr", diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 97ccb093c10f..642f720b9b05 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -133,6 +133,7 @@ struct cpg_mssr_info { extern const struct cpg_mssr_info r8a7743_cpg_mssr_info; extern const struct cpg_mssr_info r8a7745_cpg_mssr_info; +extern const struct cpg_mssr_info r8a77470_cpg_mssr_info; extern const struct cpg_mssr_info r8a7790_cpg_mssr_info; extern const struct cpg_mssr_info r8a7791_cpg_mssr_info; extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; @@ -142,6 +143,7 @@ extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; extern const struct cpg_mssr_info r8a77965_cpg_mssr_info; extern const struct cpg_mssr_info r8a77970_cpg_mssr_info; extern const struct cpg_mssr_info r8a77980_cpg_mssr_info; +extern const struct cpg_mssr_info r8a77990_cpg_mssr_info; extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; diff --git a/include/dt-bindings/clock/axg-aoclkc.h b/include/dt-bindings/clock/axg-aoclkc.h new file mode 100644 index 000000000000..61955016a55b --- /dev/null +++ b/include/dt-bindings/clock/axg-aoclkc.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (c) 2016 BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai <qiufang.dai@amlogic.com> + */ + +#ifndef DT_BINDINGS_CLOCK_AMLOGIC_MESON_AXG_AOCLK +#define DT_BINDINGS_CLOCK_AMLOGIC_MESON_AXG_AOCLK + +#define CLKID_AO_REMOTE 0 +#define CLKID_AO_I2C_MASTER 1 +#define CLKID_AO_I2C_SLAVE 2 +#define CLKID_AO_UART1 3 +#define CLKID_AO_UART2 4 +#define CLKID_AO_IR_BLASTER 5 +#define CLKID_AO_SAR_ADC 6 +#define CLKID_AO_CLK81 7 +#define CLKID_AO_SAR_ADC_SEL 8 +#define CLKID_AO_SAR_ADC_DIV 9 +#define CLKID_AO_SAR_ADC_CLK 10 +#define CLKID_AO_ALT_XTAL 11 + +#endif diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h index 8ba99a5e3fd3..7a892be90549 100644 --- a/include/dt-bindings/clock/gxbb-clkc.h +++ b/include/dt-bindings/clock/gxbb-clkc.h @@ -125,5 +125,7 @@ #define CLKID_VAPB_1 138 #define CLKID_VAPB_SEL 139 #define CLKID_VAPB 140 +#define CLKID_VDEC_1 153 +#define CLKID_VDEC_HEVC 156 #endif /* __GXBB_CLKC_H */ diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h index dea9d46d4fa7..a60f47b49231 100644 --- a/include/dt-bindings/clock/meson8b-clkc.h +++ b/include/dt-bindings/clock/meson8b-clkc.h @@ -102,5 +102,6 @@ #define CLKID_MPLL0 93 #define CLKID_MPLL1 94 #define CLKID_MPLL2 95 +#define CLKID_NAND_CLK 112 #endif /* __MESON8B_CLKC_H */ diff --git a/include/dt-bindings/clock/r8a77470-cpg-mssr.h b/include/dt-bindings/clock/r8a77470-cpg-mssr.h new file mode 100644 index 000000000000..34cba49d0f84 --- /dev/null +++ b/include/dt-bindings/clock/r8a77470-cpg-mssr.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R8A77470_CPG_MSSR_H__ +#define __DT_BINDINGS_CLOCK_R8A77470_CPG_MSSR_H__ + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +/* r8a77470 CPG Core Clocks */ +#define R8A77470_CLK_Z2 0 +#define R8A77470_CLK_ZTR 1 +#define R8A77470_CLK_ZTRD2 2 +#define R8A77470_CLK_ZT 3 +#define R8A77470_CLK_ZX 4 +#define R8A77470_CLK_ZS 5 +#define R8A77470_CLK_HP 6 +#define R8A77470_CLK_B 7 +#define R8A77470_CLK_LB 8 +#define R8A77470_CLK_P 9 +#define R8A77470_CLK_CL 10 +#define R8A77470_CLK_CP 11 +#define R8A77470_CLK_M2 12 +#define R8A77470_CLK_ZB3 13 +#define R8A77470_CLK_SDH 14 +#define R8A77470_CLK_SD0 15 +#define R8A77470_CLK_SD1 16 +#define R8A77470_CLK_SD2 17 +#define R8A77470_CLK_MP 18 +#define R8A77470_CLK_QSPI 19 +#define R8A77470_CLK_CPEX 20 +#define R8A77470_CLK_RCAN 21 +#define R8A77470_CLK_R 22 +#define R8A77470_CLK_OSC 23 + +#endif /* __DT_BINDINGS_CLOCK_R8A77470_CPG_MSSR_H__ */ diff --git a/include/dt-bindings/clock/r8a77990-cpg-mssr.h b/include/dt-bindings/clock/r8a77990-cpg-mssr.h new file mode 100644 index 000000000000..a596a482f3a9 --- /dev/null +++ b/include/dt-bindings/clock/r8a77990-cpg-mssr.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R8A77990_CPG_MSSR_H__ +#define __DT_BINDINGS_CLOCK_R8A77990_CPG_MSSR_H__ + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +/* r8a77990 CPG Core Clocks */ +#define R8A77990_CLK_Z2 0 +#define R8A77990_CLK_ZR 1 +#define R8A77990_CLK_ZG 2 +#define R8A77990_CLK_ZTR 3 +#define R8A77990_CLK_ZT 4 +#define R8A77990_CLK_ZX 5 +#define R8A77990_CLK_S0D1 6 +#define R8A77990_CLK_S0D3 7 +#define R8A77990_CLK_S0D6 8 +#define R8A77990_CLK_S0D12 9 +#define R8A77990_CLK_S0D24 10 +#define R8A77990_CLK_S1D1 11 +#define R8A77990_CLK_S1D2 12 +#define R8A77990_CLK_S1D4 13 +#define R8A77990_CLK_S2D1 14 +#define R8A77990_CLK_S2D2 15 +#define R8A77990_CLK_S2D4 16 +#define R8A77990_CLK_S3D1 17 +#define R8A77990_CLK_S3D2 18 +#define R8A77990_CLK_S3D4 19 +#define R8A77990_CLK_S0D6C 20 +#define R8A77990_CLK_S3D1C 21 +#define R8A77990_CLK_S3D2C 22 +#define R8A77990_CLK_S3D4C 23 +#define R8A77990_CLK_LB 24 +#define R8A77990_CLK_CL 25 +#define R8A77990_CLK_ZB3 26 +#define R8A77990_CLK_ZB3D2 27 +#define R8A77990_CLK_CR 28 +#define R8A77990_CLK_CRD2 29 +#define R8A77990_CLK_SD0H 30 +#define R8A77990_CLK_SD0 31 +#define R8A77990_CLK_SD1H 32 +#define R8A77990_CLK_SD1 33 +#define R8A77990_CLK_SD3H 34 +#define R8A77990_CLK_SD3 35 +#define R8A77990_CLK_RPC 36 +#define R8A77990_CLK_RPCD2 37 +#define R8A77990_CLK_ZA2 38 +#define R8A77990_CLK_ZA8 39 +#define R8A77990_CLK_Z2D 40 +#define R8A77990_CLK_CANFD 41 +#define R8A77990_CLK_MSO 42 +#define R8A77990_CLK_R 43 +#define R8A77990_CLK_OSC 44 +#define R8A77990_CLK_LV0 45 +#define R8A77990_CLK_LV1 46 +#define R8A77990_CLK_CSI0 47 +#define R8A77990_CLK_CP 48 +#define R8A77990_CLK_CPEX 49 + +#endif /* __DT_BINDINGS_CLOCK_R8A77990_CPG_MSSR_H__ */ diff --git a/include/dt-bindings/reset/axg-aoclkc.h b/include/dt-bindings/reset/axg-aoclkc.h new file mode 100644 index 000000000000..d342c0b6b2a7 --- /dev/null +++ b/include/dt-bindings/reset/axg-aoclkc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (c) 2016 BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Qiufang Dai <qiufang.dai@amlogic.com> + */ + +#ifndef DT_BINDINGS_RESET_AMLOGIC_MESON_AXG_AOCLK +#define DT_BINDINGS_RESET_AMLOGIC_MESON_AXG_AOCLK + +#define RESET_AO_REMOTE 0 +#define RESET_AO_I2C_MASTER 1 +#define RESET_AO_I2C_SLAVE 2 +#define RESET_AO_UART1 3 +#define RESET_AO_UART2 4 +#define RESET_AO_IR_BLASTER 5 + +#endif diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h new file mode 100644 index 000000000000..8a7b5cd7eac0 --- /dev/null +++ b/include/linux/clk/davinci.h @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Clock drivers for TI DaVinci PLL and PSC controllers + * + * Copyright (C) 2018 David Lechner <david@lechnology.com> + */ + +#ifndef __LINUX_CLK_DAVINCI_PLL_H___ +#define __LINUX_CLK_DAVINCI_PLL_H___ + +#include <linux/device.h> +#include <linux/regmap.h> + +/* function for registering clocks in early boot */ + +#ifdef CONFIG_ARCH_DAVINCI_DA830 +int da830_pll_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DA850 +int da850_pll0_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM355 +int dm355_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +int dm355_psc_init(struct device *dev, void __iomem *base); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM365 +int dm365_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +int dm365_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +int dm365_psc_init(struct device *dev, void __iomem *base); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM644x +int dm644x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +int dm644x_psc_init(struct device *dev, void __iomem *base); +#endif +#ifdef CONFIG_ARCH_DAVINCI_DM646x +int dm646x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip); +int dm646x_psc_init(struct device *dev, void __iomem *base); +#endif + +#endif /* __LINUX_CLK_DAVINCI_PLL_H___ */ |