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> 14*76c9dd9dSDavid 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 1012d172691SDavid Lechner * @pllm_max: The maxiumum 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 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 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 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 1942d172691SDavid Lechner static int 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 */ 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 227*76c9dd9dSDavid 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 */ 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; 245*76c9dd9dSDavid Lechner struct clk *clk; 246*76c9dd9dSDavid Lechner int ret; 2472d172691SDavid Lechner 248*76c9dd9dSDavid 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 255*76c9dd9dSDavid Lechner divider = kzalloc(sizeof(*divider), GFP_KERNEL); 256*76c9dd9dSDavid Lechner if (!divider) { 257*76c9dd9dSDavid Lechner ret = -ENOMEM; 258*76c9dd9dSDavid Lechner goto err_free_gate; 259*76c9dd9dSDavid 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 270*76c9dd9dSDavid Lechner clk = clk_register_composite(dev, name, parent_names, num_parents, 2712d172691SDavid Lechner NULL, NULL, ÷r->hw, divider_ops, 2722d172691SDavid Lechner &gate->hw, &clk_gate_ops, flags); 273*76c9dd9dSDavid Lechner if (IS_ERR(clk)) { 274*76c9dd9dSDavid Lechner ret = PTR_ERR(clk); 275*76c9dd9dSDavid Lechner goto err_free_divider; 276*76c9dd9dSDavid Lechner } 277*76c9dd9dSDavid Lechner 278*76c9dd9dSDavid Lechner return clk; 279*76c9dd9dSDavid Lechner 280*76c9dd9dSDavid Lechner err_free_divider: 281*76c9dd9dSDavid Lechner kfree(divider); 282*76c9dd9dSDavid Lechner err_free_gate: 283*76c9dd9dSDavid Lechner kfree(gate); 284*76c9dd9dSDavid Lechner 285*76c9dd9dSDavid 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 */ 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 349*76c9dd9dSDavid 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 353*76c9dd9dSDavid 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 */ 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, 369*76c9dd9dSDavid Lechner void __iomem *base, 370*76c9dd9dSDavid 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; 379*76c9dd9dSDavid Lechner struct clk *oscin_clk = NULL; 380*76c9dd9dSDavid Lechner struct clk *prediv_clk = NULL; 381*76c9dd9dSDavid Lechner struct clk *pllout_clk; 382*76c9dd9dSDavid Lechner struct clk *postdiv_clk = NULL; 383*76c9dd9dSDavid Lechner struct clk *pllen_clk; 384*76c9dd9dSDavid 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 */ 396*76c9dd9dSDavid Lechner oscin_clk = clk_register_fixed_factor(dev, OSCIN_CLK_NAME, 3972d172691SDavid Lechner parent_name, 0, 1, 1); 398*76c9dd9dSDavid Lechner if (IS_ERR(oscin_clk)) 399*76c9dd9dSDavid 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) 415*76c9dd9dSDavid Lechner prediv_clk = clk_register_fixed_factor(dev, prediv_name, 4162d172691SDavid Lechner parent_name, flags, 1, 8); 4172d172691SDavid Lechner else 418*76c9dd9dSDavid Lechner prediv_clk = davinci_pll_div_register(dev, prediv_name, 4192d172691SDavid Lechner parent_name, base + PREDIV, fixed, flags); 420*76c9dd9dSDavid Lechner if (IS_ERR(prediv_clk)) { 421*76c9dd9dSDavid Lechner ret = PTR_ERR(prediv_clk); 422*76c9dd9dSDavid Lechner goto err_unregister_oscin; 423*76c9dd9dSDavid 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) { 430*76c9dd9dSDavid Lechner if (IS_ERR_OR_NULL(cfgchip)) 4312d172691SDavid Lechner dev_warn(dev, "Failed to get CFGCHIP (%ld)\n", 432*76c9dd9dSDavid Lechner PTR_ERR(cfgchip)); 4332d172691SDavid Lechner else 434*76c9dd9dSDavid Lechner regmap_write_bits(cfgchip, info->unlock_reg, 4352d172691SDavid Lechner info->unlock_mask, 0); 4362d172691SDavid Lechner } 4372d172691SDavid Lechner 438*76c9dd9dSDavid Lechner pllout = kzalloc(sizeof(*pllout), GFP_KERNEL); 439*76c9dd9dSDavid Lechner if (!pllout) { 440*76c9dd9dSDavid Lechner ret = -ENOMEM; 441*76c9dd9dSDavid Lechner goto err_unregister_prediv; 442*76c9dd9dSDavid 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 464*76c9dd9dSDavid Lechner pllout_clk = clk_register(dev, &pllout->hw); 465*76c9dd9dSDavid Lechner if (IS_ERR(pllout_clk)) { 466*76c9dd9dSDavid Lechner ret = PTR_ERR(pllout_clk); 467*76c9dd9dSDavid Lechner goto err_free_pllout; 468*76c9dd9dSDavid 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 484*76c9dd9dSDavid Lechner postdiv_clk = davinci_pll_div_register(dev, postdiv_name, 485*76c9dd9dSDavid Lechner parent_name, base + POSTDIV, fixed, flags); 486*76c9dd9dSDavid Lechner if (IS_ERR(postdiv_clk)) { 487*76c9dd9dSDavid Lechner ret = PTR_ERR(postdiv_clk); 488*76c9dd9dSDavid Lechner goto err_unregister_pllout; 489*76c9dd9dSDavid Lechner } 4902d172691SDavid Lechner 4912d172691SDavid Lechner parent_name = postdiv_name; 4922d172691SDavid Lechner } 4932d172691SDavid Lechner 494*76c9dd9dSDavid Lechner pllen = kzalloc(sizeof(*pllout), GFP_KERNEL); 495*76c9dd9dSDavid Lechner if (!pllen) { 496*76c9dd9dSDavid Lechner ret = -ENOMEM; 497*76c9dd9dSDavid Lechner goto err_unregister_postdiv; 498*76c9dd9dSDavid 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 511*76c9dd9dSDavid Lechner pllen_clk = clk_register(dev, &pllen->hw); 512*76c9dd9dSDavid Lechner if (IS_ERR(pllen_clk)) { 513*76c9dd9dSDavid Lechner ret = PTR_ERR(pllen_clk); 514*76c9dd9dSDavid Lechner goto err_free_pllen; 515*76c9dd9dSDavid Lechner } 5162d172691SDavid Lechner 517*76c9dd9dSDavid Lechner clk_notifier_register(pllen_clk, &davinci_pllen_notifier); 5182d172691SDavid Lechner 5192d172691SDavid Lechner return pllout_clk; 520*76c9dd9dSDavid Lechner 521*76c9dd9dSDavid Lechner err_free_pllen: 522*76c9dd9dSDavid Lechner kfree(pllen); 523*76c9dd9dSDavid Lechner err_unregister_postdiv: 524*76c9dd9dSDavid Lechner clk_unregister(postdiv_clk); 525*76c9dd9dSDavid Lechner err_unregister_pllout: 526*76c9dd9dSDavid Lechner clk_unregister(pllout_clk); 527*76c9dd9dSDavid Lechner err_free_pllout: 528*76c9dd9dSDavid Lechner kfree(pllout); 529*76c9dd9dSDavid Lechner err_unregister_prediv: 530*76c9dd9dSDavid Lechner clk_unregister(prediv_clk); 531*76c9dd9dSDavid Lechner err_unregister_oscin: 532*76c9dd9dSDavid Lechner clk_unregister(oscin_clk); 533*76c9dd9dSDavid Lechner 534*76c9dd9dSDavid Lechner return ERR_PTR(ret); 5352d172691SDavid Lechner } 5362d172691SDavid Lechner 5372d172691SDavid Lechner /** 5382d172691SDavid Lechner * davinci_pll_auxclk_register - Register bypass clock (AUXCLK) 539*76c9dd9dSDavid Lechner * @dev: The PLL platform device or NULL 5402d172691SDavid Lechner * @name: The clock name 5412d172691SDavid Lechner * @base: The PLL memory region 5422d172691SDavid Lechner */ 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) 553*76c9dd9dSDavid Lechner * @dev: The PLL platform device or NULL 5542d172691SDavid Lechner * @name: The clock name 5552d172691SDavid Lechner * @base: The PLL memory region 5562d172691SDavid Lechner */ 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) 568*76c9dd9dSDavid 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 * 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; 580*76c9dd9dSDavid Lechner struct clk *clk; 5812d172691SDavid Lechner u32 oscdiv; 582*76c9dd9dSDavid Lechner int ret; 5832d172691SDavid Lechner 584*76c9dd9dSDavid 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 592*76c9dd9dSDavid Lechner gate = kzalloc(sizeof(*gate), GFP_KERNEL); 593*76c9dd9dSDavid Lechner if (!gate) { 594*76c9dd9dSDavid Lechner ret = -ENOMEM; 595*76c9dd9dSDavid Lechner goto err_free_mux; 596*76c9dd9dSDavid Lechner } 5972d172691SDavid Lechner 5982d172691SDavid Lechner gate->reg = base + CKEN; 5992d172691SDavid Lechner gate->bit_idx = CKEN_OBSCLK_SHIFT; 6002d172691SDavid Lechner 601*76c9dd9dSDavid Lechner divider = kzalloc(sizeof(*divider), GFP_KERNEL); 602*76c9dd9dSDavid Lechner if (!divider) { 603*76c9dd9dSDavid Lechner ret = -ENOMEM; 604*76c9dd9dSDavid Lechner goto err_free_gate; 605*76c9dd9dSDavid 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 616*76c9dd9dSDavid 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 ÷r->hw, &clk_divider_ops, 6202d172691SDavid Lechner &gate->hw, &clk_gate_ops, 0); 621*76c9dd9dSDavid Lechner 622*76c9dd9dSDavid Lechner if (IS_ERR(clk)) { 623*76c9dd9dSDavid Lechner ret = PTR_ERR(clk); 624*76c9dd9dSDavid Lechner goto err_free_divider; 625*76c9dd9dSDavid Lechner } 626*76c9dd9dSDavid Lechner 627*76c9dd9dSDavid Lechner return clk; 628*76c9dd9dSDavid Lechner 629*76c9dd9dSDavid Lechner err_free_divider: 630*76c9dd9dSDavid Lechner kfree(divider); 631*76c9dd9dSDavid Lechner err_free_gate: 632*76c9dd9dSDavid Lechner kfree(gate); 633*76c9dd9dSDavid Lechner err_free_mux: 634*76c9dd9dSDavid Lechner kfree(mux); 635*76c9dd9dSDavid Lechner 636*76c9dd9dSDavid Lechner return ERR_PTR(ret); 6372d172691SDavid Lechner } 6382d172691SDavid Lechner 6392d172691SDavid Lechner /* The PLL SYSCLKn clocks have a mechanism for synchronizing rate changes. */ 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); 6542d172691SDavid Lechner /* 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) 672*76c9dd9dSDavid 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 * 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; 687*76c9dd9dSDavid 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 695*76c9dd9dSDavid 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 702*76c9dd9dSDavid Lechner divider = kzalloc(sizeof(*divider), GFP_KERNEL); 703*76c9dd9dSDavid Lechner if (!divider) { 704*76c9dd9dSDavid Lechner ret = -ENOMEM; 705*76c9dd9dSDavid Lechner goto err_free_gate; 706*76c9dd9dSDavid 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, ÷r->hw, divider_ops, 7272d172691SDavid Lechner &gate->hw, &clk_gate_ops, flags); 728*76c9dd9dSDavid Lechner if (IS_ERR(clk)) { 729*76c9dd9dSDavid Lechner ret = PTR_ERR(clk); 730*76c9dd9dSDavid Lechner goto err_free_divider; 731*76c9dd9dSDavid Lechner } 7322d172691SDavid Lechner 7332d172691SDavid Lechner clk_notifier_register(clk, &davinci_pll_sysclk_notifier); 7342d172691SDavid Lechner 7352d172691SDavid Lechner return clk; 736*76c9dd9dSDavid Lechner 737*76c9dd9dSDavid Lechner err_free_divider: 738*76c9dd9dSDavid Lechner kfree(divider); 739*76c9dd9dSDavid Lechner err_free_gate: 740*76c9dd9dSDavid Lechner kfree(gate); 741*76c9dd9dSDavid Lechner 742*76c9dd9dSDavid Lechner return ERR_PTR(ret); 7432d172691SDavid Lechner } 7442d172691SDavid Lechner 745*76c9dd9dSDavid 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, 750*76c9dd9dSDavid Lechner void __iomem *base, 751*76c9dd9dSDavid 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 762*76c9dd9dSDavid 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 780*76c9dd9dSDavid Lechner clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); 7812d172691SDavid Lechner if (!clk_data) 7822d172691SDavid Lechner return -ENOMEM; 7832d172691SDavid Lechner 784*76c9dd9dSDavid Lechner clks = kmalloc_array(n_clks, sizeof(*clks), GFP_KERNEL); 785*76c9dd9dSDavid Lechner if (!clks) { 786*76c9dd9dSDavid Lechner kfree(clk_data); 7872d172691SDavid Lechner return -ENOMEM; 788*76c9dd9dSDavid Lechner } 7892d172691SDavid Lechner 7902d172691SDavid Lechner clk_data->clks = clks; 7912d172691SDavid Lechner clk_data->clk_num = n_clks; 7922d172691SDavid Lechner 7932d172691SDavid Lechner for (i = 0; i < n_clks; i++) 7942d172691SDavid Lechner clks[i] = ERR_PTR(-ENOENT); 7952d172691SDavid Lechner 7962d172691SDavid Lechner for (; *div_info; div_info++) { 7972d172691SDavid Lechner clk = davinci_pll_sysclk_register(dev, *div_info, base); 7982d172691SDavid Lechner if (IS_ERR(clk)) 7992d172691SDavid Lechner dev_warn(dev, "failed to register %s (%ld)\n", 8002d172691SDavid Lechner (*div_info)->name, PTR_ERR(clk)); 8012d172691SDavid Lechner else 8022d172691SDavid Lechner clks[(*div_info)->id] = clk; 8032d172691SDavid Lechner } 8042d172691SDavid Lechner of_clk_add_provider(child, of_clk_src_onecell_get, clk_data); 8052d172691SDavid Lechner } 8062d172691SDavid Lechner of_node_put(child); 8072d172691SDavid Lechner 8082d172691SDavid Lechner child = of_get_child_by_name(node, "auxclk"); 8092d172691SDavid Lechner if (of_device_is_available(child)) { 8102d172691SDavid Lechner char child_name[MAX_NAME_SIZE]; 8112d172691SDavid Lechner 8122d172691SDavid Lechner snprintf(child_name, MAX_NAME_SIZE, "%s_auxclk", info->name); 8132d172691SDavid Lechner 8142d172691SDavid Lechner clk = davinci_pll_auxclk_register(dev, child_name, base); 8152d172691SDavid Lechner if (IS_ERR(clk)) 8162d172691SDavid Lechner dev_warn(dev, "failed to register %s (%ld)\n", 8172d172691SDavid Lechner child_name, PTR_ERR(clk)); 8182d172691SDavid Lechner else 8192d172691SDavid Lechner of_clk_add_provider(child, of_clk_src_simple_get, clk); 8202d172691SDavid Lechner } 8212d172691SDavid Lechner of_node_put(child); 8222d172691SDavid Lechner 8232d172691SDavid Lechner child = of_get_child_by_name(node, "obsclk"); 8242d172691SDavid Lechner if (of_device_is_available(child)) { 8252d172691SDavid Lechner if (obsclk_info) 8262d172691SDavid Lechner clk = davinci_pll_obsclk_register(dev, obsclk_info, base); 8272d172691SDavid Lechner else 8282d172691SDavid Lechner clk = ERR_PTR(-EINVAL); 8292d172691SDavid Lechner 8302d172691SDavid Lechner if (IS_ERR(clk)) 8312d172691SDavid Lechner dev_warn(dev, "failed to register obsclk (%ld)\n", 8322d172691SDavid Lechner PTR_ERR(clk)); 8332d172691SDavid Lechner else 8342d172691SDavid Lechner of_clk_add_provider(child, of_clk_src_simple_get, clk); 8352d172691SDavid Lechner } 8362d172691SDavid Lechner of_node_put(child); 8372d172691SDavid Lechner 8382d172691SDavid Lechner return 0; 8392d172691SDavid Lechner } 8402d172691SDavid Lechner 841*76c9dd9dSDavid Lechner static struct davinci_pll_platform_data *davinci_pll_get_pdata(struct device *dev) 842*76c9dd9dSDavid Lechner { 843*76c9dd9dSDavid Lechner struct davinci_pll_platform_data *pdata = dev_get_platdata(dev); 844*76c9dd9dSDavid Lechner 845*76c9dd9dSDavid Lechner /* 846*76c9dd9dSDavid Lechner * Platform data is optional, so allocate a new struct if one was not 847*76c9dd9dSDavid Lechner * provided. For device tree, this will always be the case. 848*76c9dd9dSDavid Lechner */ 849*76c9dd9dSDavid Lechner if (!pdata) 850*76c9dd9dSDavid Lechner pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 851*76c9dd9dSDavid Lechner if (!pdata) 852*76c9dd9dSDavid Lechner return NULL; 853*76c9dd9dSDavid Lechner 854*76c9dd9dSDavid Lechner /* for device tree, we need to fill in the struct */ 855*76c9dd9dSDavid Lechner if (dev->of_node) 856*76c9dd9dSDavid Lechner pdata->cfgchip = 857*76c9dd9dSDavid Lechner syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); 858*76c9dd9dSDavid Lechner 859*76c9dd9dSDavid Lechner return pdata; 860*76c9dd9dSDavid Lechner } 861*76c9dd9dSDavid Lechner 8622d172691SDavid Lechner static const struct of_device_id davinci_pll_of_match[] = { 86355b3caedSDavid Lechner { .compatible = "ti,da850-pll0", .data = of_da850_pll0_init }, 86455b3caedSDavid Lechner { .compatible = "ti,da850-pll1", .data = of_da850_pll1_init }, 8652d172691SDavid Lechner { } 8662d172691SDavid Lechner }; 8672d172691SDavid Lechner 8682d172691SDavid Lechner static const struct platform_device_id davinci_pll_id_table[] = { 869c92765fdSDavid Lechner { .name = "da830-pll", .driver_data = (kernel_ulong_t)da830_pll_init }, 87055b3caedSDavid Lechner { .name = "da850-pll0", .driver_data = (kernel_ulong_t)da850_pll0_init }, 87155b3caedSDavid Lechner { .name = "da850-pll1", .driver_data = (kernel_ulong_t)da850_pll1_init }, 872dcdd19b2SDavid Lechner { .name = "dm355-pll1", .driver_data = (kernel_ulong_t)dm355_pll1_init }, 873dcdd19b2SDavid Lechner { .name = "dm355-pll2", .driver_data = (kernel_ulong_t)dm355_pll2_init }, 874650bba61SDavid Lechner { .name = "dm365-pll1", .driver_data = (kernel_ulong_t)dm365_pll1_init }, 875650bba61SDavid Lechner { .name = "dm365-pll2", .driver_data = (kernel_ulong_t)dm365_pll2_init }, 876d67c13eaSDavid Lechner { .name = "dm644x-pll1", .driver_data = (kernel_ulong_t)dm644x_pll1_init }, 877d67c13eaSDavid Lechner { .name = "dm644x-pll2", .driver_data = (kernel_ulong_t)dm644x_pll2_init }, 8786ef35851SDavid Lechner { .name = "dm646x-pll1", .driver_data = (kernel_ulong_t)dm646x_pll1_init }, 8796ef35851SDavid Lechner { .name = "dm646x-pll2", .driver_data = (kernel_ulong_t)dm646x_pll2_init }, 8802d172691SDavid Lechner { } 8812d172691SDavid Lechner }; 8822d172691SDavid Lechner 883*76c9dd9dSDavid Lechner typedef int (*davinci_pll_init)(struct device *dev, void __iomem *base, 884*76c9dd9dSDavid Lechner struct regmap *cfgchip); 8852d172691SDavid Lechner 8862d172691SDavid Lechner static int davinci_pll_probe(struct platform_device *pdev) 8872d172691SDavid Lechner { 8882d172691SDavid Lechner struct device *dev = &pdev->dev; 889*76c9dd9dSDavid Lechner struct davinci_pll_platform_data *pdata; 8902d172691SDavid Lechner const struct of_device_id *of_id; 8912d172691SDavid Lechner davinci_pll_init pll_init = NULL; 8922d172691SDavid Lechner struct resource *res; 8932d172691SDavid Lechner void __iomem *base; 8942d172691SDavid Lechner 8952d172691SDavid Lechner of_id = of_match_device(davinci_pll_of_match, dev); 8962d172691SDavid Lechner if (of_id) 8972d172691SDavid Lechner pll_init = of_id->data; 8982d172691SDavid Lechner else if (pdev->id_entry) 8992d172691SDavid Lechner pll_init = (void *)pdev->id_entry->driver_data; 9002d172691SDavid Lechner 9012d172691SDavid Lechner if (!pll_init) { 9022d172691SDavid Lechner dev_err(dev, "unable to find driver data\n"); 9032d172691SDavid Lechner return -EINVAL; 9042d172691SDavid Lechner } 9052d172691SDavid Lechner 906*76c9dd9dSDavid Lechner pdata = davinci_pll_get_pdata(dev); 907*76c9dd9dSDavid Lechner if (!pdata) { 908*76c9dd9dSDavid Lechner dev_err(dev, "missing platform data\n"); 909*76c9dd9dSDavid Lechner return -EINVAL; 910*76c9dd9dSDavid Lechner } 911*76c9dd9dSDavid Lechner 9122d172691SDavid Lechner res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 9132d172691SDavid Lechner base = devm_ioremap_resource(dev, res); 914fc3fcb4fSWei Yongjun if (IS_ERR(base)) 9152d172691SDavid Lechner return PTR_ERR(base); 9162d172691SDavid Lechner 917*76c9dd9dSDavid Lechner return pll_init(dev, base, pdata->cfgchip); 9182d172691SDavid Lechner } 9192d172691SDavid Lechner 9202d172691SDavid Lechner static struct platform_driver davinci_pll_driver = { 9212d172691SDavid Lechner .probe = davinci_pll_probe, 9222d172691SDavid Lechner .driver = { 9232d172691SDavid Lechner .name = "davinci-pll-clk", 9242d172691SDavid Lechner .of_match_table = davinci_pll_of_match, 9252d172691SDavid Lechner }, 9262d172691SDavid Lechner .id_table = davinci_pll_id_table, 9272d172691SDavid Lechner }; 9282d172691SDavid Lechner 9292d172691SDavid Lechner static int __init davinci_pll_driver_init(void) 9302d172691SDavid Lechner { 9312d172691SDavid Lechner return platform_driver_register(&davinci_pll_driver); 9322d172691SDavid Lechner } 9332d172691SDavid Lechner 9342d172691SDavid Lechner /* has to be postcore_initcall because PSC devices depend on PLL parent clocks */ 9352d172691SDavid Lechner postcore_initcall(davinci_pll_driver_init); 9362d172691SDavid Lechner 9372d172691SDavid Lechner #ifdef CONFIG_DEBUG_FS 9382d172691SDavid Lechner #include <linux/debugfs.h> 9392d172691SDavid Lechner 9402d172691SDavid Lechner #define DEBUG_REG(n) \ 9412d172691SDavid Lechner { \ 9422d172691SDavid Lechner .name = #n, \ 9432d172691SDavid Lechner .offset = n, \ 9442d172691SDavid Lechner } 9452d172691SDavid Lechner 9462d172691SDavid Lechner static const struct debugfs_reg32 davinci_pll_regs[] = { 9472d172691SDavid Lechner DEBUG_REG(REVID), 9482d172691SDavid Lechner DEBUG_REG(PLLCTL), 9492d172691SDavid Lechner DEBUG_REG(OCSEL), 9502d172691SDavid Lechner DEBUG_REG(PLLSECCTL), 9512d172691SDavid Lechner DEBUG_REG(PLLM), 9522d172691SDavid Lechner DEBUG_REG(PREDIV), 9532d172691SDavid Lechner DEBUG_REG(PLLDIV1), 9542d172691SDavid Lechner DEBUG_REG(PLLDIV2), 9552d172691SDavid Lechner DEBUG_REG(PLLDIV3), 9562d172691SDavid Lechner DEBUG_REG(OSCDIV), 9572d172691SDavid Lechner DEBUG_REG(POSTDIV), 9582d172691SDavid Lechner DEBUG_REG(BPDIV), 9592d172691SDavid Lechner DEBUG_REG(PLLCMD), 9602d172691SDavid Lechner DEBUG_REG(PLLSTAT), 9612d172691SDavid Lechner DEBUG_REG(ALNCTL), 9622d172691SDavid Lechner DEBUG_REG(DCHANGE), 9632d172691SDavid Lechner DEBUG_REG(CKEN), 9642d172691SDavid Lechner DEBUG_REG(CKSTAT), 9652d172691SDavid Lechner DEBUG_REG(SYSTAT), 9662d172691SDavid Lechner DEBUG_REG(PLLDIV4), 9672d172691SDavid Lechner DEBUG_REG(PLLDIV5), 9682d172691SDavid Lechner DEBUG_REG(PLLDIV6), 9692d172691SDavid Lechner DEBUG_REG(PLLDIV7), 9702d172691SDavid Lechner DEBUG_REG(PLLDIV8), 9712d172691SDavid Lechner DEBUG_REG(PLLDIV9), 9722d172691SDavid Lechner }; 9732d172691SDavid Lechner 9742d172691SDavid Lechner static int davinci_pll_debug_init(struct clk_hw *hw, struct dentry *dentry) 9752d172691SDavid Lechner { 9762d172691SDavid Lechner struct davinci_pll_clk *pll = to_davinci_pll_clk(hw); 9772d172691SDavid Lechner struct debugfs_regset32 *regset; 9782d172691SDavid Lechner struct dentry *d; 9792d172691SDavid Lechner 9802d172691SDavid Lechner regset = kzalloc(sizeof(*regset), GFP_KERNEL); 9812d172691SDavid Lechner if (!regset) 9822d172691SDavid Lechner return -ENOMEM; 9832d172691SDavid Lechner 9842d172691SDavid Lechner regset->regs = davinci_pll_regs; 9852d172691SDavid Lechner regset->nregs = ARRAY_SIZE(davinci_pll_regs); 9862d172691SDavid Lechner regset->base = pll->base; 9872d172691SDavid Lechner 9882d172691SDavid Lechner d = debugfs_create_regset32("registers", 0400, dentry, regset); 9892d172691SDavid Lechner if (IS_ERR(d)) { 9902d172691SDavid Lechner kfree(regset); 9912d172691SDavid Lechner return PTR_ERR(d); 9922d172691SDavid Lechner } 9932d172691SDavid Lechner 9942d172691SDavid Lechner return 0; 9952d172691SDavid Lechner } 9962d172691SDavid Lechner #endif 997