cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

clk-pll.c (45300B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
      4 * Copyright (c) 2013 Linaro Ltd.
      5 *
      6 * This file contains the utility functions to register the pll clocks.
      7*/
      8
      9#include <linux/errno.h>
     10#include <linux/hrtimer.h>
     11#include <linux/iopoll.h>
     12#include <linux/delay.h>
     13#include <linux/slab.h>
     14#include <linux/timekeeping.h>
     15#include <linux/clk-provider.h>
     16#include <linux/io.h>
     17#include "clk.h"
     18#include "clk-pll.h"
     19
     20#define PLL_TIMEOUT_US		20000U
     21#define PLL_TIMEOUT_LOOPS	1000000U
     22
     23struct samsung_clk_pll {
     24	struct clk_hw		hw;
     25	void __iomem		*lock_reg;
     26	void __iomem		*con_reg;
     27	/* PLL enable control bit offset in @con_reg register */
     28	unsigned short		enable_offs;
     29	/* PLL lock status bit offset in @con_reg register */
     30	unsigned short		lock_offs;
     31	enum samsung_pll_type	type;
     32	unsigned int		rate_count;
     33	const struct samsung_pll_rate_table *rate_table;
     34};
     35
     36#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
     37
     38static const struct samsung_pll_rate_table *samsung_get_pll_settings(
     39				struct samsung_clk_pll *pll, unsigned long rate)
     40{
     41	const struct samsung_pll_rate_table  *rate_table = pll->rate_table;
     42	int i;
     43
     44	for (i = 0; i < pll->rate_count; i++) {
     45		if (rate == rate_table[i].rate)
     46			return &rate_table[i];
     47	}
     48
     49	return NULL;
     50}
     51
     52static long samsung_pll_round_rate(struct clk_hw *hw,
     53			unsigned long drate, unsigned long *prate)
     54{
     55	struct samsung_clk_pll *pll = to_clk_pll(hw);
     56	const struct samsung_pll_rate_table *rate_table = pll->rate_table;
     57	int i;
     58
     59	/* Assumming rate_table is in descending order */
     60	for (i = 0; i < pll->rate_count; i++) {
     61		if (drate >= rate_table[i].rate)
     62			return rate_table[i].rate;
     63	}
     64
     65	/* return minimum supported value */
     66	return rate_table[i - 1].rate;
     67}
     68
     69static bool pll_early_timeout = true;
     70
     71static int __init samsung_pll_disable_early_timeout(void)
     72{
     73	pll_early_timeout = false;
     74	return 0;
     75}
     76arch_initcall(samsung_pll_disable_early_timeout);
     77
     78/* Wait until the PLL is locked */
     79static int samsung_pll_lock_wait(struct samsung_clk_pll *pll,
     80				 unsigned int reg_mask)
     81{
     82	int i, ret;
     83	u32 val;
     84
     85	/*
     86	 * This function might be called when the timekeeping API can't be used
     87	 * to detect timeouts. One situation is when the clocksource is not yet
     88	 * initialized, another when the timekeeping is suspended. udelay() also
     89	 * cannot be used when the clocksource is not running on arm64, since
     90	 * the current timer is used as cycle counter. So a simple busy loop
     91	 * is used here in that special cases. The limit of iterations has been
     92	 * derived from experimental measurements of various PLLs on multiple
     93	 * Exynos SoC variants. Single register read time was usually in range
     94	 * 0.4...1.5 us, never less than 0.4 us.
     95	 */
     96	if (pll_early_timeout || timekeeping_suspended) {
     97		i = PLL_TIMEOUT_LOOPS;
     98		while (i-- > 0) {
     99			if (readl_relaxed(pll->con_reg) & reg_mask)
    100				return 0;
    101
    102			cpu_relax();
    103		}
    104		ret = -ETIMEDOUT;
    105	} else {
    106		ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val,
    107					val & reg_mask, 0, PLL_TIMEOUT_US);
    108	}
    109
    110	if (ret < 0)
    111		pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw));
    112
    113	return ret;
    114}
    115
    116static int samsung_pll3xxx_enable(struct clk_hw *hw)
    117{
    118	struct samsung_clk_pll *pll = to_clk_pll(hw);
    119	u32 tmp;
    120
    121	tmp = readl_relaxed(pll->con_reg);
    122	tmp |= BIT(pll->enable_offs);
    123	writel_relaxed(tmp, pll->con_reg);
    124
    125	return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
    126}
    127
    128static void samsung_pll3xxx_disable(struct clk_hw *hw)
    129{
    130	struct samsung_clk_pll *pll = to_clk_pll(hw);
    131	u32 tmp;
    132
    133	tmp = readl_relaxed(pll->con_reg);
    134	tmp &= ~BIT(pll->enable_offs);
    135	writel_relaxed(tmp, pll->con_reg);
    136}
    137
    138/*
    139 * PLL2126 Clock Type
    140 */
    141
    142#define PLL2126_MDIV_MASK	(0xff)
    143#define PLL2126_PDIV_MASK	(0x3f)
    144#define PLL2126_SDIV_MASK	(0x3)
    145#define PLL2126_MDIV_SHIFT	(16)
    146#define PLL2126_PDIV_SHIFT	(8)
    147#define PLL2126_SDIV_SHIFT	(0)
    148
    149static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
    150				unsigned long parent_rate)
    151{
    152	struct samsung_clk_pll *pll = to_clk_pll(hw);
    153	u32 pll_con, mdiv, pdiv, sdiv;
    154	u64 fvco = parent_rate;
    155
    156	pll_con = readl_relaxed(pll->con_reg);
    157	mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
    158	pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
    159	sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
    160
    161	fvco *= (mdiv + 8);
    162	do_div(fvco, (pdiv + 2) << sdiv);
    163
    164	return (unsigned long)fvco;
    165}
    166
    167static const struct clk_ops samsung_pll2126_clk_ops = {
    168	.recalc_rate = samsung_pll2126_recalc_rate,
    169};
    170
    171/*
    172 * PLL3000 Clock Type
    173 */
    174
    175#define PLL3000_MDIV_MASK	(0xff)
    176#define PLL3000_PDIV_MASK	(0x3)
    177#define PLL3000_SDIV_MASK	(0x3)
    178#define PLL3000_MDIV_SHIFT	(16)
    179#define PLL3000_PDIV_SHIFT	(8)
    180#define PLL3000_SDIV_SHIFT	(0)
    181
    182static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
    183				unsigned long parent_rate)
    184{
    185	struct samsung_clk_pll *pll = to_clk_pll(hw);
    186	u32 pll_con, mdiv, pdiv, sdiv;
    187	u64 fvco = parent_rate;
    188
    189	pll_con = readl_relaxed(pll->con_reg);
    190	mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
    191	pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
    192	sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
    193
    194	fvco *= (2 * (mdiv + 8));
    195	do_div(fvco, pdiv << sdiv);
    196
    197	return (unsigned long)fvco;
    198}
    199
    200static const struct clk_ops samsung_pll3000_clk_ops = {
    201	.recalc_rate = samsung_pll3000_recalc_rate,
    202};
    203
    204/*
    205 * PLL35xx Clock Type
    206 */
    207/* Maximum lock time can be 270 * PDIV cycles */
    208#define PLL35XX_LOCK_FACTOR	(270)
    209
    210#define PLL35XX_MDIV_MASK       (0x3FF)
    211#define PLL35XX_PDIV_MASK       (0x3F)
    212#define PLL35XX_SDIV_MASK       (0x7)
    213#define PLL35XX_MDIV_SHIFT      (16)
    214#define PLL35XX_PDIV_SHIFT      (8)
    215#define PLL35XX_SDIV_SHIFT      (0)
    216#define PLL35XX_LOCK_STAT_SHIFT	(29)
    217#define PLL35XX_ENABLE_SHIFT	(31)
    218
    219static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
    220				unsigned long parent_rate)
    221{
    222	struct samsung_clk_pll *pll = to_clk_pll(hw);
    223	u32 mdiv, pdiv, sdiv, pll_con;
    224	u64 fvco = parent_rate;
    225
    226	pll_con = readl_relaxed(pll->con_reg);
    227	mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
    228	pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
    229	sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
    230
    231	fvco *= mdiv;
    232	do_div(fvco, (pdiv << sdiv));
    233
    234	return (unsigned long)fvco;
    235}
    236
    237static inline bool samsung_pll35xx_mp_change(
    238		const struct samsung_pll_rate_table *rate, u32 pll_con)
    239{
    240	u32 old_mdiv, old_pdiv;
    241
    242	old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
    243	old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
    244
    245	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
    246}
    247
    248static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
    249					unsigned long prate)
    250{
    251	struct samsung_clk_pll *pll = to_clk_pll(hw);
    252	const struct samsung_pll_rate_table *rate;
    253	u32 tmp;
    254
    255	/* Get required rate settings from table */
    256	rate = samsung_get_pll_settings(pll, drate);
    257	if (!rate) {
    258		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
    259			drate, clk_hw_get_name(hw));
    260		return -EINVAL;
    261	}
    262
    263	tmp = readl_relaxed(pll->con_reg);
    264
    265	if (!(samsung_pll35xx_mp_change(rate, tmp))) {
    266		/* If only s change, change just s value only*/
    267		tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
    268		tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
    269		writel_relaxed(tmp, pll->con_reg);
    270
    271		return 0;
    272	}
    273
    274	/* Set PLL lock time. */
    275	writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
    276			pll->lock_reg);
    277
    278	/* Change PLL PMS values */
    279	tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
    280			(PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
    281			(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
    282	tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
    283			(rate->pdiv << PLL35XX_PDIV_SHIFT) |
    284			(rate->sdiv << PLL35XX_SDIV_SHIFT);
    285	writel_relaxed(tmp, pll->con_reg);
    286
    287	/* Wait for PLL lock if the PLL is enabled */
    288	if (tmp & BIT(pll->enable_offs))
    289		return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
    290
    291	return 0;
    292}
    293
    294static const struct clk_ops samsung_pll35xx_clk_ops = {
    295	.recalc_rate = samsung_pll35xx_recalc_rate,
    296	.round_rate = samsung_pll_round_rate,
    297	.set_rate = samsung_pll35xx_set_rate,
    298	.enable = samsung_pll3xxx_enable,
    299	.disable = samsung_pll3xxx_disable,
    300};
    301
    302static const struct clk_ops samsung_pll35xx_clk_min_ops = {
    303	.recalc_rate = samsung_pll35xx_recalc_rate,
    304};
    305
    306/*
    307 * PLL36xx Clock Type
    308 */
    309/* Maximum lock time can be 3000 * PDIV cycles */
    310#define PLL36XX_LOCK_FACTOR    (3000)
    311
    312#define PLL36XX_KDIV_MASK	(0xFFFF)
    313#define PLL36XX_MDIV_MASK	(0x1FF)
    314#define PLL36XX_PDIV_MASK	(0x3F)
    315#define PLL36XX_SDIV_MASK	(0x7)
    316#define PLL36XX_MDIV_SHIFT	(16)
    317#define PLL36XX_PDIV_SHIFT	(8)
    318#define PLL36XX_SDIV_SHIFT	(0)
    319#define PLL36XX_KDIV_SHIFT	(0)
    320#define PLL36XX_LOCK_STAT_SHIFT	(29)
    321#define PLL36XX_ENABLE_SHIFT	(31)
    322
    323static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
    324				unsigned long parent_rate)
    325{
    326	struct samsung_clk_pll *pll = to_clk_pll(hw);
    327	u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
    328	s16 kdiv;
    329	u64 fvco = parent_rate;
    330
    331	pll_con0 = readl_relaxed(pll->con_reg);
    332	pll_con1 = readl_relaxed(pll->con_reg + 4);
    333	mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
    334	pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
    335	sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
    336	kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK);
    337
    338	fvco *= (mdiv << 16) + kdiv;
    339	do_div(fvco, (pdiv << sdiv));
    340	fvco >>= 16;
    341
    342	return (unsigned long)fvco;
    343}
    344
    345static inline bool samsung_pll36xx_mpk_change(
    346	const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
    347{
    348	u32 old_mdiv, old_pdiv, old_kdiv;
    349
    350	old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
    351	old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
    352	old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
    353
    354	return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
    355		rate->kdiv != old_kdiv);
    356}
    357
    358static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
    359					unsigned long parent_rate)
    360{
    361	struct samsung_clk_pll *pll = to_clk_pll(hw);
    362	u32 pll_con0, pll_con1;
    363	const struct samsung_pll_rate_table *rate;
    364
    365	rate = samsung_get_pll_settings(pll, drate);
    366	if (!rate) {
    367		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
    368			drate, clk_hw_get_name(hw));
    369		return -EINVAL;
    370	}
    371
    372	pll_con0 = readl_relaxed(pll->con_reg);
    373	pll_con1 = readl_relaxed(pll->con_reg + 4);
    374
    375	if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
    376		/* If only s change, change just s value only*/
    377		pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
    378		pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
    379		writel_relaxed(pll_con0, pll->con_reg);
    380
    381		return 0;
    382	}
    383
    384	/* Set PLL lock time. */
    385	writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
    386
    387	 /* Change PLL PMS values */
    388	pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
    389			(PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
    390			(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
    391	pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
    392			(rate->pdiv << PLL36XX_PDIV_SHIFT) |
    393			(rate->sdiv << PLL36XX_SDIV_SHIFT);
    394	writel_relaxed(pll_con0, pll->con_reg);
    395
    396	pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
    397	pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
    398	writel_relaxed(pll_con1, pll->con_reg + 4);
    399
    400	if (pll_con0 & BIT(pll->enable_offs))
    401		return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
    402
    403	return 0;
    404}
    405
    406static const struct clk_ops samsung_pll36xx_clk_ops = {
    407	.recalc_rate = samsung_pll36xx_recalc_rate,
    408	.set_rate = samsung_pll36xx_set_rate,
    409	.round_rate = samsung_pll_round_rate,
    410	.enable = samsung_pll3xxx_enable,
    411	.disable = samsung_pll3xxx_disable,
    412};
    413
    414static const struct clk_ops samsung_pll36xx_clk_min_ops = {
    415	.recalc_rate = samsung_pll36xx_recalc_rate,
    416};
    417
    418/*
    419 * PLL0822x Clock Type
    420 */
    421/* Maximum lock time can be 150 * PDIV cycles */
    422#define PLL0822X_LOCK_FACTOR		(150)
    423
    424#define PLL0822X_MDIV_MASK		(0x3FF)
    425#define PLL0822X_PDIV_MASK		(0x3F)
    426#define PLL0822X_SDIV_MASK		(0x7)
    427#define PLL0822X_MDIV_SHIFT		(16)
    428#define PLL0822X_PDIV_SHIFT		(8)
    429#define PLL0822X_SDIV_SHIFT		(0)
    430#define PLL0822X_LOCK_STAT_SHIFT	(29)
    431#define PLL0822X_ENABLE_SHIFT		(31)
    432
    433static unsigned long samsung_pll0822x_recalc_rate(struct clk_hw *hw,
    434						  unsigned long parent_rate)
    435{
    436	struct samsung_clk_pll *pll = to_clk_pll(hw);
    437	u32 mdiv, pdiv, sdiv, pll_con3;
    438	u64 fvco = parent_rate;
    439
    440	pll_con3 = readl_relaxed(pll->con_reg);
    441	mdiv = (pll_con3 >> PLL0822X_MDIV_SHIFT) & PLL0822X_MDIV_MASK;
    442	pdiv = (pll_con3 >> PLL0822X_PDIV_SHIFT) & PLL0822X_PDIV_MASK;
    443	sdiv = (pll_con3 >> PLL0822X_SDIV_SHIFT) & PLL0822X_SDIV_MASK;
    444
    445	fvco *= mdiv;
    446	do_div(fvco, (pdiv << sdiv));
    447
    448	return (unsigned long)fvco;
    449}
    450
    451static int samsung_pll0822x_set_rate(struct clk_hw *hw, unsigned long drate,
    452				     unsigned long prate)
    453{
    454	const struct samsung_pll_rate_table *rate;
    455	struct samsung_clk_pll *pll = to_clk_pll(hw);
    456	u32 pll_con3;
    457
    458	/* Get required rate settings from table */
    459	rate = samsung_get_pll_settings(pll, drate);
    460	if (!rate) {
    461		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
    462			drate, clk_hw_get_name(hw));
    463		return -EINVAL;
    464	}
    465
    466	/* Change PLL PMS values */
    467	pll_con3 = readl_relaxed(pll->con_reg);
    468	pll_con3 &= ~((PLL0822X_MDIV_MASK << PLL0822X_MDIV_SHIFT) |
    469			(PLL0822X_PDIV_MASK << PLL0822X_PDIV_SHIFT) |
    470			(PLL0822X_SDIV_MASK << PLL0822X_SDIV_SHIFT));
    471	pll_con3 |= (rate->mdiv << PLL0822X_MDIV_SHIFT) |
    472			(rate->pdiv << PLL0822X_PDIV_SHIFT) |
    473			(rate->sdiv << PLL0822X_SDIV_SHIFT);
    474
    475	/* Set PLL lock time */
    476	writel_relaxed(rate->pdiv * PLL0822X_LOCK_FACTOR,
    477			pll->lock_reg);
    478
    479	/* Write PMS values */
    480	writel_relaxed(pll_con3, pll->con_reg);
    481
    482	/* Wait for PLL lock if the PLL is enabled */
    483	if (pll_con3 & BIT(pll->enable_offs))
    484		return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
    485
    486	return 0;
    487}
    488
    489static const struct clk_ops samsung_pll0822x_clk_ops = {
    490	.recalc_rate = samsung_pll0822x_recalc_rate,
    491	.round_rate = samsung_pll_round_rate,
    492	.set_rate = samsung_pll0822x_set_rate,
    493	.enable = samsung_pll3xxx_enable,
    494	.disable = samsung_pll3xxx_disable,
    495};
    496
    497static const struct clk_ops samsung_pll0822x_clk_min_ops = {
    498	.recalc_rate = samsung_pll0822x_recalc_rate,
    499};
    500
    501/*
    502 * PLL0831x Clock Type
    503 */
    504/* Maximum lock time can be 500 * PDIV cycles */
    505#define PLL0831X_LOCK_FACTOR		(500)
    506
    507#define PLL0831X_KDIV_MASK		(0xFFFF)
    508#define PLL0831X_MDIV_MASK		(0x1FF)
    509#define PLL0831X_PDIV_MASK		(0x3F)
    510#define PLL0831X_SDIV_MASK		(0x7)
    511#define PLL0831X_MDIV_SHIFT		(16)
    512#define PLL0831X_PDIV_SHIFT		(8)
    513#define PLL0831X_SDIV_SHIFT		(0)
    514#define PLL0831X_KDIV_SHIFT		(0)
    515#define PLL0831X_LOCK_STAT_SHIFT	(29)
    516#define PLL0831X_ENABLE_SHIFT		(31)
    517
    518static unsigned long samsung_pll0831x_recalc_rate(struct clk_hw *hw,
    519						  unsigned long parent_rate)
    520{
    521	struct samsung_clk_pll *pll = to_clk_pll(hw);
    522	u32 mdiv, pdiv, sdiv, pll_con3, pll_con5;
    523	s16 kdiv;
    524	u64 fvco = parent_rate;
    525
    526	pll_con3 = readl_relaxed(pll->con_reg);
    527	pll_con5 = readl_relaxed(pll->con_reg + 8);
    528	mdiv = (pll_con3 >> PLL0831X_MDIV_SHIFT) & PLL0831X_MDIV_MASK;
    529	pdiv = (pll_con3 >> PLL0831X_PDIV_SHIFT) & PLL0831X_PDIV_MASK;
    530	sdiv = (pll_con3 >> PLL0831X_SDIV_SHIFT) & PLL0831X_SDIV_MASK;
    531	kdiv = (s16)((pll_con5 >> PLL0831X_KDIV_SHIFT) & PLL0831X_KDIV_MASK);
    532
    533	fvco *= (mdiv << 16) + kdiv;
    534	do_div(fvco, (pdiv << sdiv));
    535	fvco >>= 16;
    536
    537	return (unsigned long)fvco;
    538}
    539
    540static int samsung_pll0831x_set_rate(struct clk_hw *hw, unsigned long drate,
    541				     unsigned long parent_rate)
    542{
    543	const struct samsung_pll_rate_table *rate;
    544	struct samsung_clk_pll *pll = to_clk_pll(hw);
    545	u32 pll_con3, pll_con5;
    546
    547	/* Get required rate settings from table */
    548	rate = samsung_get_pll_settings(pll, drate);
    549	if (!rate) {
    550		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
    551			drate, clk_hw_get_name(hw));
    552		return -EINVAL;
    553	}
    554
    555	pll_con3 = readl_relaxed(pll->con_reg);
    556	pll_con5 = readl_relaxed(pll->con_reg + 8);
    557
    558	/* Change PLL PMSK values */
    559	pll_con3 &= ~((PLL0831X_MDIV_MASK << PLL0831X_MDIV_SHIFT) |
    560			(PLL0831X_PDIV_MASK << PLL0831X_PDIV_SHIFT) |
    561			(PLL0831X_SDIV_MASK << PLL0831X_SDIV_SHIFT));
    562	pll_con3 |= (rate->mdiv << PLL0831X_MDIV_SHIFT) |
    563			(rate->pdiv << PLL0831X_PDIV_SHIFT) |
    564			(rate->sdiv << PLL0831X_SDIV_SHIFT);
    565	pll_con5 &= ~(PLL0831X_KDIV_MASK << PLL0831X_KDIV_SHIFT);
    566	/*
    567	 * kdiv is 16-bit 2's complement (s16), but stored as unsigned int.
    568	 * Cast it to u16 to avoid leading 0xffff's in case of negative value.
    569	 */
    570	pll_con5 |= ((u16)rate->kdiv << PLL0831X_KDIV_SHIFT);
    571
    572	/* Set PLL lock time */
    573	writel_relaxed(rate->pdiv * PLL0831X_LOCK_FACTOR, pll->lock_reg);
    574
    575	/* Write PMSK values */
    576	writel_relaxed(pll_con3, pll->con_reg);
    577	writel_relaxed(pll_con5, pll->con_reg + 8);
    578
    579	/* Wait for PLL lock if the PLL is enabled */
    580	if (pll_con3 & BIT(pll->enable_offs))
    581		return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
    582
    583	return 0;
    584}
    585
    586static const struct clk_ops samsung_pll0831x_clk_ops = {
    587	.recalc_rate = samsung_pll0831x_recalc_rate,
    588	.set_rate = samsung_pll0831x_set_rate,
    589	.round_rate = samsung_pll_round_rate,
    590	.enable = samsung_pll3xxx_enable,
    591	.disable = samsung_pll3xxx_disable,
    592};
    593
    594static const struct clk_ops samsung_pll0831x_clk_min_ops = {
    595	.recalc_rate = samsung_pll0831x_recalc_rate,
    596};
    597
    598/*
    599 * PLL45xx Clock Type
    600 */
    601#define PLL4502_LOCK_FACTOR	400
    602#define PLL4508_LOCK_FACTOR	240
    603
    604#define PLL45XX_MDIV_MASK	(0x3FF)
    605#define PLL45XX_PDIV_MASK	(0x3F)
    606#define PLL45XX_SDIV_MASK	(0x7)
    607#define PLL45XX_AFC_MASK	(0x1F)
    608#define PLL45XX_MDIV_SHIFT	(16)
    609#define PLL45XX_PDIV_SHIFT	(8)
    610#define PLL45XX_SDIV_SHIFT	(0)
    611#define PLL45XX_AFC_SHIFT	(0)
    612
    613#define PLL45XX_ENABLE		BIT(31)
    614#define PLL45XX_LOCKED		BIT(29)
    615
    616static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
    617				unsigned long parent_rate)
    618{
    619	struct samsung_clk_pll *pll = to_clk_pll(hw);
    620	u32 mdiv, pdiv, sdiv, pll_con;
    621	u64 fvco = parent_rate;
    622
    623	pll_con = readl_relaxed(pll->con_reg);
    624	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
    625	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
    626	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
    627
    628	if (pll->type == pll_4508)
    629		sdiv = sdiv - 1;
    630
    631	fvco *= mdiv;
    632	do_div(fvco, (pdiv << sdiv));
    633
    634	return (unsigned long)fvco;
    635}
    636
    637static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
    638				const struct samsung_pll_rate_table *rate)
    639{
    640	u32 old_mdiv, old_pdiv, old_afc;
    641
    642	old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
    643	old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
    644	old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK;
    645
    646	return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
    647		|| old_afc != rate->afc);
    648}
    649
    650static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
    651					unsigned long prate)
    652{
    653	struct samsung_clk_pll *pll = to_clk_pll(hw);
    654	const struct samsung_pll_rate_table *rate;
    655	u32 con0, con1;
    656
    657	/* Get required rate settings from table */
    658	rate = samsung_get_pll_settings(pll, drate);
    659	if (!rate) {
    660		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
    661			drate, clk_hw_get_name(hw));
    662		return -EINVAL;
    663	}
    664
    665	con0 = readl_relaxed(pll->con_reg);
    666	con1 = readl_relaxed(pll->con_reg + 0x4);
    667
    668	if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
    669		/* If only s change, change just s value only*/
    670		con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
    671		con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
    672		writel_relaxed(con0, pll->con_reg);
    673
    674		return 0;
    675	}
    676
    677	/* Set PLL PMS values. */
    678	con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) |
    679			(PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) |
    680			(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT));
    681	con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) |
    682			(rate->pdiv << PLL45XX_PDIV_SHIFT) |
    683			(rate->sdiv << PLL45XX_SDIV_SHIFT);
    684
    685	/* Set PLL AFC value. */
    686	con1 = readl_relaxed(pll->con_reg + 0x4);
    687	con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
    688	con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
    689
    690	/* Set PLL lock time. */
    691	switch (pll->type) {
    692	case pll_4502:
    693		writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
    694		break;
    695	case pll_4508:
    696		writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
    697		break;
    698	default:
    699		break;
    700	}
    701
    702	/* Set new configuration. */
    703	writel_relaxed(con1, pll->con_reg + 0x4);
    704	writel_relaxed(con0, pll->con_reg);
    705
    706	/* Wait for PLL lock */
    707	return samsung_pll_lock_wait(pll, PLL45XX_LOCKED);
    708}
    709
    710static const struct clk_ops samsung_pll45xx_clk_ops = {
    711	.recalc_rate = samsung_pll45xx_recalc_rate,
    712	.round_rate = samsung_pll_round_rate,
    713	.set_rate = samsung_pll45xx_set_rate,
    714};
    715
    716static const struct clk_ops samsung_pll45xx_clk_min_ops = {
    717	.recalc_rate = samsung_pll45xx_recalc_rate,
    718};
    719
    720/*
    721 * PLL46xx Clock Type
    722 */
    723#define PLL46XX_LOCK_FACTOR	3000
    724
    725#define PLL46XX_VSEL_MASK	(1)
    726#define PLL46XX_MDIV_MASK	(0x1FF)
    727#define PLL1460X_MDIV_MASK	(0x3FF)
    728
    729#define PLL46XX_PDIV_MASK	(0x3F)
    730#define PLL46XX_SDIV_MASK	(0x7)
    731#define PLL46XX_VSEL_SHIFT	(27)
    732#define PLL46XX_MDIV_SHIFT	(16)
    733#define PLL46XX_PDIV_SHIFT	(8)
    734#define PLL46XX_SDIV_SHIFT	(0)
    735
    736#define PLL46XX_KDIV_MASK	(0xFFFF)
    737#define PLL4650C_KDIV_MASK	(0xFFF)
    738#define PLL46XX_KDIV_SHIFT	(0)
    739#define PLL46XX_MFR_MASK	(0x3F)
    740#define PLL46XX_MRR_MASK	(0x1F)
    741#define PLL46XX_KDIV_SHIFT	(0)
    742#define PLL46XX_MFR_SHIFT	(16)
    743#define PLL46XX_MRR_SHIFT	(24)
    744
    745#define PLL46XX_ENABLE		BIT(31)
    746#define PLL46XX_LOCKED		BIT(29)
    747#define PLL46XX_VSEL		BIT(27)
    748
    749static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
    750				unsigned long parent_rate)
    751{
    752	struct samsung_clk_pll *pll = to_clk_pll(hw);
    753	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
    754	u64 fvco = parent_rate;
    755
    756	pll_con0 = readl_relaxed(pll->con_reg);
    757	pll_con1 = readl_relaxed(pll->con_reg + 4);
    758	mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
    759				PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
    760	pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
    761	sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
    762	kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
    763					pll_con1 & PLL46XX_KDIV_MASK;
    764
    765	shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10;
    766
    767	fvco *= (mdiv << shift) + kdiv;
    768	do_div(fvco, (pdiv << sdiv));
    769	fvco >>= shift;
    770
    771	return (unsigned long)fvco;
    772}
    773
    774static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
    775				const struct samsung_pll_rate_table *rate)
    776{
    777	u32 old_mdiv, old_pdiv, old_kdiv;
    778
    779	old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
    780	old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
    781	old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK;
    782
    783	return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
    784		|| old_kdiv != rate->kdiv);
    785}
    786
    787static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
    788					unsigned long prate)
    789{
    790	struct samsung_clk_pll *pll = to_clk_pll(hw);
    791	const struct samsung_pll_rate_table *rate;
    792	u32 con0, con1, lock;
    793
    794	/* Get required rate settings from table */
    795	rate = samsung_get_pll_settings(pll, drate);
    796	if (!rate) {
    797		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
    798			drate, clk_hw_get_name(hw));
    799		return -EINVAL;
    800	}
    801
    802	con0 = readl_relaxed(pll->con_reg);
    803	con1 = readl_relaxed(pll->con_reg + 0x4);
    804
    805	if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
    806		/* If only s change, change just s value only*/
    807		con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
    808		con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
    809		writel_relaxed(con0, pll->con_reg);
    810
    811		return 0;
    812	}
    813
    814	/* Set PLL lock time. */
    815	lock = rate->pdiv * PLL46XX_LOCK_FACTOR;
    816	if (lock > 0xffff)
    817		/* Maximum lock time bitfield is 16-bit. */
    818		lock = 0xffff;
    819
    820	/* Set PLL PMS and VSEL values. */
    821	if (pll->type == pll_1460x) {
    822		con0 &= ~((PLL1460X_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
    823			(PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
    824			(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT));
    825	} else {
    826		con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
    827			(PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
    828			(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
    829			(PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
    830		con0 |=	rate->vsel << PLL46XX_VSEL_SHIFT;
    831	}
    832
    833	con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
    834			(rate->pdiv << PLL46XX_PDIV_SHIFT) |
    835			(rate->sdiv << PLL46XX_SDIV_SHIFT);
    836
    837	/* Set PLL K, MFR and MRR values. */
    838	con1 = readl_relaxed(pll->con_reg + 0x4);
    839	con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
    840			(PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
    841			(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
    842	con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) |
    843			(rate->mfr << PLL46XX_MFR_SHIFT) |
    844			(rate->mrr << PLL46XX_MRR_SHIFT);
    845
    846	/* Write configuration to PLL */
    847	writel_relaxed(lock, pll->lock_reg);
    848	writel_relaxed(con0, pll->con_reg);
    849	writel_relaxed(con1, pll->con_reg + 0x4);
    850
    851	/* Wait for PLL lock */
    852	return samsung_pll_lock_wait(pll, PLL46XX_LOCKED);
    853}
    854
    855static const struct clk_ops samsung_pll46xx_clk_ops = {
    856	.recalc_rate = samsung_pll46xx_recalc_rate,
    857	.round_rate = samsung_pll_round_rate,
    858	.set_rate = samsung_pll46xx_set_rate,
    859};
    860
    861static const struct clk_ops samsung_pll46xx_clk_min_ops = {
    862	.recalc_rate = samsung_pll46xx_recalc_rate,
    863};
    864
    865/*
    866 * PLL6552 Clock Type
    867 */
    868
    869#define PLL6552_MDIV_MASK	0x3ff
    870#define PLL6552_PDIV_MASK	0x3f
    871#define PLL6552_SDIV_MASK	0x7
    872#define PLL6552_MDIV_SHIFT	16
    873#define PLL6552_MDIV_SHIFT_2416	14
    874#define PLL6552_PDIV_SHIFT	8
    875#define PLL6552_PDIV_SHIFT_2416	5
    876#define PLL6552_SDIV_SHIFT	0
    877
    878static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
    879						unsigned long parent_rate)
    880{
    881	struct samsung_clk_pll *pll = to_clk_pll(hw);
    882	u32 mdiv, pdiv, sdiv, pll_con;
    883	u64 fvco = parent_rate;
    884
    885	pll_con = readl_relaxed(pll->con_reg);
    886	if (pll->type == pll_6552_s3c2416) {
    887		mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
    888		pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
    889	} else {
    890		mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
    891		pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
    892	}
    893	sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
    894
    895	fvco *= mdiv;
    896	do_div(fvco, (pdiv << sdiv));
    897
    898	return (unsigned long)fvco;
    899}
    900
    901static const struct clk_ops samsung_pll6552_clk_ops = {
    902	.recalc_rate = samsung_pll6552_recalc_rate,
    903};
    904
    905/*
    906 * PLL6553 Clock Type
    907 */
    908
    909#define PLL6553_MDIV_MASK	0xff
    910#define PLL6553_PDIV_MASK	0x3f
    911#define PLL6553_SDIV_MASK	0x7
    912#define PLL6553_KDIV_MASK	0xffff
    913#define PLL6553_MDIV_SHIFT	16
    914#define PLL6553_PDIV_SHIFT	8
    915#define PLL6553_SDIV_SHIFT	0
    916#define PLL6553_KDIV_SHIFT	0
    917
    918static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
    919						unsigned long parent_rate)
    920{
    921	struct samsung_clk_pll *pll = to_clk_pll(hw);
    922	u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
    923	u64 fvco = parent_rate;
    924
    925	pll_con0 = readl_relaxed(pll->con_reg);
    926	pll_con1 = readl_relaxed(pll->con_reg + 0x4);
    927	mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
    928	pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
    929	sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
    930	kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK;
    931
    932	fvco *= (mdiv << 16) + kdiv;
    933	do_div(fvco, (pdiv << sdiv));
    934	fvco >>= 16;
    935
    936	return (unsigned long)fvco;
    937}
    938
    939static const struct clk_ops samsung_pll6553_clk_ops = {
    940	.recalc_rate = samsung_pll6553_recalc_rate,
    941};
    942
    943/*
    944 * PLL Clock Type of S3C24XX before S3C2443
    945 */
    946
    947#define PLLS3C2410_MDIV_MASK		(0xff)
    948#define PLLS3C2410_PDIV_MASK		(0x1f)
    949#define PLLS3C2410_SDIV_MASK		(0x3)
    950#define PLLS3C2410_MDIV_SHIFT		(12)
    951#define PLLS3C2410_PDIV_SHIFT		(4)
    952#define PLLS3C2410_SDIV_SHIFT		(0)
    953
    954#define PLLS3C2410_ENABLE_REG_OFFSET	0x10
    955
    956static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
    957					unsigned long parent_rate)
    958{
    959	struct samsung_clk_pll *pll = to_clk_pll(hw);
    960	u32 pll_con, mdiv, pdiv, sdiv;
    961	u64 fvco = parent_rate;
    962
    963	pll_con = readl_relaxed(pll->con_reg);
    964	mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
    965	pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
    966	sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
    967
    968	fvco *= (mdiv + 8);
    969	do_div(fvco, (pdiv + 2) << sdiv);
    970
    971	return (unsigned int)fvco;
    972}
    973
    974static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
    975					unsigned long parent_rate)
    976{
    977	struct samsung_clk_pll *pll = to_clk_pll(hw);
    978	u32 pll_con, mdiv, pdiv, sdiv;
    979	u64 fvco = parent_rate;
    980
    981	pll_con = readl_relaxed(pll->con_reg);
    982	mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
    983	pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
    984	sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
    985
    986	fvco *= (2 * (mdiv + 8));
    987	do_div(fvco, (pdiv + 2) << sdiv);
    988
    989	return (unsigned int)fvco;
    990}
    991
    992static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
    993					unsigned long prate)
    994{
    995	struct samsung_clk_pll *pll = to_clk_pll(hw);
    996	const struct samsung_pll_rate_table *rate;
    997	u32 tmp;
    998
    999	/* Get required rate settings from table */
   1000	rate = samsung_get_pll_settings(pll, drate);
   1001	if (!rate) {
   1002		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
   1003			drate, clk_hw_get_name(hw));
   1004		return -EINVAL;
   1005	}
   1006
   1007	tmp = readl_relaxed(pll->con_reg);
   1008
   1009	/* Change PLL PMS values */
   1010	tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) |
   1011			(PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) |
   1012			(PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT));
   1013	tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) |
   1014			(rate->pdiv << PLLS3C2410_PDIV_SHIFT) |
   1015			(rate->sdiv << PLLS3C2410_SDIV_SHIFT);
   1016	writel_relaxed(tmp, pll->con_reg);
   1017
   1018	/* Time to settle according to the manual */
   1019	udelay(300);
   1020
   1021	return 0;
   1022}
   1023
   1024static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable)
   1025{
   1026	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1027	u32 pll_en = readl_relaxed(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
   1028	u32 pll_en_orig = pll_en;
   1029
   1030	if (enable)
   1031		pll_en &= ~BIT(bit);
   1032	else
   1033		pll_en |= BIT(bit);
   1034
   1035	writel_relaxed(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET);
   1036
   1037	/* if we started the UPLL, then allow to settle */
   1038	if (enable && (pll_en_orig & BIT(bit)))
   1039		udelay(300);
   1040
   1041	return 0;
   1042}
   1043
   1044static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
   1045{
   1046	return samsung_s3c2410_pll_enable(hw, 5, true);
   1047}
   1048
   1049static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
   1050{
   1051	samsung_s3c2410_pll_enable(hw, 5, false);
   1052}
   1053
   1054static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
   1055{
   1056	return samsung_s3c2410_pll_enable(hw, 7, true);
   1057}
   1058
   1059static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
   1060{
   1061	samsung_s3c2410_pll_enable(hw, 7, false);
   1062}
   1063
   1064static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = {
   1065	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
   1066	.enable = samsung_s3c2410_mpll_enable,
   1067	.disable = samsung_s3c2410_mpll_disable,
   1068};
   1069
   1070static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = {
   1071	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
   1072	.enable = samsung_s3c2410_upll_enable,
   1073	.disable = samsung_s3c2410_upll_disable,
   1074};
   1075
   1076static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = {
   1077	.recalc_rate = samsung_s3c2440_mpll_recalc_rate,
   1078	.enable = samsung_s3c2410_mpll_enable,
   1079	.disable = samsung_s3c2410_mpll_disable,
   1080};
   1081
   1082static const struct clk_ops samsung_s3c2410_mpll_clk_ops = {
   1083	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
   1084	.enable = samsung_s3c2410_mpll_enable,
   1085	.disable = samsung_s3c2410_mpll_disable,
   1086	.round_rate = samsung_pll_round_rate,
   1087	.set_rate = samsung_s3c2410_pll_set_rate,
   1088};
   1089
   1090static const struct clk_ops samsung_s3c2410_upll_clk_ops = {
   1091	.recalc_rate = samsung_s3c2410_pll_recalc_rate,
   1092	.enable = samsung_s3c2410_upll_enable,
   1093	.disable = samsung_s3c2410_upll_disable,
   1094	.round_rate = samsung_pll_round_rate,
   1095	.set_rate = samsung_s3c2410_pll_set_rate,
   1096};
   1097
   1098static const struct clk_ops samsung_s3c2440_mpll_clk_ops = {
   1099	.recalc_rate = samsung_s3c2440_mpll_recalc_rate,
   1100	.enable = samsung_s3c2410_mpll_enable,
   1101	.disable = samsung_s3c2410_mpll_disable,
   1102	.round_rate = samsung_pll_round_rate,
   1103	.set_rate = samsung_s3c2410_pll_set_rate,
   1104};
   1105
   1106/*
   1107 * PLL2550x Clock Type
   1108 */
   1109
   1110#define PLL2550X_R_MASK       (0x1)
   1111#define PLL2550X_P_MASK       (0x3F)
   1112#define PLL2550X_M_MASK       (0x3FF)
   1113#define PLL2550X_S_MASK       (0x7)
   1114#define PLL2550X_R_SHIFT      (20)
   1115#define PLL2550X_P_SHIFT      (14)
   1116#define PLL2550X_M_SHIFT      (4)
   1117#define PLL2550X_S_SHIFT      (0)
   1118
   1119static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
   1120				unsigned long parent_rate)
   1121{
   1122	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1123	u32 r, p, m, s, pll_stat;
   1124	u64 fvco = parent_rate;
   1125
   1126	pll_stat = readl_relaxed(pll->con_reg);
   1127	r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
   1128	if (!r)
   1129		return 0;
   1130	p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
   1131	m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
   1132	s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
   1133
   1134	fvco *= m;
   1135	do_div(fvco, (p << s));
   1136
   1137	return (unsigned long)fvco;
   1138}
   1139
   1140static const struct clk_ops samsung_pll2550x_clk_ops = {
   1141	.recalc_rate = samsung_pll2550x_recalc_rate,
   1142};
   1143
   1144/*
   1145 * PLL2550xx Clock Type
   1146 */
   1147
   1148/* Maximum lock time can be 270 * PDIV cycles */
   1149#define PLL2550XX_LOCK_FACTOR 270
   1150
   1151#define PLL2550XX_M_MASK		0x3FF
   1152#define PLL2550XX_P_MASK		0x3F
   1153#define PLL2550XX_S_MASK		0x7
   1154#define PLL2550XX_LOCK_STAT_MASK	0x1
   1155#define PLL2550XX_M_SHIFT		9
   1156#define PLL2550XX_P_SHIFT		3
   1157#define PLL2550XX_S_SHIFT		0
   1158#define PLL2550XX_LOCK_STAT_SHIFT	21
   1159
   1160static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw,
   1161				unsigned long parent_rate)
   1162{
   1163	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1164	u32 mdiv, pdiv, sdiv, pll_con;
   1165	u64 fvco = parent_rate;
   1166
   1167	pll_con = readl_relaxed(pll->con_reg);
   1168	mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
   1169	pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
   1170	sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK;
   1171
   1172	fvco *= mdiv;
   1173	do_div(fvco, (pdiv << sdiv));
   1174
   1175	return (unsigned long)fvco;
   1176}
   1177
   1178static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con)
   1179{
   1180	u32 old_mdiv, old_pdiv;
   1181
   1182	old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK;
   1183	old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK;
   1184
   1185	return mdiv != old_mdiv || pdiv != old_pdiv;
   1186}
   1187
   1188static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate,
   1189					unsigned long prate)
   1190{
   1191	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1192	const struct samsung_pll_rate_table *rate;
   1193	u32 tmp;
   1194
   1195	/* Get required rate settings from table */
   1196	rate = samsung_get_pll_settings(pll, drate);
   1197	if (!rate) {
   1198		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
   1199			drate, clk_hw_get_name(hw));
   1200		return -EINVAL;
   1201	}
   1202
   1203	tmp = readl_relaxed(pll->con_reg);
   1204
   1205	if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) {
   1206		/* If only s change, change just s value only*/
   1207		tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT);
   1208		tmp |= rate->sdiv << PLL2550XX_S_SHIFT;
   1209		writel_relaxed(tmp, pll->con_reg);
   1210
   1211		return 0;
   1212	}
   1213
   1214	/* Set PLL lock time. */
   1215	writel_relaxed(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg);
   1216
   1217	/* Change PLL PMS values */
   1218	tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) |
   1219			(PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) |
   1220			(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT));
   1221	tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) |
   1222			(rate->pdiv << PLL2550XX_P_SHIFT) |
   1223			(rate->sdiv << PLL2550XX_S_SHIFT);
   1224	writel_relaxed(tmp, pll->con_reg);
   1225
   1226	/* Wait for PLL lock */
   1227	return samsung_pll_lock_wait(pll,
   1228			PLL2550XX_LOCK_STAT_MASK << PLL2550XX_LOCK_STAT_SHIFT);
   1229}
   1230
   1231static const struct clk_ops samsung_pll2550xx_clk_ops = {
   1232	.recalc_rate = samsung_pll2550xx_recalc_rate,
   1233	.round_rate = samsung_pll_round_rate,
   1234	.set_rate = samsung_pll2550xx_set_rate,
   1235};
   1236
   1237static const struct clk_ops samsung_pll2550xx_clk_min_ops = {
   1238	.recalc_rate = samsung_pll2550xx_recalc_rate,
   1239};
   1240
   1241/*
   1242 * PLL2650x Clock Type
   1243 */
   1244
   1245/* Maximum lock time can be 3000 * PDIV cycles */
   1246#define PLL2650X_LOCK_FACTOR		3000
   1247
   1248#define PLL2650X_M_MASK			0x1ff
   1249#define PLL2650X_P_MASK			0x3f
   1250#define PLL2650X_S_MASK			0x7
   1251#define PLL2650X_K_MASK			0xffff
   1252#define PLL2650X_LOCK_STAT_MASK		0x1
   1253#define PLL2650X_M_SHIFT		16
   1254#define PLL2650X_P_SHIFT		8
   1255#define PLL2650X_S_SHIFT		0
   1256#define PLL2650X_K_SHIFT		0
   1257#define PLL2650X_LOCK_STAT_SHIFT	29
   1258#define PLL2650X_PLL_ENABLE_SHIFT	31
   1259
   1260static unsigned long samsung_pll2650x_recalc_rate(struct clk_hw *hw,
   1261				unsigned long parent_rate)
   1262{
   1263	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1264	u64 fout = parent_rate;
   1265	u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
   1266	s16 kdiv;
   1267
   1268	pll_con0 = readl_relaxed(pll->con_reg);
   1269	mdiv = (pll_con0 >> PLL2650X_M_SHIFT) & PLL2650X_M_MASK;
   1270	pdiv = (pll_con0 >> PLL2650X_P_SHIFT) & PLL2650X_P_MASK;
   1271	sdiv = (pll_con0 >> PLL2650X_S_SHIFT) & PLL2650X_S_MASK;
   1272
   1273	pll_con1 = readl_relaxed(pll->con_reg + 4);
   1274	kdiv = (s16)((pll_con1 >> PLL2650X_K_SHIFT) & PLL2650X_K_MASK);
   1275
   1276	fout *= (mdiv << 16) + kdiv;
   1277	do_div(fout, (pdiv << sdiv));
   1278	fout >>= 16;
   1279
   1280	return (unsigned long)fout;
   1281}
   1282
   1283static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate,
   1284					unsigned long prate)
   1285{
   1286	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1287	const struct samsung_pll_rate_table *rate;
   1288	u32 con0, con1;
   1289
   1290	/* Get required rate settings from table */
   1291	rate = samsung_get_pll_settings(pll, drate);
   1292	if (!rate) {
   1293		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
   1294			drate, clk_hw_get_name(hw));
   1295		return -EINVAL;
   1296	}
   1297
   1298	con0 = readl_relaxed(pll->con_reg);
   1299	con1 = readl_relaxed(pll->con_reg + 4);
   1300
   1301	/* Set PLL lock time. */
   1302	writel_relaxed(rate->pdiv * PLL2650X_LOCK_FACTOR, pll->lock_reg);
   1303
   1304	/* Change PLL PMS values */
   1305	con0 &= ~((PLL2650X_M_MASK << PLL2650X_M_SHIFT) |
   1306			(PLL2650X_P_MASK << PLL2650X_P_SHIFT) |
   1307			(PLL2650X_S_MASK << PLL2650X_S_SHIFT));
   1308	con0 |= (rate->mdiv << PLL2650X_M_SHIFT) |
   1309			(rate->pdiv << PLL2650X_P_SHIFT) |
   1310			(rate->sdiv << PLL2650X_S_SHIFT);
   1311	con0 |= (1 << PLL2650X_PLL_ENABLE_SHIFT);
   1312	writel_relaxed(con0, pll->con_reg);
   1313
   1314	con1 &= ~(PLL2650X_K_MASK << PLL2650X_K_SHIFT);
   1315	con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT);
   1316	writel_relaxed(con1, pll->con_reg + 4);
   1317
   1318	/* Wait for PLL lock */
   1319	return samsung_pll_lock_wait(pll,
   1320			PLL2650X_LOCK_STAT_MASK << PLL2650X_LOCK_STAT_SHIFT);
   1321}
   1322
   1323static const struct clk_ops samsung_pll2650x_clk_ops = {
   1324	.recalc_rate = samsung_pll2650x_recalc_rate,
   1325	.round_rate = samsung_pll_round_rate,
   1326	.set_rate = samsung_pll2650x_set_rate,
   1327};
   1328
   1329static const struct clk_ops samsung_pll2650x_clk_min_ops = {
   1330	.recalc_rate = samsung_pll2650x_recalc_rate,
   1331};
   1332
   1333/*
   1334 * PLL2650XX Clock Type
   1335 */
   1336
   1337/* Maximum lock time can be 3000 * PDIV cycles */
   1338#define PLL2650XX_LOCK_FACTOR 3000
   1339
   1340#define PLL2650XX_MDIV_SHIFT		9
   1341#define PLL2650XX_PDIV_SHIFT		3
   1342#define PLL2650XX_SDIV_SHIFT		0
   1343#define PLL2650XX_KDIV_SHIFT		0
   1344#define PLL2650XX_MDIV_MASK		0x1ff
   1345#define PLL2650XX_PDIV_MASK		0x3f
   1346#define PLL2650XX_SDIV_MASK		0x7
   1347#define PLL2650XX_KDIV_MASK		0xffff
   1348#define PLL2650XX_PLL_ENABLE_SHIFT	23
   1349#define PLL2650XX_PLL_LOCKTIME_SHIFT	21
   1350#define PLL2650XX_PLL_FOUTMASK_SHIFT	31
   1351
   1352static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw,
   1353				unsigned long parent_rate)
   1354{
   1355	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1356	u32 mdiv, pdiv, sdiv, pll_con0, pll_con2;
   1357	s16 kdiv;
   1358	u64 fvco = parent_rate;
   1359
   1360	pll_con0 = readl_relaxed(pll->con_reg);
   1361	pll_con2 = readl_relaxed(pll->con_reg + 8);
   1362	mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK;
   1363	pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK;
   1364	sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK;
   1365	kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK);
   1366
   1367	fvco *= (mdiv << 16) + kdiv;
   1368	do_div(fvco, (pdiv << sdiv));
   1369	fvco >>= 16;
   1370
   1371	return (unsigned long)fvco;
   1372}
   1373
   1374static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate,
   1375					unsigned long parent_rate)
   1376{
   1377	struct samsung_clk_pll *pll = to_clk_pll(hw);
   1378	u32 pll_con0, pll_con2;
   1379	const struct samsung_pll_rate_table *rate;
   1380
   1381	rate = samsung_get_pll_settings(pll, drate);
   1382	if (!rate) {
   1383		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
   1384			drate, clk_hw_get_name(hw));
   1385		return -EINVAL;
   1386	}
   1387
   1388	pll_con0 = readl_relaxed(pll->con_reg);
   1389	pll_con2 = readl_relaxed(pll->con_reg + 8);
   1390
   1391	 /* Change PLL PMS values */
   1392	pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT |
   1393			PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT |
   1394			PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT);
   1395	pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT;
   1396	pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT;
   1397	pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT;
   1398	pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT;
   1399	pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT;
   1400
   1401	pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT);
   1402	pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK)
   1403			<< PLL2650XX_KDIV_SHIFT;
   1404
   1405	/* Set PLL lock time. */
   1406	writel_relaxed(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg);
   1407
   1408	writel_relaxed(pll_con0, pll->con_reg);
   1409	writel_relaxed(pll_con2, pll->con_reg + 8);
   1410
   1411	return samsung_pll_lock_wait(pll, 0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT);
   1412}
   1413
   1414static const struct clk_ops samsung_pll2650xx_clk_ops = {
   1415	.recalc_rate = samsung_pll2650xx_recalc_rate,
   1416	.set_rate = samsung_pll2650xx_set_rate,
   1417	.round_rate = samsung_pll_round_rate,
   1418};
   1419
   1420static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
   1421	.recalc_rate = samsung_pll2650xx_recalc_rate,
   1422};
   1423
   1424static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
   1425				const struct samsung_pll_clock *pll_clk,
   1426				void __iomem *base)
   1427{
   1428	struct samsung_clk_pll *pll;
   1429	struct clk_init_data init;
   1430	int ret, len;
   1431
   1432	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
   1433	if (!pll) {
   1434		pr_err("%s: could not allocate pll clk %s\n",
   1435			__func__, pll_clk->name);
   1436		return;
   1437	}
   1438
   1439	init.name = pll_clk->name;
   1440	init.flags = pll_clk->flags;
   1441	init.parent_names = &pll_clk->parent_name;
   1442	init.num_parents = 1;
   1443
   1444	if (pll_clk->rate_table) {
   1445		/* find count of rates in rate_table */
   1446		for (len = 0; pll_clk->rate_table[len].rate != 0; )
   1447			len++;
   1448
   1449		pll->rate_count = len;
   1450		pll->rate_table = kmemdup(pll_clk->rate_table,
   1451					pll->rate_count *
   1452					sizeof(struct samsung_pll_rate_table),
   1453					GFP_KERNEL);
   1454		WARN(!pll->rate_table,
   1455			"%s: could not allocate rate table for %s\n",
   1456			__func__, pll_clk->name);
   1457	}
   1458
   1459	switch (pll_clk->type) {
   1460	case pll_2126:
   1461		init.ops = &samsung_pll2126_clk_ops;
   1462		break;
   1463	case pll_3000:
   1464		init.ops = &samsung_pll3000_clk_ops;
   1465		break;
   1466	/* clk_ops for 35xx and 2550 are similar */
   1467	case pll_35xx:
   1468	case pll_2550:
   1469	case pll_1450x:
   1470	case pll_1451x:
   1471	case pll_1452x:
   1472	case pll_142xx:
   1473		pll->enable_offs = PLL35XX_ENABLE_SHIFT;
   1474		pll->lock_offs = PLL35XX_LOCK_STAT_SHIFT;
   1475		if (!pll->rate_table)
   1476			init.ops = &samsung_pll35xx_clk_min_ops;
   1477		else
   1478			init.ops = &samsung_pll35xx_clk_ops;
   1479		break;
   1480	case pll_1417x:
   1481	case pll_0822x:
   1482		pll->enable_offs = PLL0822X_ENABLE_SHIFT;
   1483		pll->lock_offs = PLL0822X_LOCK_STAT_SHIFT;
   1484		if (!pll->rate_table)
   1485			init.ops = &samsung_pll0822x_clk_min_ops;
   1486		else
   1487			init.ops = &samsung_pll0822x_clk_ops;
   1488		break;
   1489	case pll_4500:
   1490		init.ops = &samsung_pll45xx_clk_min_ops;
   1491		break;
   1492	case pll_4502:
   1493	case pll_4508:
   1494		if (!pll->rate_table)
   1495			init.ops = &samsung_pll45xx_clk_min_ops;
   1496		else
   1497			init.ops = &samsung_pll45xx_clk_ops;
   1498		break;
   1499	/* clk_ops for 36xx and 2650 are similar */
   1500	case pll_36xx:
   1501	case pll_2650:
   1502		pll->enable_offs = PLL36XX_ENABLE_SHIFT;
   1503		pll->lock_offs = PLL36XX_LOCK_STAT_SHIFT;
   1504		if (!pll->rate_table)
   1505			init.ops = &samsung_pll36xx_clk_min_ops;
   1506		else
   1507			init.ops = &samsung_pll36xx_clk_ops;
   1508		break;
   1509	case pll_0831x:
   1510		pll->enable_offs = PLL0831X_ENABLE_SHIFT;
   1511		pll->lock_offs = PLL0831X_LOCK_STAT_SHIFT;
   1512		if (!pll->rate_table)
   1513			init.ops = &samsung_pll0831x_clk_min_ops;
   1514		else
   1515			init.ops = &samsung_pll0831x_clk_ops;
   1516		break;
   1517	case pll_6552:
   1518	case pll_6552_s3c2416:
   1519		init.ops = &samsung_pll6552_clk_ops;
   1520		break;
   1521	case pll_6553:
   1522		init.ops = &samsung_pll6553_clk_ops;
   1523		break;
   1524	case pll_4600:
   1525	case pll_4650:
   1526	case pll_4650c:
   1527	case pll_1460x:
   1528		if (!pll->rate_table)
   1529			init.ops = &samsung_pll46xx_clk_min_ops;
   1530		else
   1531			init.ops = &samsung_pll46xx_clk_ops;
   1532		break;
   1533	case pll_s3c2410_mpll:
   1534		if (!pll->rate_table)
   1535			init.ops = &samsung_s3c2410_mpll_clk_min_ops;
   1536		else
   1537			init.ops = &samsung_s3c2410_mpll_clk_ops;
   1538		break;
   1539	case pll_s3c2410_upll:
   1540		if (!pll->rate_table)
   1541			init.ops = &samsung_s3c2410_upll_clk_min_ops;
   1542		else
   1543			init.ops = &samsung_s3c2410_upll_clk_ops;
   1544		break;
   1545	case pll_s3c2440_mpll:
   1546		if (!pll->rate_table)
   1547			init.ops = &samsung_s3c2440_mpll_clk_min_ops;
   1548		else
   1549			init.ops = &samsung_s3c2440_mpll_clk_ops;
   1550		break;
   1551	case pll_2550x:
   1552		init.ops = &samsung_pll2550x_clk_ops;
   1553		break;
   1554	case pll_2550xx:
   1555		if (!pll->rate_table)
   1556			init.ops = &samsung_pll2550xx_clk_min_ops;
   1557		else
   1558			init.ops = &samsung_pll2550xx_clk_ops;
   1559		break;
   1560	case pll_2650x:
   1561		if (!pll->rate_table)
   1562			init.ops = &samsung_pll2650x_clk_min_ops;
   1563		else
   1564			init.ops = &samsung_pll2650x_clk_ops;
   1565		break;
   1566	case pll_2650xx:
   1567		if (!pll->rate_table)
   1568			init.ops = &samsung_pll2650xx_clk_min_ops;
   1569		else
   1570			init.ops = &samsung_pll2650xx_clk_ops;
   1571		break;
   1572	default:
   1573		pr_warn("%s: Unknown pll type for pll clk %s\n",
   1574			__func__, pll_clk->name);
   1575	}
   1576
   1577	pll->hw.init = &init;
   1578	pll->type = pll_clk->type;
   1579	pll->lock_reg = base + pll_clk->lock_offset;
   1580	pll->con_reg = base + pll_clk->con_offset;
   1581
   1582	ret = clk_hw_register(ctx->dev, &pll->hw);
   1583	if (ret) {
   1584		pr_err("%s: failed to register pll clock %s : %d\n",
   1585			__func__, pll_clk->name, ret);
   1586		kfree(pll);
   1587		return;
   1588	}
   1589
   1590	samsung_clk_add_lookup(ctx, &pll->hw, pll_clk->id);
   1591}
   1592
   1593void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
   1594			const struct samsung_pll_clock *pll_list,
   1595			unsigned int nr_pll, void __iomem *base)
   1596{
   1597	int cnt;
   1598
   1599	for (cnt = 0; cnt < nr_pll; cnt++)
   1600		_samsung_clk_register_pll(ctx, &pll_list[cnt], base);
   1601}