xref: /openbmc/linux/drivers/clk/davinci/pll.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
12d172691SDavid Lechner // SPDX-License-Identifier: GPL-2.0
22d172691SDavid Lechner /*
32d172691SDavid Lechner  * PLL clock driver for TI Davinci SoCs
42d172691SDavid Lechner  *
52d172691SDavid Lechner  * Copyright (C) 2018 David Lechner <david@lechnology.com>
62d172691SDavid Lechner  *
72d172691SDavid Lechner  * Based on arch/arm/mach-davinci/clock.c
82d172691SDavid Lechner  * Copyright (C) 2006-2007 Texas Instruments.
92d172691SDavid Lechner  * Copyright (C) 2008-2009 Deep Root Systems, LLC
102d172691SDavid Lechner  */
112d172691SDavid Lechner 
122d172691SDavid Lechner #include <linux/clk-provider.h>
132d172691SDavid Lechner #include <linux/clk.h>
1476c9dd9dSDavid Lechner #include <linux/clk/davinci.h>
152d172691SDavid Lechner #include <linux/delay.h>
162d172691SDavid Lechner #include <linux/err.h>
172d172691SDavid Lechner #include <linux/io.h>
182d172691SDavid Lechner #include <linux/kernel.h>
192d172691SDavid Lechner #include <linux/mfd/syscon.h>
202d172691SDavid Lechner #include <linux/notifier.h>
212d172691SDavid Lechner #include <linux/of_address.h>
222d172691SDavid Lechner #include <linux/of_device.h>
232d172691SDavid Lechner #include <linux/of.h>
242d172691SDavid Lechner #include <linux/platform_data/clk-davinci-pll.h>
252d172691SDavid Lechner #include <linux/platform_device.h>
262d172691SDavid Lechner #include <linux/regmap.h>
272d172691SDavid Lechner #include <linux/slab.h>
282d172691SDavid Lechner #include <linux/types.h>
292d172691SDavid Lechner 
302d172691SDavid Lechner #include "pll.h"
312d172691SDavid Lechner 
322d172691SDavid Lechner #define MAX_NAME_SIZE	20
332d172691SDavid Lechner #define OSCIN_CLK_NAME	"oscin"
342d172691SDavid Lechner 
352d172691SDavid Lechner #define REVID		0x000
362d172691SDavid Lechner #define PLLCTL		0x100
372d172691SDavid Lechner #define OCSEL		0x104
382d172691SDavid Lechner #define PLLSECCTL	0x108
392d172691SDavid Lechner #define PLLM		0x110
402d172691SDavid Lechner #define PREDIV		0x114
412d172691SDavid Lechner #define PLLDIV1		0x118
422d172691SDavid Lechner #define PLLDIV2		0x11c
432d172691SDavid Lechner #define PLLDIV3		0x120
442d172691SDavid Lechner #define OSCDIV		0x124
452d172691SDavid Lechner #define POSTDIV		0x128
462d172691SDavid Lechner #define BPDIV		0x12c
472d172691SDavid Lechner #define PLLCMD		0x138
482d172691SDavid Lechner #define PLLSTAT		0x13c
492d172691SDavid Lechner #define ALNCTL		0x140
502d172691SDavid Lechner #define DCHANGE		0x144
512d172691SDavid Lechner #define CKEN		0x148
522d172691SDavid Lechner #define CKSTAT		0x14c
532d172691SDavid Lechner #define SYSTAT		0x150
542d172691SDavid Lechner #define PLLDIV4		0x160
552d172691SDavid Lechner #define PLLDIV5		0x164
562d172691SDavid Lechner #define PLLDIV6		0x168
572d172691SDavid Lechner #define PLLDIV7		0x16c
582d172691SDavid Lechner #define PLLDIV8		0x170
592d172691SDavid Lechner #define PLLDIV9		0x174
602d172691SDavid Lechner 
612d172691SDavid Lechner #define PLLCTL_PLLEN		BIT(0)
622d172691SDavid Lechner #define PLLCTL_PLLPWRDN		BIT(1)
632d172691SDavid Lechner #define PLLCTL_PLLRST		BIT(3)
642d172691SDavid Lechner #define PLLCTL_PLLDIS		BIT(4)
652d172691SDavid Lechner #define PLLCTL_PLLENSRC		BIT(5)
662d172691SDavid Lechner #define PLLCTL_CLKMODE		BIT(8)
672d172691SDavid Lechner 
682d172691SDavid Lechner /* shared by most *DIV registers */
692d172691SDavid Lechner #define DIV_RATIO_SHIFT		0
702d172691SDavid Lechner #define DIV_RATIO_WIDTH		5
712d172691SDavid Lechner #define DIV_ENABLE_SHIFT	15
722d172691SDavid Lechner 
732d172691SDavid Lechner #define PLLCMD_GOSET		BIT(0)
742d172691SDavid Lechner #define PLLSTAT_GOSTAT		BIT(0)
752d172691SDavid Lechner 
762d172691SDavid Lechner #define CKEN_OBSCLK_SHIFT	1
772d172691SDavid Lechner #define CKEN_AUXEN_SHIFT	0
782d172691SDavid Lechner 
792d172691SDavid Lechner /*
802d172691SDavid Lechner  * OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN
812d172691SDavid Lechner  * cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us
822d172691SDavid Lechner  * ensures we are good for all > 4MHz OSCIN/CLKIN inputs. Typically the input
832d172691SDavid Lechner  * is ~25MHz. Units are micro seconds.
842d172691SDavid Lechner  */
852d172691SDavid Lechner #define PLL_BYPASS_TIME		1
862d172691SDavid Lechner 
872d172691SDavid Lechner /* From OMAP-L138 datasheet table 6-4. Units are micro seconds */
882d172691SDavid Lechner #define PLL_RESET_TIME		1
892d172691SDavid Lechner 
902d172691SDavid Lechner /*
912d172691SDavid Lechner  * From OMAP-L138 datasheet table 6-4; assuming prediv = 1, sqrt(pllm) = 4
922d172691SDavid Lechner  * Units are micro seconds.
932d172691SDavid Lechner  */
942d172691SDavid Lechner #define PLL_LOCK_TIME		20
952d172691SDavid Lechner 
962d172691SDavid Lechner /**
972d172691SDavid Lechner  * struct davinci_pll_clk - Main PLL clock (aka PLLOUT)
982d172691SDavid Lechner  * @hw: clk_hw for the pll
992d172691SDavid Lechner  * @base: Base memory address
1002d172691SDavid Lechner  * @pllm_min: The minimum allowable PLLM[PLLM] value
101*225bb791SJiangshan Yi  * @pllm_max: The maximum allowable PLLM[PLLM] value
1022d172691SDavid Lechner  * @pllm_mask: Bitmask for PLLM[PLLM] value
1032d172691SDavid Lechner  */
1042d172691SDavid Lechner struct davinci_pll_clk {
1052d172691SDavid Lechner 	struct clk_hw hw;
1062d172691SDavid Lechner 	void __iomem *base;
1072d172691SDavid Lechner 	u32 pllm_min;
1082d172691SDavid Lechner 	u32 pllm_max;
1092d172691SDavid Lechner 	u32 pllm_mask;
1102d172691SDavid Lechner };
1112d172691SDavid Lechner 
1122d172691SDavid Lechner #define to_davinci_pll_clk(_hw) \
1132d172691SDavid Lechner 	container_of((_hw), struct davinci_pll_clk, hw)
1142d172691SDavid Lechner 
davinci_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)1152d172691SDavid Lechner static unsigned long davinci_pll_recalc_rate(struct clk_hw *hw,
1162d172691SDavid Lechner 					     unsigned long parent_rate)
1172d172691SDavid Lechner {
1182d172691SDavid Lechner 	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
1192d172691SDavid Lechner 	unsigned long rate = parent_rate;
1202d172691SDavid Lechner 	u32 mult;
1212d172691SDavid Lechner 
1222d172691SDavid Lechner 	mult = readl(pll->base + PLLM) & pll->pllm_mask;
1232d172691SDavid Lechner 	rate *= mult + 1;
1242d172691SDavid Lechner 
1252d172691SDavid Lechner 	return rate;
1262d172691SDavid Lechner }
1272d172691SDavid Lechner 
davinci_pll_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)1282d172691SDavid Lechner static int davinci_pll_determine_rate(struct clk_hw *hw,
1292d172691SDavid Lechner 				      struct clk_rate_request *req)
1302d172691SDavid Lechner {
1312d172691SDavid Lechner 	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
1322d172691SDavid Lechner 	struct clk_hw *parent = req->best_parent_hw;
1332d172691SDavid Lechner 	unsigned long parent_rate = req->best_parent_rate;
1342d172691SDavid Lechner 	unsigned long rate = req->rate;
1352d172691SDavid Lechner 	unsigned long best_rate, r;
1362d172691SDavid Lechner 	u32 mult;
1372d172691SDavid Lechner 
1382d172691SDavid Lechner 	/* there is a limited range of valid outputs (see datasheet) */
1392d172691SDavid Lechner 	if (rate < req->min_rate)
1402d172691SDavid Lechner 		return -EINVAL;
1412d172691SDavid Lechner 
1422d172691SDavid Lechner 	rate = min(rate, req->max_rate);
1432d172691SDavid Lechner 	mult = rate / parent_rate;
1442d172691SDavid Lechner 	best_rate = parent_rate * mult;
1452d172691SDavid Lechner 
1462d172691SDavid Lechner 	/* easy case when there is no PREDIV */
1472d172691SDavid Lechner 	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
1482d172691SDavid Lechner 		if (best_rate < req->min_rate)
1492d172691SDavid Lechner 			return -EINVAL;
1502d172691SDavid Lechner 
1512d172691SDavid Lechner 		if (mult < pll->pllm_min || mult > pll->pllm_max)
1522d172691SDavid Lechner 			return -EINVAL;
1532d172691SDavid Lechner 
1542d172691SDavid Lechner 		req->rate = best_rate;
1552d172691SDavid Lechner 
1562d172691SDavid Lechner 		return 0;
1572d172691SDavid Lechner 	}
1582d172691SDavid Lechner 
1592d172691SDavid Lechner 	/* see if the PREDIV clock can help us */
1602d172691SDavid Lechner 	best_rate = 0;
1612d172691SDavid Lechner 
1622d172691SDavid Lechner 	for (mult = pll->pllm_min; mult <= pll->pllm_max; mult++) {
1632d172691SDavid Lechner 		parent_rate = clk_hw_round_rate(parent, rate / mult);
1642d172691SDavid Lechner 		r = parent_rate * mult;
1652d172691SDavid Lechner 		if (r < req->min_rate)
1662d172691SDavid Lechner 			continue;
1672d172691SDavid Lechner 		if (r > rate || r > req->max_rate)
1682d172691SDavid Lechner 			break;
1692d172691SDavid Lechner 		if (r > best_rate) {
1702d172691SDavid Lechner 			best_rate = r;
1712d172691SDavid Lechner 			req->rate = best_rate;
1722d172691SDavid Lechner 			req->best_parent_rate = parent_rate;
1732d172691SDavid Lechner 			if (best_rate == rate)
1742d172691SDavid Lechner 				break;
1752d172691SDavid Lechner 		}
1762d172691SDavid Lechner 	}
1772d172691SDavid Lechner 
1782d172691SDavid Lechner 	return 0;
1792d172691SDavid Lechner }
1802d172691SDavid Lechner 
davinci_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)1812d172691SDavid Lechner static int davinci_pll_set_rate(struct clk_hw *hw, unsigned long rate,
1822d172691SDavid Lechner 				unsigned long parent_rate)
1832d172691SDavid Lechner {
1842d172691SDavid Lechner 	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
1852d172691SDavid Lechner 	u32 mult;
1862d172691SDavid Lechner 
1872d172691SDavid Lechner 	mult = rate / parent_rate;
1882d172691SDavid Lechner 	writel(mult - 1, pll->base + PLLM);
1892d172691SDavid Lechner 
1902d172691SDavid Lechner 	return 0;
1912d172691SDavid Lechner }
1922d172691SDavid Lechner 
1932d172691SDavid Lechner #ifdef CONFIG_DEBUG_FS
194d75d50c0SStephen Boyd static void davinci_pll_debug_init(struct clk_hw *hw, struct dentry *dentry);
1952d172691SDavid Lechner #else
1962d172691SDavid Lechner #define davinci_pll_debug_init NULL
1972d172691SDavid Lechner #endif
1982d172691SDavid Lechner 
1992d172691SDavid Lechner static const struct clk_ops davinci_pll_ops = {
2002d172691SDavid Lechner 	.recalc_rate	= davinci_pll_recalc_rate,
2012d172691SDavid Lechner 	.determine_rate	= davinci_pll_determine_rate,
2022d172691SDavid Lechner 	.set_rate	= davinci_pll_set_rate,
2032d172691SDavid Lechner 	.debug_init	= davinci_pll_debug_init,
2042d172691SDavid Lechner };
2052d172691SDavid Lechner 
2062d172691SDavid Lechner /* PLLM works differently on DM365 */
dm365_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)2072d172691SDavid Lechner static unsigned long dm365_pll_recalc_rate(struct clk_hw *hw,
2082d172691SDavid Lechner 					   unsigned long parent_rate)
2092d172691SDavid Lechner {
2102d172691SDavid Lechner 	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
2112d172691SDavid Lechner 	unsigned long rate = parent_rate;
2122d172691SDavid Lechner 	u32 mult;
2132d172691SDavid Lechner 
2142d172691SDavid Lechner 	mult = readl(pll->base + PLLM) & pll->pllm_mask;
2152d172691SDavid Lechner 	rate *= mult * 2;
2162d172691SDavid Lechner 
2172d172691SDavid Lechner 	return rate;
2182d172691SDavid Lechner }
2192d172691SDavid Lechner 
2202d172691SDavid Lechner static const struct clk_ops dm365_pll_ops = {
2212d172691SDavid Lechner 	.recalc_rate	= dm365_pll_recalc_rate,
2222d172691SDavid Lechner 	.debug_init	= davinci_pll_debug_init,
2232d172691SDavid Lechner };
2242d172691SDavid Lechner 
2252d172691SDavid Lechner /**
2262d172691SDavid Lechner  * davinci_pll_div_register - common *DIV clock implementation
22776c9dd9dSDavid Lechner  * @dev: The PLL platform device or NULL
2282d172691SDavid Lechner  * @name: the clock name
2292d172691SDavid Lechner  * @parent_name: the parent clock name
2302d172691SDavid Lechner  * @reg: the *DIV register
2312d172691SDavid Lechner  * @fixed: if true, the divider is a fixed value
2322d172691SDavid Lechner  * @flags: bitmap of CLK_* flags from clock-provider.h
2332d172691SDavid Lechner  */
davinci_pll_div_register(struct device * dev,const char * name,const char * parent_name,void __iomem * reg,bool fixed,u32 flags)2342d172691SDavid Lechner static struct clk *davinci_pll_div_register(struct device *dev,
2352d172691SDavid Lechner 					    const char *name,
2362d172691SDavid Lechner 					    const char *parent_name,
2372d172691SDavid Lechner 					    void __iomem *reg,
2382d172691SDavid Lechner 					    bool fixed, u32 flags)
2392d172691SDavid Lechner {
2402d172691SDavid Lechner 	const char * const *parent_names = parent_name ? &parent_name : NULL;
2412d172691SDavid Lechner 	int num_parents = parent_name ? 1 : 0;
2422d172691SDavid Lechner 	const struct clk_ops *divider_ops = &clk_divider_ops;
2432d172691SDavid Lechner 	struct clk_gate *gate;
2442d172691SDavid Lechner 	struct clk_divider *divider;
24576c9dd9dSDavid Lechner 	struct clk *clk;
24676c9dd9dSDavid Lechner 	int ret;
2472d172691SDavid Lechner 
24876c9dd9dSDavid Lechner 	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
2492d172691SDavid Lechner 	if (!gate)
2502d172691SDavid Lechner 		return ERR_PTR(-ENOMEM);
2512d172691SDavid Lechner 
2522d172691SDavid Lechner 	gate->reg = reg;
2532d172691SDavid Lechner 	gate->bit_idx = DIV_ENABLE_SHIFT;
2542d172691SDavid Lechner 
25576c9dd9dSDavid Lechner 	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
25676c9dd9dSDavid Lechner 	if (!divider) {
25776c9dd9dSDavid Lechner 		ret = -ENOMEM;
25876c9dd9dSDavid Lechner 		goto err_free_gate;
25976c9dd9dSDavid Lechner 	}
2602d172691SDavid Lechner 
2612d172691SDavid Lechner 	divider->reg = reg;
2622d172691SDavid Lechner 	divider->shift = DIV_RATIO_SHIFT;
2632d172691SDavid Lechner 	divider->width = DIV_RATIO_WIDTH;
2642d172691SDavid Lechner 
2652d172691SDavid Lechner 	if (fixed) {
2662d172691SDavid Lechner 		divider->flags |= CLK_DIVIDER_READ_ONLY;
2672d172691SDavid Lechner 		divider_ops = &clk_divider_ro_ops;
2682d172691SDavid Lechner 	}
2692d172691SDavid Lechner 
27076c9dd9dSDavid Lechner 	clk = clk_register_composite(dev, name, parent_names, num_parents,
2712d172691SDavid Lechner 				     NULL, NULL, &divider->hw, divider_ops,
2722d172691SDavid Lechner 				     &gate->hw, &clk_gate_ops, flags);
27376c9dd9dSDavid Lechner 	if (IS_ERR(clk)) {
27476c9dd9dSDavid Lechner 		ret = PTR_ERR(clk);
27576c9dd9dSDavid Lechner 		goto err_free_divider;
27676c9dd9dSDavid Lechner 	}
27776c9dd9dSDavid Lechner 
27876c9dd9dSDavid Lechner 	return clk;
27976c9dd9dSDavid Lechner 
28076c9dd9dSDavid Lechner err_free_divider:
28176c9dd9dSDavid Lechner 	kfree(divider);
28276c9dd9dSDavid Lechner err_free_gate:
28376c9dd9dSDavid Lechner 	kfree(gate);
28476c9dd9dSDavid Lechner 
28576c9dd9dSDavid Lechner 	return ERR_PTR(ret);
2862d172691SDavid Lechner }
2872d172691SDavid Lechner 
2882d172691SDavid Lechner struct davinci_pllen_clk {
2892d172691SDavid Lechner 	struct clk_hw hw;
2902d172691SDavid Lechner 	void __iomem *base;
2912d172691SDavid Lechner };
2922d172691SDavid Lechner 
2932d172691SDavid Lechner #define to_davinci_pllen_clk(_hw) \
2942d172691SDavid Lechner 	container_of((_hw), struct davinci_pllen_clk, hw)
2952d172691SDavid Lechner 
2962d172691SDavid Lechner static const struct clk_ops davinci_pllen_ops = {
2972d172691SDavid Lechner 	/* this clocks just uses the clock notification feature */
2982d172691SDavid Lechner };
2992d172691SDavid Lechner 
3002d172691SDavid Lechner /*
3012d172691SDavid Lechner  * The PLL has to be switched into bypass mode while we are chaning the rate,
3022d172691SDavid Lechner  * so we do that on the PLLEN clock since it is the end of the line. This will
3032d172691SDavid Lechner  * switch to bypass before any of the parent clocks (PREDIV, PLL, POSTDIV) are
3042d172691SDavid Lechner  * changed and will switch back to the PLL after the changes have been made.
3052d172691SDavid Lechner  */
davinci_pllen_rate_change(struct notifier_block * nb,unsigned long flags,void * data)3062d172691SDavid Lechner static int davinci_pllen_rate_change(struct notifier_block *nb,
3072d172691SDavid Lechner 				     unsigned long flags, void *data)
3082d172691SDavid Lechner {
3092d172691SDavid Lechner 	struct clk_notifier_data *cnd = data;
3102d172691SDavid Lechner 	struct clk_hw *hw = __clk_get_hw(cnd->clk);
3112d172691SDavid Lechner 	struct davinci_pllen_clk *pll = to_davinci_pllen_clk(hw);
3122d172691SDavid Lechner 	u32 ctrl;
3132d172691SDavid Lechner 
3142d172691SDavid Lechner 	ctrl = readl(pll->base + PLLCTL);
3152d172691SDavid Lechner 
3162d172691SDavid Lechner 	if (flags == PRE_RATE_CHANGE) {
3172d172691SDavid Lechner 		/* Switch the PLL to bypass mode */
3182d172691SDavid Lechner 		ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
3192d172691SDavid Lechner 		writel(ctrl, pll->base + PLLCTL);
3202d172691SDavid Lechner 
3212d172691SDavid Lechner 		udelay(PLL_BYPASS_TIME);
3222d172691SDavid Lechner 
3232d172691SDavid Lechner 		/* Reset and enable PLL */
3242d172691SDavid Lechner 		ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
3252d172691SDavid Lechner 		writel(ctrl, pll->base + PLLCTL);
3262d172691SDavid Lechner 	} else {
3272d172691SDavid Lechner 		udelay(PLL_RESET_TIME);
3282d172691SDavid Lechner 
3292d172691SDavid Lechner 		/* Bring PLL out of reset */
3302d172691SDavid Lechner 		ctrl |= PLLCTL_PLLRST;
3312d172691SDavid Lechner 		writel(ctrl, pll->base + PLLCTL);
3322d172691SDavid Lechner 
3332d172691SDavid Lechner 		udelay(PLL_LOCK_TIME);
3342d172691SDavid Lechner 
3352d172691SDavid Lechner 		/* Remove PLL from bypass mode */
3362d172691SDavid Lechner 		ctrl |= PLLCTL_PLLEN;
3372d172691SDavid Lechner 		writel(ctrl, pll->base + PLLCTL);
3382d172691SDavid Lechner 	}
3392d172691SDavid Lechner 
3402d172691SDavid Lechner 	return NOTIFY_OK;
3412d172691SDavid Lechner }
3422d172691SDavid Lechner 
3432d172691SDavid Lechner static struct notifier_block davinci_pllen_notifier = {
3442d172691SDavid Lechner 	.notifier_call = davinci_pllen_rate_change,
3452d172691SDavid Lechner };
3462d172691SDavid Lechner 
3472d172691SDavid Lechner /**
3482d172691SDavid Lechner  * davinci_pll_clk_register - Register a PLL clock
34976c9dd9dSDavid Lechner  * @dev: The PLL platform device or NULL
3502d172691SDavid Lechner  * @info: The device-specific clock info
3512d172691SDavid Lechner  * @parent_name: The parent clock name
3522d172691SDavid Lechner  * @base: The PLL's memory region
35376c9dd9dSDavid Lechner  * @cfgchip: CFGCHIP syscon regmap for info->unlock_reg or NULL
3542d172691SDavid Lechner  *
3552d172691SDavid Lechner  * This creates a series of clocks that represent the PLL.
3562d172691SDavid Lechner  *
3572d172691SDavid Lechner  *     OSCIN > [PREDIV >] PLL > [POSTDIV >] PLLEN
3582d172691SDavid Lechner  *
3592d172691SDavid Lechner  * - OSCIN is the parent clock (on secondary PLL, may come from primary PLL)
3602d172691SDavid Lechner  * - PREDIV and POSTDIV are optional (depends on the PLL controller)
3612d172691SDavid Lechner  * - PLL is the PLL output (aka PLLOUT)
3622d172691SDavid Lechner  * - PLLEN is the bypass multiplexer
3632d172691SDavid Lechner  *
3642d172691SDavid Lechner  * Returns: The PLLOUT clock or a negative error code.
3652d172691SDavid Lechner  */
davinci_pll_clk_register(struct device * dev,const struct davinci_pll_clk_info * info,const char * parent_name,void __iomem * base,struct regmap * cfgchip)3662d172691SDavid Lechner struct clk *davinci_pll_clk_register(struct device *dev,
3672d172691SDavid Lechner 				     const struct davinci_pll_clk_info *info,
3682d172691SDavid Lechner 				     const char *parent_name,
36976c9dd9dSDavid Lechner 				     void __iomem *base,
37076c9dd9dSDavid Lechner 				     struct regmap *cfgchip)
3712d172691SDavid Lechner {
3722d172691SDavid Lechner 	char prediv_name[MAX_NAME_SIZE];
3732d172691SDavid Lechner 	char pllout_name[MAX_NAME_SIZE];
3742d172691SDavid Lechner 	char postdiv_name[MAX_NAME_SIZE];
3752d172691SDavid Lechner 	char pllen_name[MAX_NAME_SIZE];
3762d172691SDavid Lechner 	struct clk_init_data init;
3772d172691SDavid Lechner 	struct davinci_pll_clk *pllout;
3782d172691SDavid Lechner 	struct davinci_pllen_clk *pllen;
37976c9dd9dSDavid Lechner 	struct clk *oscin_clk = NULL;
38076c9dd9dSDavid Lechner 	struct clk *prediv_clk = NULL;
38176c9dd9dSDavid Lechner 	struct clk *pllout_clk;
38276c9dd9dSDavid Lechner 	struct clk *postdiv_clk = NULL;
38376c9dd9dSDavid Lechner 	struct clk *pllen_clk;
38476c9dd9dSDavid Lechner 	int ret;
3852d172691SDavid Lechner 
3862d172691SDavid Lechner 	if (info->flags & PLL_HAS_CLKMODE) {
3872d172691SDavid Lechner 		/*
3882d172691SDavid Lechner 		 * If a PLL has PLLCTL[CLKMODE], then it is the primary PLL.
3892d172691SDavid Lechner 		 * We register a clock named "oscin" that serves as the internal
3902d172691SDavid Lechner 		 * "input clock" domain shared by both PLLs (if there are 2)
3912d172691SDavid Lechner 		 * and will be the parent clock to the AUXCLK, SYSCLKBP and
3922d172691SDavid Lechner 		 * OBSCLK domains. NB: The various TRMs use "OSCIN" to mean
3932d172691SDavid Lechner 		 * a number of different things. In this driver we use it to
3942d172691SDavid Lechner 		 * mean the signal after the PLLCTL[CLKMODE] switch.
3952d172691SDavid Lechner 		 */
39676c9dd9dSDavid Lechner 		oscin_clk = clk_register_fixed_factor(dev, OSCIN_CLK_NAME,
3972d172691SDavid Lechner 						      parent_name, 0, 1, 1);
39876c9dd9dSDavid Lechner 		if (IS_ERR(oscin_clk))
39976c9dd9dSDavid Lechner 			return oscin_clk;
4002d172691SDavid Lechner 
4012d172691SDavid Lechner 		parent_name = OSCIN_CLK_NAME;
4022d172691SDavid Lechner 	}
4032d172691SDavid Lechner 
4042d172691SDavid Lechner 	if (info->flags & PLL_HAS_PREDIV) {
4052d172691SDavid Lechner 		bool fixed = info->flags & PLL_PREDIV_FIXED_DIV;
4062d172691SDavid Lechner 		u32 flags = 0;
4072d172691SDavid Lechner 
4082d172691SDavid Lechner 		snprintf(prediv_name, MAX_NAME_SIZE, "%s_prediv", info->name);
4092d172691SDavid Lechner 
4102d172691SDavid Lechner 		if (info->flags & PLL_PREDIV_ALWAYS_ENABLED)
4112d172691SDavid Lechner 			flags |= CLK_IS_CRITICAL;
4122d172691SDavid Lechner 
4132d172691SDavid Lechner 		/* Some? DM355 chips don't correctly report the PREDIV value */
4142d172691SDavid Lechner 		if (info->flags & PLL_PREDIV_FIXED8)
41576c9dd9dSDavid Lechner 			prediv_clk = clk_register_fixed_factor(dev, prediv_name,
4162d172691SDavid Lechner 							parent_name, flags, 1, 8);
4172d172691SDavid Lechner 		else
41876c9dd9dSDavid Lechner 			prediv_clk = davinci_pll_div_register(dev, prediv_name,
4192d172691SDavid Lechner 				parent_name, base + PREDIV, fixed, flags);
42076c9dd9dSDavid Lechner 		if (IS_ERR(prediv_clk)) {
42176c9dd9dSDavid Lechner 			ret = PTR_ERR(prediv_clk);
42276c9dd9dSDavid Lechner 			goto err_unregister_oscin;
42376c9dd9dSDavid Lechner 		}
4242d172691SDavid Lechner 
4252d172691SDavid Lechner 		parent_name = prediv_name;
4262d172691SDavid Lechner 	}
4272d172691SDavid Lechner 
4282d172691SDavid Lechner 	/* Unlock writing to PLL registers */
4292d172691SDavid Lechner 	if (info->unlock_reg) {
43076c9dd9dSDavid Lechner 		if (IS_ERR_OR_NULL(cfgchip))
4312d172691SDavid Lechner 			dev_warn(dev, "Failed to get CFGCHIP (%ld)\n",
43276c9dd9dSDavid Lechner 				 PTR_ERR(cfgchip));
4332d172691SDavid Lechner 		else
43476c9dd9dSDavid Lechner 			regmap_write_bits(cfgchip, info->unlock_reg,
4352d172691SDavid Lechner 					  info->unlock_mask, 0);
4362d172691SDavid Lechner 	}
4372d172691SDavid Lechner 
43876c9dd9dSDavid Lechner 	pllout = kzalloc(sizeof(*pllout), GFP_KERNEL);
43976c9dd9dSDavid Lechner 	if (!pllout) {
44076c9dd9dSDavid Lechner 		ret = -ENOMEM;
44176c9dd9dSDavid Lechner 		goto err_unregister_prediv;
44276c9dd9dSDavid Lechner 	}
4432d172691SDavid Lechner 
4442d172691SDavid Lechner 	snprintf(pllout_name, MAX_NAME_SIZE, "%s_pllout", info->name);
4452d172691SDavid Lechner 
4462d172691SDavid Lechner 	init.name = pllout_name;
4472d172691SDavid Lechner 	if (info->flags & PLL_PLLM_2X)
4482d172691SDavid Lechner 		init.ops = &dm365_pll_ops;
4492d172691SDavid Lechner 	else
4502d172691SDavid Lechner 		init.ops = &davinci_pll_ops;
4512d172691SDavid Lechner 	init.parent_names = &parent_name;
4522d172691SDavid Lechner 	init.num_parents = 1;
4532d172691SDavid Lechner 	init.flags = 0;
4542d172691SDavid Lechner 
4552d172691SDavid Lechner 	if (info->flags & PLL_HAS_PREDIV)
4562d172691SDavid Lechner 		init.flags |= CLK_SET_RATE_PARENT;
4572d172691SDavid Lechner 
4582d172691SDavid Lechner 	pllout->hw.init = &init;
4592d172691SDavid Lechner 	pllout->base = base;
4602d172691SDavid Lechner 	pllout->pllm_mask = info->pllm_mask;
4612d172691SDavid Lechner 	pllout->pllm_min = info->pllm_min;
4622d172691SDavid Lechner 	pllout->pllm_max = info->pllm_max;
4632d172691SDavid Lechner 
46476c9dd9dSDavid Lechner 	pllout_clk = clk_register(dev, &pllout->hw);
46576c9dd9dSDavid Lechner 	if (IS_ERR(pllout_clk)) {
46676c9dd9dSDavid Lechner 		ret = PTR_ERR(pllout_clk);
46776c9dd9dSDavid Lechner 		goto err_free_pllout;
46876c9dd9dSDavid Lechner 	}
4692d172691SDavid Lechner 
4702d172691SDavid Lechner 	clk_hw_set_rate_range(&pllout->hw, info->pllout_min_rate,
4712d172691SDavid Lechner 			      info->pllout_max_rate);
4722d172691SDavid Lechner 
4732d172691SDavid Lechner 	parent_name = pllout_name;
4742d172691SDavid Lechner 
4752d172691SDavid Lechner 	if (info->flags & PLL_HAS_POSTDIV) {
4762d172691SDavid Lechner 		bool fixed = info->flags & PLL_POSTDIV_FIXED_DIV;
4772d172691SDavid Lechner 		u32 flags = CLK_SET_RATE_PARENT;
4782d172691SDavid Lechner 
4792d172691SDavid Lechner 		snprintf(postdiv_name, MAX_NAME_SIZE, "%s_postdiv", info->name);
4802d172691SDavid Lechner 
4812d172691SDavid Lechner 		if (info->flags & PLL_POSTDIV_ALWAYS_ENABLED)
4822d172691SDavid Lechner 			flags |= CLK_IS_CRITICAL;
4832d172691SDavid Lechner 
48476c9dd9dSDavid Lechner 		postdiv_clk = davinci_pll_div_register(dev, postdiv_name,
48576c9dd9dSDavid Lechner 				parent_name, base + POSTDIV, fixed, flags);
48676c9dd9dSDavid Lechner 		if (IS_ERR(postdiv_clk)) {
48776c9dd9dSDavid Lechner 			ret = PTR_ERR(postdiv_clk);
48876c9dd9dSDavid Lechner 			goto err_unregister_pllout;
48976c9dd9dSDavid Lechner 		}
4902d172691SDavid Lechner 
4912d172691SDavid Lechner 		parent_name = postdiv_name;
4922d172691SDavid Lechner 	}
4932d172691SDavid Lechner 
4943dabfa2bSChristophe JAILLET 	pllen = kzalloc(sizeof(*pllen), GFP_KERNEL);
49576c9dd9dSDavid Lechner 	if (!pllen) {
49676c9dd9dSDavid Lechner 		ret = -ENOMEM;
49776c9dd9dSDavid Lechner 		goto err_unregister_postdiv;
49876c9dd9dSDavid Lechner 	}
4992d172691SDavid Lechner 
5002d172691SDavid Lechner 	snprintf(pllen_name, MAX_NAME_SIZE, "%s_pllen", info->name);
5012d172691SDavid Lechner 
5022d172691SDavid Lechner 	init.name = pllen_name;
5032d172691SDavid Lechner 	init.ops = &davinci_pllen_ops;
5042d172691SDavid Lechner 	init.parent_names = &parent_name;
5052d172691SDavid Lechner 	init.num_parents = 1;
5062d172691SDavid Lechner 	init.flags = CLK_SET_RATE_PARENT;
5072d172691SDavid Lechner 
5082d172691SDavid Lechner 	pllen->hw.init = &init;
5092d172691SDavid Lechner 	pllen->base = base;
5102d172691SDavid Lechner 
51176c9dd9dSDavid Lechner 	pllen_clk = clk_register(dev, &pllen->hw);
51276c9dd9dSDavid Lechner 	if (IS_ERR(pllen_clk)) {
51376c9dd9dSDavid Lechner 		ret = PTR_ERR(pllen_clk);
51476c9dd9dSDavid Lechner 		goto err_free_pllen;
51576c9dd9dSDavid Lechner 	}
5162d172691SDavid Lechner 
51776c9dd9dSDavid Lechner 	clk_notifier_register(pllen_clk, &davinci_pllen_notifier);
5182d172691SDavid Lechner 
5192d172691SDavid Lechner 	return pllout_clk;
52076c9dd9dSDavid Lechner 
52176c9dd9dSDavid Lechner err_free_pllen:
52276c9dd9dSDavid Lechner 	kfree(pllen);
52376c9dd9dSDavid Lechner err_unregister_postdiv:
52476c9dd9dSDavid Lechner 	clk_unregister(postdiv_clk);
52576c9dd9dSDavid Lechner err_unregister_pllout:
52676c9dd9dSDavid Lechner 	clk_unregister(pllout_clk);
52776c9dd9dSDavid Lechner err_free_pllout:
52876c9dd9dSDavid Lechner 	kfree(pllout);
52976c9dd9dSDavid Lechner err_unregister_prediv:
53076c9dd9dSDavid Lechner 	clk_unregister(prediv_clk);
53176c9dd9dSDavid Lechner err_unregister_oscin:
53276c9dd9dSDavid Lechner 	clk_unregister(oscin_clk);
53376c9dd9dSDavid Lechner 
53476c9dd9dSDavid Lechner 	return ERR_PTR(ret);
5352d172691SDavid Lechner }
5362d172691SDavid Lechner 
5372d172691SDavid Lechner /**
5382d172691SDavid Lechner  * davinci_pll_auxclk_register - Register bypass clock (AUXCLK)
53976c9dd9dSDavid Lechner  * @dev: The PLL platform device or NULL
5402d172691SDavid Lechner  * @name: The clock name
5412d172691SDavid Lechner  * @base: The PLL memory region
5422d172691SDavid Lechner  */
davinci_pll_auxclk_register(struct device * dev,const char * name,void __iomem * base)5432d172691SDavid Lechner struct clk *davinci_pll_auxclk_register(struct device *dev,
5442d172691SDavid Lechner 					const char *name,
5452d172691SDavid Lechner 					void __iomem *base)
5462d172691SDavid Lechner {
5472d172691SDavid Lechner 	return clk_register_gate(dev, name, OSCIN_CLK_NAME, 0, base + CKEN,
5482d172691SDavid Lechner 				 CKEN_AUXEN_SHIFT, 0, NULL);
5492d172691SDavid Lechner }
5502d172691SDavid Lechner 
5512d172691SDavid Lechner /**
5522d172691SDavid Lechner  * davinci_pll_sysclkbp_clk_register - Register bypass divider clock (SYSCLKBP)
55376c9dd9dSDavid Lechner  * @dev: The PLL platform device or NULL
5542d172691SDavid Lechner  * @name: The clock name
5552d172691SDavid Lechner  * @base: The PLL memory region
5562d172691SDavid Lechner  */
davinci_pll_sysclkbp_clk_register(struct device * dev,const char * name,void __iomem * base)5572d172691SDavid Lechner struct clk *davinci_pll_sysclkbp_clk_register(struct device *dev,
5582d172691SDavid Lechner 					      const char *name,
5592d172691SDavid Lechner 					      void __iomem *base)
5602d172691SDavid Lechner {
5612d172691SDavid Lechner 	return clk_register_divider(dev, name, OSCIN_CLK_NAME, 0, base + BPDIV,
5622d172691SDavid Lechner 				    DIV_RATIO_SHIFT, DIV_RATIO_WIDTH,
5632d172691SDavid Lechner 				    CLK_DIVIDER_READ_ONLY, NULL);
5642d172691SDavid Lechner }
5652d172691SDavid Lechner 
5662d172691SDavid Lechner /**
5672d172691SDavid Lechner  * davinci_pll_obsclk_register - Register oscillator divider clock (OBSCLK)
56876c9dd9dSDavid Lechner  * @dev: The PLL platform device or NULL
5692d172691SDavid Lechner  * @info: The clock info
5702d172691SDavid Lechner  * @base: The PLL memory region
5712d172691SDavid Lechner  */
5722d172691SDavid Lechner struct clk *
davinci_pll_obsclk_register(struct device * dev,const struct davinci_pll_obsclk_info * info,void __iomem * base)5732d172691SDavid Lechner davinci_pll_obsclk_register(struct device *dev,
5742d172691SDavid Lechner 			    const struct davinci_pll_obsclk_info *info,
5752d172691SDavid Lechner 			    void __iomem *base)
5762d172691SDavid Lechner {
5772d172691SDavid Lechner 	struct clk_mux *mux;
5782d172691SDavid Lechner 	struct clk_gate *gate;
5792d172691SDavid Lechner 	struct clk_divider *divider;
58076c9dd9dSDavid Lechner 	struct clk *clk;
5812d172691SDavid Lechner 	u32 oscdiv;
58276c9dd9dSDavid Lechner 	int ret;
5832d172691SDavid Lechner 
58476c9dd9dSDavid Lechner 	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
5852d172691SDavid Lechner 	if (!mux)
5862d172691SDavid Lechner 		return ERR_PTR(-ENOMEM);
5872d172691SDavid Lechner 
5882d172691SDavid Lechner 	mux->reg = base + OCSEL;
5892d172691SDavid Lechner 	mux->table = info->table;
5902d172691SDavid Lechner 	mux->mask = info->ocsrc_mask;
5912d172691SDavid Lechner 
59276c9dd9dSDavid Lechner 	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
59376c9dd9dSDavid Lechner 	if (!gate) {
59476c9dd9dSDavid Lechner 		ret = -ENOMEM;
59576c9dd9dSDavid Lechner 		goto err_free_mux;
59676c9dd9dSDavid Lechner 	}
5972d172691SDavid Lechner 
5982d172691SDavid Lechner 	gate->reg = base + CKEN;
5992d172691SDavid Lechner 	gate->bit_idx = CKEN_OBSCLK_SHIFT;
6002d172691SDavid Lechner 
60176c9dd9dSDavid Lechner 	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
60276c9dd9dSDavid Lechner 	if (!divider) {
60376c9dd9dSDavid Lechner 		ret = -ENOMEM;
60476c9dd9dSDavid Lechner 		goto err_free_gate;
60576c9dd9dSDavid Lechner 	}
6062d172691SDavid Lechner 
6072d172691SDavid Lechner 	divider->reg = base + OSCDIV;
6082d172691SDavid Lechner 	divider->shift = DIV_RATIO_SHIFT;
6092d172691SDavid Lechner 	divider->width = DIV_RATIO_WIDTH;
6102d172691SDavid Lechner 
6112d172691SDavid Lechner 	/* make sure divider is enabled just in case bootloader disabled it */
6122d172691SDavid Lechner 	oscdiv = readl(base + OSCDIV);
6132d172691SDavid Lechner 	oscdiv |= BIT(DIV_ENABLE_SHIFT);
6142d172691SDavid Lechner 	writel(oscdiv, base + OSCDIV);
6152d172691SDavid Lechner 
61676c9dd9dSDavid Lechner 	clk = clk_register_composite(dev, info->name, info->parent_names,
6172d172691SDavid Lechner 				     info->num_parents,
6182d172691SDavid Lechner 				     &mux->hw, &clk_mux_ops,
6192d172691SDavid Lechner 				     &divider->hw, &clk_divider_ops,
6202d172691SDavid Lechner 				     &gate->hw, &clk_gate_ops, 0);
62176c9dd9dSDavid Lechner 
62276c9dd9dSDavid Lechner 	if (IS_ERR(clk)) {
62376c9dd9dSDavid Lechner 		ret = PTR_ERR(clk);
62476c9dd9dSDavid Lechner 		goto err_free_divider;
62576c9dd9dSDavid Lechner 	}
62676c9dd9dSDavid Lechner 
62776c9dd9dSDavid Lechner 	return clk;
62876c9dd9dSDavid Lechner 
62976c9dd9dSDavid Lechner err_free_divider:
63076c9dd9dSDavid Lechner 	kfree(divider);
63176c9dd9dSDavid Lechner err_free_gate:
63276c9dd9dSDavid Lechner 	kfree(gate);
63376c9dd9dSDavid Lechner err_free_mux:
63476c9dd9dSDavid Lechner 	kfree(mux);
63576c9dd9dSDavid Lechner 
63676c9dd9dSDavid Lechner 	return ERR_PTR(ret);
6372d172691SDavid Lechner }
6382d172691SDavid Lechner 
6392d172691SDavid Lechner /* The PLL SYSCLKn clocks have a mechanism for synchronizing rate changes. */
davinci_pll_sysclk_rate_change(struct notifier_block * nb,unsigned long flags,void * data)6402d172691SDavid Lechner static int davinci_pll_sysclk_rate_change(struct notifier_block *nb,
6412d172691SDavid Lechner 					  unsigned long flags, void *data)
6422d172691SDavid Lechner {
6432d172691SDavid Lechner 	struct clk_notifier_data *cnd = data;
6442d172691SDavid Lechner 	struct clk_hw *hw = __clk_get_hw(clk_get_parent(cnd->clk));
6452d172691SDavid Lechner 	struct davinci_pllen_clk *pll = to_davinci_pllen_clk(hw);
6462d172691SDavid Lechner 	u32 pllcmd, pllstat;
6472d172691SDavid Lechner 
6482d172691SDavid Lechner 	switch (flags) {
6492d172691SDavid Lechner 	case POST_RATE_CHANGE:
6502d172691SDavid Lechner 		/* apply the changes */
6512d172691SDavid Lechner 		pllcmd = readl(pll->base + PLLCMD);
6522d172691SDavid Lechner 		pllcmd |= PLLCMD_GOSET;
6532d172691SDavid Lechner 		writel(pllcmd, pll->base + PLLCMD);
6547a346a37SGustavo A. R. Silva 		fallthrough;
6552d172691SDavid Lechner 	case PRE_RATE_CHANGE:
6562d172691SDavid Lechner 		/* Wait until for outstanding changes to take effect */
6572d172691SDavid Lechner 		do {
6582d172691SDavid Lechner 			pllstat = readl(pll->base + PLLSTAT);
6592d172691SDavid Lechner 		} while (pllstat & PLLSTAT_GOSTAT);
6602d172691SDavid Lechner 		break;
6612d172691SDavid Lechner 	}
6622d172691SDavid Lechner 
6632d172691SDavid Lechner 	return NOTIFY_OK;
6642d172691SDavid Lechner }
6652d172691SDavid Lechner 
6662d172691SDavid Lechner static struct notifier_block davinci_pll_sysclk_notifier = {
6672d172691SDavid Lechner 	.notifier_call = davinci_pll_sysclk_rate_change,
6682d172691SDavid Lechner };
6692d172691SDavid Lechner 
6702d172691SDavid Lechner /**
6712d172691SDavid Lechner  * davinci_pll_sysclk_register - Register divider clocks (SYSCLKn)
67276c9dd9dSDavid Lechner  * @dev: The PLL platform device or NULL
6732d172691SDavid Lechner  * @info: The clock info
6742d172691SDavid Lechner  * @base: The PLL memory region
6752d172691SDavid Lechner  */
6762d172691SDavid Lechner struct clk *
davinci_pll_sysclk_register(struct device * dev,const struct davinci_pll_sysclk_info * info,void __iomem * base)6772d172691SDavid Lechner davinci_pll_sysclk_register(struct device *dev,
6782d172691SDavid Lechner 			    const struct davinci_pll_sysclk_info *info,
6792d172691SDavid Lechner 			    void __iomem *base)
6802d172691SDavid Lechner {
6812d172691SDavid Lechner 	const struct clk_ops *divider_ops = &clk_divider_ops;
6822d172691SDavid Lechner 	struct clk_gate *gate;
6832d172691SDavid Lechner 	struct clk_divider *divider;
6842d172691SDavid Lechner 	struct clk *clk;
6852d172691SDavid Lechner 	u32 reg;
6862d172691SDavid Lechner 	u32 flags = 0;
68776c9dd9dSDavid Lechner 	int ret;
6882d172691SDavid Lechner 
6892d172691SDavid Lechner 	/* PLLDIVn registers are not entirely consecutive */
6902d172691SDavid Lechner 	if (info->id < 4)
6912d172691SDavid Lechner 		reg = PLLDIV1 + 4 * (info->id - 1);
6922d172691SDavid Lechner 	else
6932d172691SDavid Lechner 		reg = PLLDIV4 + 4 * (info->id - 4);
6942d172691SDavid Lechner 
69576c9dd9dSDavid Lechner 	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
6962d172691SDavid Lechner 	if (!gate)
6972d172691SDavid Lechner 		return ERR_PTR(-ENOMEM);
6982d172691SDavid Lechner 
6992d172691SDavid Lechner 	gate->reg = base + reg;
7002d172691SDavid Lechner 	gate->bit_idx = DIV_ENABLE_SHIFT;
7012d172691SDavid Lechner 
70276c9dd9dSDavid Lechner 	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
70376c9dd9dSDavid Lechner 	if (!divider) {
70476c9dd9dSDavid Lechner 		ret = -ENOMEM;
70576c9dd9dSDavid Lechner 		goto err_free_gate;
70676c9dd9dSDavid Lechner 	}
7072d172691SDavid Lechner 
7082d172691SDavid Lechner 	divider->reg = base + reg;
7092d172691SDavid Lechner 	divider->shift = DIV_RATIO_SHIFT;
7102d172691SDavid Lechner 	divider->width = info->ratio_width;
7112d172691SDavid Lechner 	divider->flags = 0;
7122d172691SDavid Lechner 
7132d172691SDavid Lechner 	if (info->flags & SYSCLK_FIXED_DIV) {
7142d172691SDavid Lechner 		divider->flags |= CLK_DIVIDER_READ_ONLY;
7152d172691SDavid Lechner 		divider_ops = &clk_divider_ro_ops;
7162d172691SDavid Lechner 	}
7172d172691SDavid Lechner 
7182d172691SDavid Lechner 	/* Only the ARM clock can change the parent PLL rate */
7192d172691SDavid Lechner 	if (info->flags & SYSCLK_ARM_RATE)
7202d172691SDavid Lechner 		flags |= CLK_SET_RATE_PARENT;
7212d172691SDavid Lechner 
7222d172691SDavid Lechner 	if (info->flags & SYSCLK_ALWAYS_ENABLED)
7232d172691SDavid Lechner 		flags |= CLK_IS_CRITICAL;
7242d172691SDavid Lechner 
7252d172691SDavid Lechner 	clk = clk_register_composite(dev, info->name, &info->parent_name, 1,
7262d172691SDavid Lechner 				     NULL, NULL, &divider->hw, divider_ops,
7272d172691SDavid Lechner 				     &gate->hw, &clk_gate_ops, flags);
72876c9dd9dSDavid Lechner 	if (IS_ERR(clk)) {
72976c9dd9dSDavid Lechner 		ret = PTR_ERR(clk);
73076c9dd9dSDavid Lechner 		goto err_free_divider;
73176c9dd9dSDavid Lechner 	}
7322d172691SDavid Lechner 
7332d172691SDavid Lechner 	clk_notifier_register(clk, &davinci_pll_sysclk_notifier);
7342d172691SDavid Lechner 
7352d172691SDavid Lechner 	return clk;
73676c9dd9dSDavid Lechner 
73776c9dd9dSDavid Lechner err_free_divider:
73876c9dd9dSDavid Lechner 	kfree(divider);
73976c9dd9dSDavid Lechner err_free_gate:
74076c9dd9dSDavid Lechner 	kfree(gate);
74176c9dd9dSDavid Lechner 
74276c9dd9dSDavid Lechner 	return ERR_PTR(ret);
7432d172691SDavid Lechner }
7442d172691SDavid Lechner 
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,struct regmap * cfgchip)74576c9dd9dSDavid Lechner int of_davinci_pll_init(struct device *dev, struct device_node *node,
7462d172691SDavid Lechner 			const struct davinci_pll_clk_info *info,
7472d172691SDavid Lechner 			const struct davinci_pll_obsclk_info *obsclk_info,
7482d172691SDavid Lechner 			const struct davinci_pll_sysclk_info **div_info,
7492d172691SDavid Lechner 			u8 max_sysclk_id,
75076c9dd9dSDavid Lechner 			void __iomem *base,
75176c9dd9dSDavid Lechner 			struct regmap *cfgchip)
7522d172691SDavid Lechner {
7532d172691SDavid Lechner 	struct device_node *child;
7542d172691SDavid Lechner 	const char *parent_name;
7552d172691SDavid Lechner 	struct clk *clk;
7562d172691SDavid Lechner 
7572d172691SDavid Lechner 	if (info->flags & PLL_HAS_CLKMODE)
7582d172691SDavid Lechner 		parent_name = of_clk_get_parent_name(node, 0);
7592d172691SDavid Lechner 	else
7602d172691SDavid Lechner 		parent_name = OSCIN_CLK_NAME;
7612d172691SDavid Lechner 
76276c9dd9dSDavid Lechner 	clk = davinci_pll_clk_register(dev, info, parent_name, base, cfgchip);
7632d172691SDavid Lechner 	if (IS_ERR(clk)) {
7642d172691SDavid Lechner 		dev_err(dev, "failed to register %s\n", info->name);
7652d172691SDavid Lechner 		return PTR_ERR(clk);
7662d172691SDavid Lechner 	}
7672d172691SDavid Lechner 
7682d172691SDavid Lechner 	child = of_get_child_by_name(node, "pllout");
7692d172691SDavid Lechner 	if (of_device_is_available(child))
7702d172691SDavid Lechner 		of_clk_add_provider(child, of_clk_src_simple_get, clk);
7712d172691SDavid Lechner 	of_node_put(child);
7722d172691SDavid Lechner 
7732d172691SDavid Lechner 	child = of_get_child_by_name(node, "sysclk");
7742d172691SDavid Lechner 	if (of_device_is_available(child)) {
7752d172691SDavid Lechner 		struct clk_onecell_data *clk_data;
7762d172691SDavid Lechner 		struct clk **clks;
7772d172691SDavid Lechner 		int n_clks =  max_sysclk_id + 1;
7782d172691SDavid Lechner 		int i;
7792d172691SDavid Lechner 
78076c9dd9dSDavid Lechner 		clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
781d55841ceSNishka Dasgupta 		if (!clk_data) {
782d55841ceSNishka Dasgupta 			of_node_put(child);
7832d172691SDavid Lechner 			return -ENOMEM;
784d55841ceSNishka Dasgupta 		}
7852d172691SDavid Lechner 
78676c9dd9dSDavid Lechner 		clks = kmalloc_array(n_clks, sizeof(*clks), GFP_KERNEL);
78776c9dd9dSDavid Lechner 		if (!clks) {
78876c9dd9dSDavid Lechner 			kfree(clk_data);
789d55841ceSNishka Dasgupta 			of_node_put(child);
7902d172691SDavid Lechner 			return -ENOMEM;
79176c9dd9dSDavid Lechner 		}
7922d172691SDavid Lechner 
7932d172691SDavid Lechner 		clk_data->clks = clks;
7942d172691SDavid Lechner 		clk_data->clk_num = n_clks;
7952d172691SDavid Lechner 
7962d172691SDavid Lechner 		for (i = 0; i < n_clks; i++)
7972d172691SDavid Lechner 			clks[i] = ERR_PTR(-ENOENT);
7982d172691SDavid Lechner 
7992d172691SDavid Lechner 		for (; *div_info; div_info++) {
8002d172691SDavid Lechner 			clk = davinci_pll_sysclk_register(dev, *div_info, base);
8012d172691SDavid Lechner 			if (IS_ERR(clk))
8022d172691SDavid Lechner 				dev_warn(dev, "failed to register %s (%ld)\n",
8032d172691SDavid Lechner 					 (*div_info)->name, PTR_ERR(clk));
8042d172691SDavid Lechner 			else
8052d172691SDavid Lechner 				clks[(*div_info)->id] = clk;
8062d172691SDavid Lechner 		}
8072d172691SDavid Lechner 		of_clk_add_provider(child, of_clk_src_onecell_get, clk_data);
8082d172691SDavid Lechner 	}
8092d172691SDavid Lechner 	of_node_put(child);
8102d172691SDavid Lechner 
8112d172691SDavid Lechner 	child = of_get_child_by_name(node, "auxclk");
8122d172691SDavid Lechner 	if (of_device_is_available(child)) {
8132d172691SDavid Lechner 		char child_name[MAX_NAME_SIZE];
8142d172691SDavid Lechner 
8152d172691SDavid Lechner 		snprintf(child_name, MAX_NAME_SIZE, "%s_auxclk", info->name);
8162d172691SDavid Lechner 
8172d172691SDavid Lechner 		clk = davinci_pll_auxclk_register(dev, child_name, base);
8182d172691SDavid Lechner 		if (IS_ERR(clk))
8192d172691SDavid Lechner 			dev_warn(dev, "failed to register %s (%ld)\n",
8202d172691SDavid Lechner 				 child_name, PTR_ERR(clk));
8212d172691SDavid Lechner 		else
8222d172691SDavid Lechner 			of_clk_add_provider(child, of_clk_src_simple_get, clk);
8232d172691SDavid Lechner 	}
8242d172691SDavid Lechner 	of_node_put(child);
8252d172691SDavid Lechner 
8262d172691SDavid Lechner 	child = of_get_child_by_name(node, "obsclk");
8272d172691SDavid Lechner 	if (of_device_is_available(child)) {
8282d172691SDavid Lechner 		if (obsclk_info)
8292d172691SDavid Lechner 			clk = davinci_pll_obsclk_register(dev, obsclk_info, base);
8302d172691SDavid Lechner 		else
8312d172691SDavid Lechner 			clk = ERR_PTR(-EINVAL);
8322d172691SDavid Lechner 
8332d172691SDavid Lechner 		if (IS_ERR(clk))
8342d172691SDavid Lechner 			dev_warn(dev, "failed to register obsclk (%ld)\n",
8352d172691SDavid Lechner 				 PTR_ERR(clk));
8362d172691SDavid Lechner 		else
8372d172691SDavid Lechner 			of_clk_add_provider(child, of_clk_src_simple_get, clk);
8382d172691SDavid Lechner 	}
8392d172691SDavid Lechner 	of_node_put(child);
8402d172691SDavid Lechner 
8412d172691SDavid Lechner 	return 0;
8422d172691SDavid Lechner }
8432d172691SDavid Lechner 
davinci_pll_get_pdata(struct device * dev)84476c9dd9dSDavid Lechner static struct davinci_pll_platform_data *davinci_pll_get_pdata(struct device *dev)
84576c9dd9dSDavid Lechner {
84676c9dd9dSDavid Lechner 	struct davinci_pll_platform_data *pdata = dev_get_platdata(dev);
84776c9dd9dSDavid Lechner 
84876c9dd9dSDavid Lechner 	/*
84976c9dd9dSDavid Lechner 	 * Platform data is optional, so allocate a new struct if one was not
85076c9dd9dSDavid Lechner 	 * provided. For device tree, this will always be the case.
85176c9dd9dSDavid Lechner 	 */
85276c9dd9dSDavid Lechner 	if (!pdata)
85376c9dd9dSDavid Lechner 		pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
85476c9dd9dSDavid Lechner 	if (!pdata)
85576c9dd9dSDavid Lechner 		return NULL;
85676c9dd9dSDavid Lechner 
85776c9dd9dSDavid Lechner 	/* for device tree, we need to fill in the struct */
85876c9dd9dSDavid Lechner 	if (dev->of_node)
85976c9dd9dSDavid Lechner 		pdata->cfgchip =
86076c9dd9dSDavid Lechner 			syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");
86176c9dd9dSDavid Lechner 
86276c9dd9dSDavid Lechner 	return pdata;
86376c9dd9dSDavid Lechner }
86476c9dd9dSDavid Lechner 
86517d8bacfSDavid Lechner /* needed in early boot for clocksource/clockevent */
8664eff0bebSDavid Lechner #ifdef CONFIG_ARCH_DAVINCI_DA850
86717d8bacfSDavid Lechner CLK_OF_DECLARE(da850_pll0, "ti,da850-pll0", of_da850_pll0_init);
8684eff0bebSDavid Lechner #endif
86917d8bacfSDavid Lechner 
8702d172691SDavid Lechner static const struct of_device_id davinci_pll_of_match[] = {
8714eff0bebSDavid Lechner #ifdef CONFIG_ARCH_DAVINCI_DA850
87255b3caedSDavid Lechner 	{ .compatible = "ti,da850-pll1", .data = of_da850_pll1_init },
8734eff0bebSDavid Lechner #endif
8742d172691SDavid Lechner 	{ }
8752d172691SDavid Lechner };
8762d172691SDavid Lechner 
8772d172691SDavid Lechner static const struct platform_device_id davinci_pll_id_table[] = {
8784eff0bebSDavid Lechner #ifdef CONFIG_ARCH_DAVINCI_DA830
879c92765fdSDavid Lechner 	{ .name = "da830-pll",   .driver_data = (kernel_ulong_t)da830_pll_init   },
8804eff0bebSDavid Lechner #endif
8814eff0bebSDavid Lechner #ifdef CONFIG_ARCH_DAVINCI_DA850
88255b3caedSDavid Lechner 	{ .name = "da850-pll0",  .driver_data = (kernel_ulong_t)da850_pll0_init  },
88355b3caedSDavid Lechner 	{ .name = "da850-pll1",  .driver_data = (kernel_ulong_t)da850_pll1_init  },
8844eff0bebSDavid Lechner #endif
8852d172691SDavid Lechner 	{ }
8862d172691SDavid Lechner };
8872d172691SDavid Lechner 
88876c9dd9dSDavid Lechner typedef int (*davinci_pll_init)(struct device *dev, void __iomem *base,
88976c9dd9dSDavid Lechner 				struct regmap *cfgchip);
8902d172691SDavid Lechner 
davinci_pll_probe(struct platform_device * pdev)8912d172691SDavid Lechner static int davinci_pll_probe(struct platform_device *pdev)
8922d172691SDavid Lechner {
8932d172691SDavid Lechner 	struct device *dev = &pdev->dev;
89476c9dd9dSDavid Lechner 	struct davinci_pll_platform_data *pdata;
8952d172691SDavid Lechner 	const struct of_device_id *of_id;
8962d172691SDavid Lechner 	davinci_pll_init pll_init = NULL;
8972d172691SDavid Lechner 	void __iomem *base;
8982d172691SDavid Lechner 
8992d172691SDavid Lechner 	of_id = of_match_device(davinci_pll_of_match, dev);
9002d172691SDavid Lechner 	if (of_id)
9012d172691SDavid Lechner 		pll_init = of_id->data;
9022d172691SDavid Lechner 	else if (pdev->id_entry)
9032d172691SDavid Lechner 		pll_init = (void *)pdev->id_entry->driver_data;
9042d172691SDavid Lechner 
9052d172691SDavid Lechner 	if (!pll_init) {
9062d172691SDavid Lechner 		dev_err(dev, "unable to find driver data\n");
9072d172691SDavid Lechner 		return -EINVAL;
9082d172691SDavid Lechner 	}
9092d172691SDavid Lechner 
91076c9dd9dSDavid Lechner 	pdata = davinci_pll_get_pdata(dev);
91176c9dd9dSDavid Lechner 	if (!pdata) {
91276c9dd9dSDavid Lechner 		dev_err(dev, "missing platform data\n");
91376c9dd9dSDavid Lechner 		return -EINVAL;
91476c9dd9dSDavid Lechner 	}
91576c9dd9dSDavid Lechner 
9161f8f3c6bSYueHaibing 	base = devm_platform_ioremap_resource(pdev, 0);
917fc3fcb4fSWei Yongjun 	if (IS_ERR(base))
9182d172691SDavid Lechner 		return PTR_ERR(base);
9192d172691SDavid Lechner 
92076c9dd9dSDavid Lechner 	return pll_init(dev, base, pdata->cfgchip);
9212d172691SDavid Lechner }
9222d172691SDavid Lechner 
9232d172691SDavid Lechner static struct platform_driver davinci_pll_driver = {
9242d172691SDavid Lechner 	.probe		= davinci_pll_probe,
9252d172691SDavid Lechner 	.driver		= {
9262d172691SDavid Lechner 		.name		= "davinci-pll-clk",
9272d172691SDavid Lechner 		.of_match_table	= davinci_pll_of_match,
9282d172691SDavid Lechner 	},
9292d172691SDavid Lechner 	.id_table	= davinci_pll_id_table,
9302d172691SDavid Lechner };
9312d172691SDavid Lechner 
davinci_pll_driver_init(void)9322d172691SDavid Lechner static int __init davinci_pll_driver_init(void)
9332d172691SDavid Lechner {
9342d172691SDavid Lechner 	return platform_driver_register(&davinci_pll_driver);
9352d172691SDavid Lechner }
9362d172691SDavid Lechner 
9372d172691SDavid Lechner /* has to be postcore_initcall because PSC devices depend on PLL parent clocks */
9382d172691SDavid Lechner postcore_initcall(davinci_pll_driver_init);
9392d172691SDavid Lechner 
9402d172691SDavid Lechner #ifdef CONFIG_DEBUG_FS
9412d172691SDavid Lechner #include <linux/debugfs.h>
9422d172691SDavid Lechner 
9432d172691SDavid Lechner #define DEBUG_REG(n)	\
9442d172691SDavid Lechner {			\
9452d172691SDavid Lechner 	.name	= #n,	\
9462d172691SDavid Lechner 	.offset	= n,	\
9472d172691SDavid Lechner }
9482d172691SDavid Lechner 
9492d172691SDavid Lechner static const struct debugfs_reg32 davinci_pll_regs[] = {
9502d172691SDavid Lechner 	DEBUG_REG(REVID),
9512d172691SDavid Lechner 	DEBUG_REG(PLLCTL),
9522d172691SDavid Lechner 	DEBUG_REG(OCSEL),
9532d172691SDavid Lechner 	DEBUG_REG(PLLSECCTL),
9542d172691SDavid Lechner 	DEBUG_REG(PLLM),
9552d172691SDavid Lechner 	DEBUG_REG(PREDIV),
9562d172691SDavid Lechner 	DEBUG_REG(PLLDIV1),
9572d172691SDavid Lechner 	DEBUG_REG(PLLDIV2),
9582d172691SDavid Lechner 	DEBUG_REG(PLLDIV3),
9592d172691SDavid Lechner 	DEBUG_REG(OSCDIV),
9602d172691SDavid Lechner 	DEBUG_REG(POSTDIV),
9612d172691SDavid Lechner 	DEBUG_REG(BPDIV),
9622d172691SDavid Lechner 	DEBUG_REG(PLLCMD),
9632d172691SDavid Lechner 	DEBUG_REG(PLLSTAT),
9642d172691SDavid Lechner 	DEBUG_REG(ALNCTL),
9652d172691SDavid Lechner 	DEBUG_REG(DCHANGE),
9662d172691SDavid Lechner 	DEBUG_REG(CKEN),
9672d172691SDavid Lechner 	DEBUG_REG(CKSTAT),
9682d172691SDavid Lechner 	DEBUG_REG(SYSTAT),
9692d172691SDavid Lechner 	DEBUG_REG(PLLDIV4),
9702d172691SDavid Lechner 	DEBUG_REG(PLLDIV5),
9712d172691SDavid Lechner 	DEBUG_REG(PLLDIV6),
9722d172691SDavid Lechner 	DEBUG_REG(PLLDIV7),
9732d172691SDavid Lechner 	DEBUG_REG(PLLDIV8),
9742d172691SDavid Lechner 	DEBUG_REG(PLLDIV9),
9752d172691SDavid Lechner };
9762d172691SDavid Lechner 
davinci_pll_debug_init(struct clk_hw * hw,struct dentry * dentry)977d75d50c0SStephen Boyd static void davinci_pll_debug_init(struct clk_hw *hw, struct dentry *dentry)
9782d172691SDavid Lechner {
9792d172691SDavid Lechner 	struct davinci_pll_clk *pll = to_davinci_pll_clk(hw);
9802d172691SDavid Lechner 	struct debugfs_regset32 *regset;
9812d172691SDavid Lechner 
9822d172691SDavid Lechner 	regset = kzalloc(sizeof(*regset), GFP_KERNEL);
9832d172691SDavid Lechner 	if (!regset)
984d75d50c0SStephen Boyd 		return;
9852d172691SDavid Lechner 
9862d172691SDavid Lechner 	regset->regs = davinci_pll_regs;
9872d172691SDavid Lechner 	regset->nregs = ARRAY_SIZE(davinci_pll_regs);
9882d172691SDavid Lechner 	regset->base = pll->base;
9892d172691SDavid Lechner 
990bcee7673SGreg Kroah-Hartman 	debugfs_create_regset32("registers", 0400, dentry, regset);
9912d172691SDavid Lechner }
9922d172691SDavid Lechner #endif
993