Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
0004  * Copyright (c) 2013 Linaro Ltd.
0005  *
0006  * This file contains the utility functions to register the pll clocks.
0007 */
0008 
0009 #include <linux/errno.h>
0010 #include <linux/hrtimer.h>
0011 #include <linux/iopoll.h>
0012 #include <linux/delay.h>
0013 #include <linux/slab.h>
0014 #include <linux/timekeeping.h>
0015 #include <linux/clk-provider.h>
0016 #include <linux/io.h>
0017 #include "clk.h"
0018 #include "clk-pll.h"
0019 
0020 #define PLL_TIMEOUT_US      20000U
0021 #define PLL_TIMEOUT_LOOPS   1000000U
0022 
0023 struct samsung_clk_pll {
0024     struct clk_hw       hw;
0025     void __iomem        *lock_reg;
0026     void __iomem        *con_reg;
0027     /* PLL enable control bit offset in @con_reg register */
0028     unsigned short      enable_offs;
0029     /* PLL lock status bit offset in @con_reg register */
0030     unsigned short      lock_offs;
0031     enum samsung_pll_type   type;
0032     unsigned int        rate_count;
0033     const struct samsung_pll_rate_table *rate_table;
0034 };
0035 
0036 #define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
0037 
0038 static const struct samsung_pll_rate_table *samsung_get_pll_settings(
0039                 struct samsung_clk_pll *pll, unsigned long rate)
0040 {
0041     const struct samsung_pll_rate_table  *rate_table = pll->rate_table;
0042     int i;
0043 
0044     for (i = 0; i < pll->rate_count; i++) {
0045         if (rate == rate_table[i].rate)
0046             return &rate_table[i];
0047     }
0048 
0049     return NULL;
0050 }
0051 
0052 static long samsung_pll_round_rate(struct clk_hw *hw,
0053             unsigned long drate, unsigned long *prate)
0054 {
0055     struct samsung_clk_pll *pll = to_clk_pll(hw);
0056     const struct samsung_pll_rate_table *rate_table = pll->rate_table;
0057     int i;
0058 
0059     /* Assumming rate_table is in descending order */
0060     for (i = 0; i < pll->rate_count; i++) {
0061         if (drate >= rate_table[i].rate)
0062             return rate_table[i].rate;
0063     }
0064 
0065     /* return minimum supported value */
0066     return rate_table[i - 1].rate;
0067 }
0068 
0069 static bool pll_early_timeout = true;
0070 
0071 static int __init samsung_pll_disable_early_timeout(void)
0072 {
0073     pll_early_timeout = false;
0074     return 0;
0075 }
0076 arch_initcall(samsung_pll_disable_early_timeout);
0077 
0078 /* Wait until the PLL is locked */
0079 static int samsung_pll_lock_wait(struct samsung_clk_pll *pll,
0080                  unsigned int reg_mask)
0081 {
0082     int i, ret;
0083     u32 val;
0084 
0085     /*
0086      * This function might be called when the timekeeping API can't be used
0087      * to detect timeouts. One situation is when the clocksource is not yet
0088      * initialized, another when the timekeeping is suspended. udelay() also
0089      * cannot be used when the clocksource is not running on arm64, since
0090      * the current timer is used as cycle counter. So a simple busy loop
0091      * is used here in that special cases. The limit of iterations has been
0092      * derived from experimental measurements of various PLLs on multiple
0093      * Exynos SoC variants. Single register read time was usually in range
0094      * 0.4...1.5 us, never less than 0.4 us.
0095      */
0096     if (pll_early_timeout || timekeeping_suspended) {
0097         i = PLL_TIMEOUT_LOOPS;
0098         while (i-- > 0) {
0099             if (readl_relaxed(pll->con_reg) & reg_mask)
0100                 return 0;
0101 
0102             cpu_relax();
0103         }
0104         ret = -ETIMEDOUT;
0105     } else {
0106         ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val,
0107                     val & reg_mask, 0, PLL_TIMEOUT_US);
0108     }
0109 
0110     if (ret < 0)
0111         pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw));
0112 
0113     return ret;
0114 }
0115 
0116 static int samsung_pll3xxx_enable(struct clk_hw *hw)
0117 {
0118     struct samsung_clk_pll *pll = to_clk_pll(hw);
0119     u32 tmp;
0120 
0121     tmp = readl_relaxed(pll->con_reg);
0122     tmp |= BIT(pll->enable_offs);
0123     writel_relaxed(tmp, pll->con_reg);
0124 
0125     return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
0126 }
0127 
0128 static void samsung_pll3xxx_disable(struct clk_hw *hw)
0129 {
0130     struct samsung_clk_pll *pll = to_clk_pll(hw);
0131     u32 tmp;
0132 
0133     tmp = readl_relaxed(pll->con_reg);
0134     tmp &= ~BIT(pll->enable_offs);
0135     writel_relaxed(tmp, pll->con_reg);
0136 }
0137 
0138 /*
0139  * PLL2126 Clock Type
0140  */
0141 
0142 #define PLL2126_MDIV_MASK   (0xff)
0143 #define PLL2126_PDIV_MASK   (0x3f)
0144 #define PLL2126_SDIV_MASK   (0x3)
0145 #define PLL2126_MDIV_SHIFT  (16)
0146 #define PLL2126_PDIV_SHIFT  (8)
0147 #define PLL2126_SDIV_SHIFT  (0)
0148 
0149 static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw,
0150                 unsigned long parent_rate)
0151 {
0152     struct samsung_clk_pll *pll = to_clk_pll(hw);
0153     u32 pll_con, mdiv, pdiv, sdiv;
0154     u64 fvco = parent_rate;
0155 
0156     pll_con = readl_relaxed(pll->con_reg);
0157     mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK;
0158     pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK;
0159     sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK;
0160 
0161     fvco *= (mdiv + 8);
0162     do_div(fvco, (pdiv + 2) << sdiv);
0163 
0164     return (unsigned long)fvco;
0165 }
0166 
0167 static const struct clk_ops samsung_pll2126_clk_ops = {
0168     .recalc_rate = samsung_pll2126_recalc_rate,
0169 };
0170 
0171 /*
0172  * PLL3000 Clock Type
0173  */
0174 
0175 #define PLL3000_MDIV_MASK   (0xff)
0176 #define PLL3000_PDIV_MASK   (0x3)
0177 #define PLL3000_SDIV_MASK   (0x3)
0178 #define PLL3000_MDIV_SHIFT  (16)
0179 #define PLL3000_PDIV_SHIFT  (8)
0180 #define PLL3000_SDIV_SHIFT  (0)
0181 
0182 static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
0183                 unsigned long parent_rate)
0184 {
0185     struct samsung_clk_pll *pll = to_clk_pll(hw);
0186     u32 pll_con, mdiv, pdiv, sdiv;
0187     u64 fvco = parent_rate;
0188 
0189     pll_con = readl_relaxed(pll->con_reg);
0190     mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK;
0191     pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK;
0192     sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK;
0193 
0194     fvco *= (2 * (mdiv + 8));
0195     do_div(fvco, pdiv << sdiv);
0196 
0197     return (unsigned long)fvco;
0198 }
0199 
0200 static const struct clk_ops samsung_pll3000_clk_ops = {
0201     .recalc_rate = samsung_pll3000_recalc_rate,
0202 };
0203 
0204 /*
0205  * PLL35xx Clock Type
0206  */
0207 /* Maximum lock time can be 270 * PDIV cycles */
0208 #define PLL35XX_LOCK_FACTOR (270)
0209 
0210 #define PLL35XX_MDIV_MASK       (0x3FF)
0211 #define PLL35XX_PDIV_MASK       (0x3F)
0212 #define PLL35XX_SDIV_MASK       (0x7)
0213 #define PLL35XX_MDIV_SHIFT      (16)
0214 #define PLL35XX_PDIV_SHIFT      (8)
0215 #define PLL35XX_SDIV_SHIFT      (0)
0216 #define PLL35XX_LOCK_STAT_SHIFT (29)
0217 #define PLL35XX_ENABLE_SHIFT    (31)
0218 
0219 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
0220                 unsigned long parent_rate)
0221 {
0222     struct samsung_clk_pll *pll = to_clk_pll(hw);
0223     u32 mdiv, pdiv, sdiv, pll_con;
0224     u64 fvco = parent_rate;
0225 
0226     pll_con = readl_relaxed(pll->con_reg);
0227     mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
0228     pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
0229     sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
0230 
0231     fvco *= mdiv;
0232     do_div(fvco, (pdiv << sdiv));
0233 
0234     return (unsigned long)fvco;
0235 }
0236 
0237 static inline bool samsung_pll35xx_mp_change(
0238         const struct samsung_pll_rate_table *rate, u32 pll_con)
0239 {
0240     u32 old_mdiv, old_pdiv;
0241 
0242     old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
0243     old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
0244 
0245     return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
0246 }
0247 
0248 static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
0249                     unsigned long prate)
0250 {
0251     struct samsung_clk_pll *pll = to_clk_pll(hw);
0252     const struct samsung_pll_rate_table *rate;
0253     u32 tmp;
0254 
0255     /* Get required rate settings from table */
0256     rate = samsung_get_pll_settings(pll, drate);
0257     if (!rate) {
0258         pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
0259             drate, clk_hw_get_name(hw));
0260         return -EINVAL;
0261     }
0262 
0263     tmp = readl_relaxed(pll->con_reg);
0264 
0265     if (!(samsung_pll35xx_mp_change(rate, tmp))) {
0266         /* If only s change, change just s value only*/
0267         tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
0268         tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
0269         writel_relaxed(tmp, pll->con_reg);
0270 
0271         return 0;
0272     }
0273 
0274     /* Set PLL lock time. */
0275     writel_relaxed(rate->pdiv * PLL35XX_LOCK_FACTOR,
0276             pll->lock_reg);
0277 
0278     /* Change PLL PMS values */
0279     tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
0280             (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
0281             (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
0282     tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
0283             (rate->pdiv << PLL35XX_PDIV_SHIFT) |
0284             (rate->sdiv << PLL35XX_SDIV_SHIFT);
0285     writel_relaxed(tmp, pll->con_reg);
0286 
0287     /* Wait for PLL lock if the PLL is enabled */
0288     if (tmp & BIT(pll->enable_offs))
0289         return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
0290 
0291     return 0;
0292 }
0293 
0294 static const struct clk_ops samsung_pll35xx_clk_ops = {
0295     .recalc_rate = samsung_pll35xx_recalc_rate,
0296     .round_rate = samsung_pll_round_rate,
0297     .set_rate = samsung_pll35xx_set_rate,
0298     .enable = samsung_pll3xxx_enable,
0299     .disable = samsung_pll3xxx_disable,
0300 };
0301 
0302 static const struct clk_ops samsung_pll35xx_clk_min_ops = {
0303     .recalc_rate = samsung_pll35xx_recalc_rate,
0304 };
0305 
0306 /*
0307  * PLL36xx Clock Type
0308  */
0309 /* Maximum lock time can be 3000 * PDIV cycles */
0310 #define PLL36XX_LOCK_FACTOR    (3000)
0311 
0312 #define PLL36XX_KDIV_MASK   (0xFFFF)
0313 #define PLL36XX_MDIV_MASK   (0x1FF)
0314 #define PLL36XX_PDIV_MASK   (0x3F)
0315 #define PLL36XX_SDIV_MASK   (0x7)
0316 #define PLL36XX_MDIV_SHIFT  (16)
0317 #define PLL36XX_PDIV_SHIFT  (8)
0318 #define PLL36XX_SDIV_SHIFT  (0)
0319 #define PLL36XX_KDIV_SHIFT  (0)
0320 #define PLL36XX_LOCK_STAT_SHIFT (29)
0321 #define PLL36XX_ENABLE_SHIFT    (31)
0322 
0323 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
0324                 unsigned long parent_rate)
0325 {
0326     struct samsung_clk_pll *pll = to_clk_pll(hw);
0327     u32 mdiv, pdiv, sdiv, pll_con0, pll_con1;
0328     s16 kdiv;
0329     u64 fvco = parent_rate;
0330 
0331     pll_con0 = readl_relaxed(pll->con_reg);
0332     pll_con1 = readl_relaxed(pll->con_reg + 4);
0333     mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
0334     pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
0335     sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
0336     kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK);
0337 
0338     fvco *= (mdiv << 16) + kdiv;
0339     do_div(fvco, (pdiv << sdiv));
0340     fvco >>= 16;
0341 
0342     return (unsigned long)fvco;
0343 }
0344 
0345 static inline bool samsung_pll36xx_mpk_change(
0346     const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
0347 {
0348     u32 old_mdiv, old_pdiv, old_kdiv;
0349 
0350     old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
0351     old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
0352     old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
0353 
0354     return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
0355         rate->kdiv != old_kdiv);
0356 }
0357 
0358 static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
0359                     unsigned long parent_rate)
0360 {
0361     struct samsung_clk_pll *pll = to_clk_pll(hw);
0362     u32 pll_con0, pll_con1;
0363     const struct samsung_pll_rate_table *rate;
0364 
0365     rate = samsung_get_pll_settings(pll, drate);
0366     if (!rate) {
0367         pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
0368             drate, clk_hw_get_name(hw));
0369         return -EINVAL;
0370     }
0371 
0372     pll_con0 = readl_relaxed(pll->con_reg);
0373     pll_con1 = readl_relaxed(pll->con_reg + 4);
0374 
0375     if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
0376         /* If only s change, change just s value only*/
0377         pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
0378         pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
0379         writel_relaxed(pll_con0, pll->con_reg);
0380 
0381         return 0;
0382     }
0383 
0384     /* Set PLL lock time. */
0385     writel_relaxed(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
0386 
0387      /* Change PLL PMS values */
0388     pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
0389             (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
0390             (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
0391     pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
0392             (rate->pdiv << PLL36XX_PDIV_SHIFT) |
0393             (rate->sdiv << PLL36XX_SDIV_SHIFT);
0394     writel_relaxed(pll_con0, pll->con_reg);
0395 
0396     pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
0397     pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
0398     writel_relaxed(pll_con1, pll->con_reg + 4);
0399 
0400     if (pll_con0 & BIT(pll->enable_offs))
0401         return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
0402 
0403     return 0;
0404 }
0405 
0406 static const struct clk_ops samsung_pll36xx_clk_ops = {
0407     .recalc_rate = samsung_pll36xx_recalc_rate,
0408     .set_rate = samsung_pll36xx_set_rate,
0409     .round_rate = samsung_pll_round_rate,
0410     .enable = samsung_pll3xxx_enable,
0411     .disable = samsung_pll3xxx_disable,
0412 };
0413 
0414 static const struct clk_ops samsung_pll36xx_clk_min_ops = {
0415     .recalc_rate = samsung_pll36xx_recalc_rate,
0416 };
0417 
0418 /*
0419  * PLL0822x Clock Type
0420  */
0421 /* Maximum lock time can be 150 * PDIV cycles */
0422 #define PLL0822X_LOCK_FACTOR        (150)
0423 
0424 #define PLL0822X_MDIV_MASK      (0x3FF)
0425 #define PLL0822X_PDIV_MASK      (0x3F)
0426 #define PLL0822X_SDIV_MASK      (0x7)
0427 #define PLL0822X_MDIV_SHIFT     (16)
0428 #define PLL0822X_PDIV_SHIFT     (8)
0429 #define PLL0822X_SDIV_SHIFT     (0)
0430 #define PLL0822X_LOCK_STAT_SHIFT    (29)
0431 #define PLL0822X_ENABLE_SHIFT       (31)
0432 
0433 static unsigned long samsung_pll0822x_recalc_rate(struct clk_hw *hw,
0434                           unsigned long parent_rate)
0435 {
0436     struct samsung_clk_pll *pll = to_clk_pll(hw);
0437     u32 mdiv, pdiv, sdiv, pll_con3;
0438     u64 fvco = parent_rate;
0439 
0440     pll_con3 = readl_relaxed(pll->con_reg);
0441     mdiv = (pll_con3 >> PLL0822X_MDIV_SHIFT) & PLL0822X_MDIV_MASK;
0442     pdiv = (pll_con3 >> PLL0822X_PDIV_SHIFT) & PLL0822X_PDIV_MASK;
0443     sdiv = (pll_con3 >> PLL0822X_SDIV_SHIFT) & PLL0822X_SDIV_MASK;
0444 
0445     fvco *= mdiv;
0446     do_div(fvco, (pdiv << sdiv));
0447 
0448     return (unsigned long)fvco;
0449 }
0450 
0451 static int samsung_pll0822x_set_rate(struct clk_hw *hw, unsigned long drate,
0452                      unsigned long prate)
0453 {
0454     const struct samsung_pll_rate_table *rate;
0455     struct samsung_clk_pll *pll = to_clk_pll(hw);
0456     u32 pll_con3;
0457 
0458     /* Get required rate settings from table */
0459     rate = samsung_get_pll_settings(pll, drate);
0460     if (!rate) {
0461         pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
0462             drate, clk_hw_get_name(hw));
0463         return -EINVAL;
0464     }
0465 
0466     /* Change PLL PMS values */
0467     pll_con3 = readl_relaxed(pll->con_reg);
0468     pll_con3 &= ~((PLL0822X_MDIV_MASK << PLL0822X_MDIV_SHIFT) |
0469             (PLL0822X_PDIV_MASK << PLL0822X_PDIV_SHIFT) |
0470             (PLL0822X_SDIV_MASK << PLL0822X_SDIV_SHIFT));
0471     pll_con3 |= (rate->mdiv << PLL0822X_MDIV_SHIFT) |
0472             (rate->pdiv << PLL0822X_PDIV_SHIFT) |
0473             (rate->sdiv << PLL0822X_SDIV_SHIFT);
0474 
0475     /* Set PLL lock time */
0476     writel_relaxed(rate->pdiv * PLL0822X_LOCK_FACTOR,
0477             pll->lock_reg);
0478 
0479     /* Write PMS values */
0480     writel_relaxed(pll_con3, pll->con_reg);
0481 
0482     /* Wait for PLL lock if the PLL is enabled */
0483     if (pll_con3 & BIT(pll->enable_offs))
0484         return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
0485 
0486     return 0;
0487 }
0488 
0489 static const struct clk_ops samsung_pll0822x_clk_ops = {
0490     .recalc_rate = samsung_pll0822x_recalc_rate,
0491     .round_rate = samsung_pll_round_rate,
0492     .set_rate = samsung_pll0822x_set_rate,
0493     .enable = samsung_pll3xxx_enable,
0494     .disable = samsung_pll3xxx_disable,
0495 };
0496 
0497 static const struct clk_ops samsung_pll0822x_clk_min_ops = {
0498     .recalc_rate = samsung_pll0822x_recalc_rate,
0499 };
0500 
0501 /*
0502  * PLL0831x Clock Type
0503  */
0504 /* Maximum lock time can be 500 * PDIV cycles */
0505 #define PLL0831X_LOCK_FACTOR        (500)
0506 
0507 #define PLL0831X_KDIV_MASK      (0xFFFF)
0508 #define PLL0831X_MDIV_MASK      (0x1FF)
0509 #define PLL0831X_PDIV_MASK      (0x3F)
0510 #define PLL0831X_SDIV_MASK      (0x7)
0511 #define PLL0831X_MDIV_SHIFT     (16)
0512 #define PLL0831X_PDIV_SHIFT     (8)
0513 #define PLL0831X_SDIV_SHIFT     (0)
0514 #define PLL0831X_KDIV_SHIFT     (0)
0515 #define PLL0831X_LOCK_STAT_SHIFT    (29)
0516 #define PLL0831X_ENABLE_SHIFT       (31)
0517 
0518 static unsigned long samsung_pll0831x_recalc_rate(struct clk_hw *hw,
0519                           unsigned long parent_rate)
0520 {
0521     struct samsung_clk_pll *pll = to_clk_pll(hw);
0522     u32 mdiv, pdiv, sdiv, pll_con3, pll_con5;
0523     s16 kdiv;
0524     u64 fvco = parent_rate;
0525 
0526     pll_con3 = readl_relaxed(pll->con_reg);
0527     pll_con5 = readl_relaxed(pll->con_reg + 8);
0528     mdiv = (pll_con3 >> PLL0831X_MDIV_SHIFT) & PLL0831X_MDIV_MASK;
0529     pdiv = (pll_con3 >> PLL0831X_PDIV_SHIFT) & PLL0831X_PDIV_MASK;
0530     sdiv = (pll_con3 >> PLL0831X_SDIV_SHIFT) & PLL0831X_SDIV_MASK;
0531     kdiv = (s16)((pll_con5 >> PLL0831X_KDIV_SHIFT) & PLL0831X_KDIV_MASK);
0532 
0533     fvco *= (mdiv << 16) + kdiv;
0534     do_div(fvco, (pdiv << sdiv));
0535     fvco >>= 16;
0536 
0537     return (unsigned long)fvco;
0538 }
0539 
0540 static int samsung_pll0831x_set_rate(struct clk_hw *hw, unsigned long drate,
0541                      unsigned long parent_rate)
0542 {
0543     const struct samsung_pll_rate_table *rate;
0544     struct samsung_clk_pll *pll = to_clk_pll(hw);
0545     u32 pll_con3, pll_con5;
0546 
0547     /* Get required rate settings from table */
0548     rate = samsung_get_pll_settings(pll, drate);
0549     if (!rate) {
0550         pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
0551             drate, clk_hw_get_name(hw));
0552         return -EINVAL;
0553     }
0554 
0555     pll_con3 = readl_relaxed(pll->con_reg);
0556     pll_con5 = readl_relaxed(pll->con_reg + 8);
0557 
0558     /* Change PLL PMSK values */
0559     pll_con3 &= ~((PLL0831X_MDIV_MASK << PLL0831X_MDIV_SHIFT) |
0560             (PLL0831X_PDIV_MASK << PLL0831X_PDIV_SHIFT) |
0561             (PLL0831X_SDIV_MASK << PLL0831X_SDIV_SHIFT));
0562     pll_con3 |= (rate->mdiv << PLL0831X_MDIV_SHIFT) |
0563             (rate->pdiv << PLL0831X_PDIV_SHIFT) |
0564             (rate->sdiv << PLL0831X_SDIV_SHIFT);
0565     pll_con5 &= ~(PLL0831X_KDIV_MASK << PLL0831X_KDIV_SHIFT);
0566     /*
0567      * kdiv is 16-bit 2's complement (s16), but stored as unsigned int.
0568      * Cast it to u16 to avoid leading 0xffff's in case of negative value.
0569      */
0570     pll_con5 |= ((u16)rate->kdiv << PLL0831X_KDIV_SHIFT);
0571 
0572     /* Set PLL lock time */
0573     writel_relaxed(rate->pdiv * PLL0831X_LOCK_FACTOR, pll->lock_reg);
0574 
0575     /* Write PMSK values */
0576     writel_relaxed(pll_con3, pll->con_reg);
0577     writel_relaxed(pll_con5, pll->con_reg + 8);
0578 
0579     /* Wait for PLL lock if the PLL is enabled */
0580     if (pll_con3 & BIT(pll->enable_offs))
0581         return samsung_pll_lock_wait(pll, BIT(pll->lock_offs));
0582 
0583     return 0;
0584 }
0585 
0586 static const struct clk_ops samsung_pll0831x_clk_ops = {
0587     .recalc_rate = samsung_pll0831x_recalc_rate,
0588     .set_rate = samsung_pll0831x_set_rate,
0589     .round_rate = samsung_pll_round_rate,
0590     .enable = samsung_pll3xxx_enable,
0591     .disable = samsung_pll3xxx_disable,
0592 };
0593 
0594 static const struct clk_ops samsung_pll0831x_clk_min_ops = {
0595     .recalc_rate = samsung_pll0831x_recalc_rate,
0596 };
0597 
0598 /*
0599  * PLL45xx Clock Type
0600  */
0601 #define PLL4502_LOCK_FACTOR 400
0602 #define PLL4508_LOCK_FACTOR 240
0603 
0604 #define PLL45XX_MDIV_MASK   (0x3FF)
0605 #define PLL45XX_PDIV_MASK   (0x3F)
0606 #define PLL45XX_SDIV_MASK   (0x7)
0607 #define PLL45XX_AFC_MASK    (0x1F)
0608 #define PLL45XX_MDIV_SHIFT  (16)
0609 #define PLL45XX_PDIV_SHIFT  (8)
0610 #define PLL45XX_SDIV_SHIFT  (0)
0611 #define PLL45XX_AFC_SHIFT   (0)
0612 
0613 #define PLL45XX_ENABLE      BIT(31)
0614 #define PLL45XX_LOCKED      BIT(29)
0615 
0616 static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
0617                 unsigned long parent_rate)
0618 {
0619     struct samsung_clk_pll *pll = to_clk_pll(hw);
0620     u32 mdiv, pdiv, sdiv, pll_con;
0621     u64 fvco = parent_rate;
0622 
0623     pll_con = readl_relaxed(pll->con_reg);
0624     mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
0625     pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
0626     sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
0627 
0628     if (pll->type == pll_4508)
0629         sdiv = sdiv - 1;
0630 
0631     fvco *= mdiv;
0632     do_div(fvco, (pdiv << sdiv));
0633 
0634     return (unsigned long)fvco;
0635 }
0636 
0637 static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
0638                 const struct samsung_pll_rate_table *rate)
0639 {
0640     u32 old_mdiv, old_pdiv, old_afc;
0641 
0642     old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
0643     old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
0644     old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK;
0645 
0646     return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
0647         || old_afc != rate->afc);
0648 }
0649 
0650 static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
0651                     unsigned long prate)
0652 {
0653     struct samsung_clk_pll *pll = to_clk_pll(hw);
0654     const struct samsung_pll_rate_table *rate;
0655     u32 con0, con1;
0656 
0657     /* Get required rate settings from table */
0658     rate = samsung_get_pll_settings(pll, drate);
0659     if (!rate) {
0660         pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
0661             drate, clk_hw_get_name(hw));
0662         return -EINVAL;
0663     }
0664 
0665     con0 = readl_relaxed(pll->con_reg);
0666     con1 = readl_relaxed(pll->con_reg + 0x4);
0667 
0668     if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
0669         /* If only s change, change just s value only*/
0670         con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
0671         con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
0672         writel_relaxed(con0, pll->con_reg);
0673 
0674         return 0;
0675     }
0676 
0677     /* Set PLL PMS values. */
0678     con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) |
0679             (PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) |
0680             (PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT));
0681     con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) |
0682             (rate->pdiv << PLL45XX_PDIV_SHIFT) |
0683             (rate->sdiv << PLL45XX_SDIV_SHIFT);
0684 
0685     /* Set PLL AFC value. */
0686     con1 = readl_relaxed(pll->con_reg + 0x4);
0687     con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
0688     con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
0689 
0690     /* Set PLL lock time. */
0691     switch (pll->type) {
0692     case pll_4502:
0693         writel_relaxed(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
0694         break;
0695     case pll_4508:
0696         writel_relaxed(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
0697         break;
0698     default:
0699         break;
0700     }
0701 
0702     /* Set new configuration. */
0703     writel_relaxed(con1, pll->con_reg + 0x4);
0704     writel_relaxed(con0, pll->con_reg);
0705 
0706     /* Wait for PLL lock */
0707     return samsung_pll_lock_wait(pll, PLL45XX_LOCKED);
0708 }
0709 
0710 static const struct clk_ops samsung_pll45xx_clk_ops = {
0711     .recalc_rate = samsung_pll45xx_recalc_rate,
0712     .round_rate = samsung_pll_round_rate,
0713     .set_rate = samsung_pll45xx_set_rate,
0714 };
0715 
0716 static const struct clk_ops samsung_pll45xx_clk_min_ops = {
0717     .recalc_rate = samsung_pll45xx_recalc_rate,
0718 };
0719 
0720 /*
0721  * PLL46xx Clock Type
0722  */
0723 #define PLL46XX_LOCK_FACTOR 3000
0724 
0725 #define PLL46XX_VSEL_MASK   (1)
0726 #define PLL46XX_MDIV_MASK   (0x1FF)
0727 #define PLL1460X_MDIV_MASK  (0x3FF)
0728 
0729 #define PLL46XX_PDIV_MASK   (0x3F)
0730 #define PLL46XX_SDIV_MASK   (0x7)
0731 #define PLL46XX_VSEL_SHIFT  (27)
0732 #define PLL46XX_MDIV_SHIFT  (16)
0733 #define PLL46XX_PDIV_SHIFT  (8)
0734 #define PLL46XX_SDIV_SHIFT  (0)
0735 
0736 #define PLL46XX_KDIV_MASK   (0xFFFF)
0737 #define PLL4650C_KDIV_MASK  (0xFFF)
0738 #define PLL46XX_KDIV_SHIFT  (0)
0739 #define PLL46XX_MFR_MASK    (0x3F)
0740 #define PLL46XX_MRR_MASK    (0x1F)
0741 #define PLL46XX_KDIV_SHIFT  (0)
0742 #define PLL46XX_MFR_SHIFT   (16)
0743 #define PLL46XX_MRR_SHIFT   (24)
0744 
0745 #define PLL46XX_ENABLE      BIT(31)
0746 #define PLL46XX_LOCKED      BIT(29)
0747 #define PLL46XX_VSEL        BIT(27)
0748 
0749 static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
0750                 unsigned long parent_rate)
0751 {
0752     struct samsung_clk_pll *pll = to_clk_pll(hw);
0753     u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
0754     u64 fvco = parent_rate;
0755 
0756     pll_con0 = readl_relaxed(pll->con_reg);
0757     pll_con1 = readl_relaxed(pll->con_reg + 4);
0758     mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & ((pll->type == pll_1460x) ?
0759                 PLL1460X_MDIV_MASK : PLL46XX_MDIV_MASK);
0760     pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
0761     sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
0762     kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
0763                     pll_con1 & PLL46XX_KDIV_MASK;
0764 
0765     shift = ((pll->type == pll_4600) || (pll->type == pll_1460x)) ? 16 : 10;
0766 
0767     fvco *= (mdiv << shift) + kdiv;
0768     do_div(fvco, (pdiv << sdiv));
0769     fvco >>= shift;
0770 
0771     return (unsigned long)fvco;
0772 }
0773 
0774 static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
0775                 const struct samsung_pll_rate_table *rate)
0776 {
0777     u32 old_mdiv, old_pdiv, old_kdiv;
0778 
0779     old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
0780     old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
0781     old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK;
0782 
0783     return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
0784         || old_kdiv != rate->kdiv);
0785 }
0786 
0787 static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
0788                     unsigned long prate)
0789 {
0790     struct samsung_clk_pll *pll = to_clk_pll(hw);
0791     const struct samsung_pll_rate_table *rate;
0792     u32 con0, con1, lock;
0793 
0794     /* Get required rate settings from table */
0795     rate = samsung_get_pll_settings(pll, drate);
0796     if (!rate) {
0797         pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
0798             drate, clk_hw_get_name(hw));
0799         return -EINVAL;
0800     }
0801 
0802     con0 = readl_relaxed(pll->con_reg);
0803     con1 = readl_relaxed(pll->con_reg + 0x4);
0804 
0805     if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
0806         /* If only s change, change just s value only*/
0807         con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
0808         con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
0809         writel_relaxed(con0, pll->con_reg);
0810 
0811         return 0;
0812     }
0813 
0814     /* Set PLL lock time. */
0815     lock = rate->pdiv * PLL46XX_LOCK_FACTOR;
0816     if (lock > 0xffff)
0817         /* Maximum lock time bitfield is 16-bit. */
0818         lock = 0xffff;
0819 
0820     /* Set PLL PMS and VSEL values. */
0821     if (pll->type == pll_1460x) {
0822         con0 &= ~((PLL1460X_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
0823             (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
0824             (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT));
0825     } else {
0826         con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
0827             (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
0828             (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
0829             (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
0830         con0 |= rate->vsel << PLL46XX_VSEL_SHIFT;
0831     }
0832 
0833     con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
0834             (rate->pdiv << PLL46XX_PDIV_SHIFT) |
0835             (rate->sdiv << PLL46XX_SDIV_SHIFT);
0836 
0837     /* Set PLL K, MFR and MRR values. */
0838     con1 = readl_relaxed(pll->con_reg + 0x4);
0839     con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
0840             (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
0841             (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
0842     con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) |
0843             (rate->mfr << PLL46XX_MFR_SHIFT) |
0844             (rate->mrr << PLL46XX_MRR_SHIFT);
0845 
0846     /* Write configuration to PLL */
0847     writel_relaxed(lock, pll->lock_reg);
0848     writel_relaxed(con0, pll->con_reg);
0849     writel_relaxed(con1, pll->con_reg + 0x4);
0850 
0851     /* Wait for PLL lock */
0852     return samsung_pll_lock_wait(pll, PLL46XX_LOCKED);
0853 }
0854 
0855 static const struct clk_ops samsung_pll46xx_clk_ops = {
0856     .recalc_rate = samsung_pll46xx_recalc_rate,
0857     .round_rate = samsung_pll_round_rate,
0858     .set_rate = samsung_pll46xx_set_rate,
0859 };
0860 
0861 static const struct clk_ops samsung_pll46xx_clk_min_ops = {
0862     .recalc_rate = samsung_pll46xx_recalc_rate,
0863 };
0864 
0865 /*
0866  * PLL6552 Clock Type
0867  */
0868 
0869 #define PLL6552_MDIV_MASK   0x3ff
0870 #define PLL6552_PDIV_MASK   0x3f
0871 #define PLL6552_SDIV_MASK   0x7
0872 #define PLL6552_MDIV_SHIFT  16
0873 #define PLL6552_MDIV_SHIFT_2416 14
0874 #define PLL6552_PDIV_SHIFT  8
0875 #define PLL6552_PDIV_SHIFT_2416 5
0876 #define PLL6552_SDIV_SHIFT  0
0877 
0878 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw,
0879                         unsigned long parent_rate)
0880 {
0881     struct samsung_clk_pll *pll = to_clk_pll(hw);
0882     u32 mdiv, pdiv, sdiv, pll_con;
0883     u64 fvco = parent_rate;
0884 
0885     pll_con = readl_relaxed(pll->con_reg);
0886     if (pll->type == pll_6552_s3c2416) {
0887         mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK;
0888         pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK;
0889     } else {
0890         mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK;
0891         pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK;
0892     }
0893     sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK;
0894 
0895     fvco *= mdiv;
0896     do_div(fvco, (pdiv << sdiv));
0897 
0898     return (unsigned long)fvco;
0899 }
0900 
0901 static const struct clk_ops samsung_pll6552_clk_ops = {
0902     .recalc_rate = samsung_pll6552_recalc_rate,
0903 };
0904 
0905 /*
0906  * PLL6553 Clock Type
0907  */
0908 
0909 #define PLL6553_MDIV_MASK   0xff
0910 #define PLL6553_PDIV_MASK   0x3f
0911 #define PLL6553_SDIV_MASK   0x7
0912 #define PLL6553_KDIV_MASK   0xffff
0913 #define PLL6553_MDIV_SHIFT  16
0914 #define PLL6553_PDIV_SHIFT  8
0915 #define PLL6553_SDIV_SHIFT  0
0916 #define PLL6553_KDIV_SHIFT  0
0917 
0918 static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
0919                         unsigned long parent_rate)
0920 {
0921     struct samsung_clk_pll *pll = to_clk_pll(hw);
0922     u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
0923     u64 fvco = parent_rate;
0924 
0925     pll_con0 = readl_relaxed(pll->con_reg);
0926     pll_con1 = readl_relaxed(pll->con_reg + 0x4);
0927     mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
0928     pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
0929     sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
0930     kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK;
0931 
0932     fvco *= (mdiv << 16) + kdiv;
0933     do_div(fvco, (pdiv << sdiv));
0934     fvco >>= 16;
0935 
0936     return (unsigned long)fvco;
0937 }
0938 
0939 static const struct clk_ops samsung_pll6553_clk_ops = {
0940     .recalc_rate = samsung_pll6553_recalc_rate,
0941 };
0942 
0943 /*
0944  * PLL Clock Type of S3C24XX before S3C2443
0945  */
0946 
0947 #define PLLS3C2410_MDIV_MASK        (0xff)
0948 #define PLLS3C2410_PDIV_MASK        (0x1f)
0949 #define PLLS3C2410_SDIV_MASK        (0x3)
0950 #define PLLS3C2410_MDIV_SHIFT       (12)
0951 #define PLLS3C2410_PDIV_SHIFT       (4)
0952 #define PLLS3C2410_SDIV_SHIFT       (0)
0953 
0954 #define PLLS3C2410_ENABLE_REG_OFFSET    0x10
0955 
0956 static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw,
0957                     unsigned long parent_rate)
0958 {
0959     struct samsung_clk_pll *pll = to_clk_pll(hw);
0960     u32 pll_con, mdiv, pdiv, sdiv;
0961     u64 fvco = parent_rate;
0962 
0963     pll_con = readl_relaxed(pll->con_reg);
0964     mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
0965     pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
0966     sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
0967 
0968     fvco *= (mdiv + 8);
0969     do_div(fvco, (pdiv + 2) << sdiv);
0970 
0971     return (unsigned int)fvco;
0972 }
0973 
0974 static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw,
0975                     unsigned long parent_rate)
0976 {
0977     struct samsung_clk_pll *pll = to_clk_pll(hw);
0978     u32 pll_con, mdiv, pdiv, sdiv;
0979     u64 fvco = parent_rate;
0980 
0981     pll_con = readl_relaxed(pll->con_reg);
0982     mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK;
0983     pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK;
0984     sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK;
0985 
0986     fvco *= (2 * (mdiv + 8));
0987     do_div(fvco, (pdiv + 2) << sdiv);
0988 
0989     return (unsigned int)fvco;
0990 }
0991 
0992 static int samsung_s3c2410_pll_set_rate(struct clk_hw *hw, unsigned long drate,
0993                     unsigned long prate)
0994 {
0995     struct samsung_clk_pll *pll = to_clk_pll(hw);
0996     const struct samsung_pll_rate_table *rate;
0997     u32 tmp;
0998 
0999     /* 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 
1024 static 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 
1044 static int samsung_s3c2410_mpll_enable(struct clk_hw *hw)
1045 {
1046     return samsung_s3c2410_pll_enable(hw, 5, true);
1047 }
1048 
1049 static void samsung_s3c2410_mpll_disable(struct clk_hw *hw)
1050 {
1051     samsung_s3c2410_pll_enable(hw, 5, false);
1052 }
1053 
1054 static int samsung_s3c2410_upll_enable(struct clk_hw *hw)
1055 {
1056     return samsung_s3c2410_pll_enable(hw, 7, true);
1057 }
1058 
1059 static void samsung_s3c2410_upll_disable(struct clk_hw *hw)
1060 {
1061     samsung_s3c2410_pll_enable(hw, 7, false);
1062 }
1063 
1064 static 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 
1070 static 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 
1076 static 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 
1082 static 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 
1090 static 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 
1098 static 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 
1119 static 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 
1140 static 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 
1160 static 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 
1178 static 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 
1188 static 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 
1231 static 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 
1237 static 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 
1260 static 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 
1283 static 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 
1323 static 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 
1329 static 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 
1352 static 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 
1374 static 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 
1414 static 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 
1420 static const struct clk_ops samsung_pll2650xx_clk_min_ops = {
1421     .recalc_rate = samsung_pll2650xx_recalc_rate,
1422 };
1423 
1424 static 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 
1593 void __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 }