Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/clk.h>
0004 #include <linux/io.h>
0005 #include <linux/errno.h>
0006 #include <linux/delay.h>
0007 #include <linux/slab.h>
0008 #include <linux/err.h>
0009 
0010 #include <asm/div64.h>
0011 
0012 #include "clk.h"
0013 
0014 #define to_clk_pllv2(clk) (container_of(clk, struct clk_pllv2, clk))
0015 
0016 /* PLL Register Offsets */
0017 #define MXC_PLL_DP_CTL          0x00
0018 #define MXC_PLL_DP_CONFIG       0x04
0019 #define MXC_PLL_DP_OP           0x08
0020 #define MXC_PLL_DP_MFD          0x0C
0021 #define MXC_PLL_DP_MFN          0x10
0022 #define MXC_PLL_DP_MFNMINUS     0x14
0023 #define MXC_PLL_DP_MFNPLUS      0x18
0024 #define MXC_PLL_DP_HFS_OP       0x1C
0025 #define MXC_PLL_DP_HFS_MFD      0x20
0026 #define MXC_PLL_DP_HFS_MFN      0x24
0027 #define MXC_PLL_DP_MFN_TOGC     0x28
0028 #define MXC_PLL_DP_DESTAT       0x2c
0029 
0030 /* PLL Register Bit definitions */
0031 #define MXC_PLL_DP_CTL_MUL_CTRL     0x2000
0032 #define MXC_PLL_DP_CTL_DPDCK0_2_EN  0x1000
0033 #define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET  12
0034 #define MXC_PLL_DP_CTL_ADE      0x800
0035 #define MXC_PLL_DP_CTL_REF_CLK_DIV  0x400
0036 #define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK (3 << 8)
0037 #define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET   8
0038 #define MXC_PLL_DP_CTL_HFSM     0x80
0039 #define MXC_PLL_DP_CTL_PRE      0x40
0040 #define MXC_PLL_DP_CTL_UPEN     0x20
0041 #define MXC_PLL_DP_CTL_RST      0x10
0042 #define MXC_PLL_DP_CTL_RCP      0x8
0043 #define MXC_PLL_DP_CTL_PLM      0x4
0044 #define MXC_PLL_DP_CTL_BRM0     0x2
0045 #define MXC_PLL_DP_CTL_LRF      0x1
0046 
0047 #define MXC_PLL_DP_CONFIG_BIST      0x8
0048 #define MXC_PLL_DP_CONFIG_SJC_CE    0x4
0049 #define MXC_PLL_DP_CONFIG_AREN      0x2
0050 #define MXC_PLL_DP_CONFIG_LDREQ     0x1
0051 
0052 #define MXC_PLL_DP_OP_MFI_OFFSET    4
0053 #define MXC_PLL_DP_OP_MFI_MASK      (0xF << 4)
0054 #define MXC_PLL_DP_OP_PDF_OFFSET    0
0055 #define MXC_PLL_DP_OP_PDF_MASK      0xF
0056 
0057 #define MXC_PLL_DP_MFD_OFFSET       0
0058 #define MXC_PLL_DP_MFD_MASK     0x07FFFFFF
0059 
0060 #define MXC_PLL_DP_MFN_OFFSET       0x0
0061 #define MXC_PLL_DP_MFN_MASK     0x07FFFFFF
0062 
0063 #define MXC_PLL_DP_MFN_TOGC_TOG_DIS (1 << 17)
0064 #define MXC_PLL_DP_MFN_TOGC_TOG_EN  (1 << 16)
0065 #define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET  0x0
0066 #define MXC_PLL_DP_MFN_TOGC_CNT_MASK    0xFFFF
0067 
0068 #define MXC_PLL_DP_DESTAT_TOG_SEL   (1 << 31)
0069 #define MXC_PLL_DP_DESTAT_MFN       0x07FFFFFF
0070 
0071 #define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */
0072 
0073 struct clk_pllv2 {
0074     struct clk_hw   hw;
0075     void __iomem    *base;
0076 };
0077 
0078 static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
0079         u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn)
0080 {
0081     long mfi, mfn, mfd, pdf, ref_clk;
0082     unsigned long dbl;
0083     u64 temp;
0084 
0085     dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
0086 
0087     pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
0088     mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
0089     mfi = (mfi <= 5) ? 5 : mfi;
0090     mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
0091     mfn = dp_mfn & MXC_PLL_DP_MFN_MASK;
0092     mfn = sign_extend32(mfn, 26);
0093 
0094     ref_clk = 2 * parent_rate;
0095     if (dbl != 0)
0096         ref_clk *= 2;
0097 
0098     ref_clk /= (pdf + 1);
0099     temp = (u64) ref_clk * abs(mfn);
0100     do_div(temp, mfd + 1);
0101     if (mfn < 0)
0102         temp = (ref_clk * mfi) - temp;
0103     else
0104         temp = (ref_clk * mfi) + temp;
0105 
0106     return temp;
0107 }
0108 
0109 static unsigned long clk_pllv2_recalc_rate(struct clk_hw *hw,
0110         unsigned long parent_rate)
0111 {
0112     u32 dp_op, dp_mfd, dp_mfn, dp_ctl;
0113     void __iomem *pllbase;
0114     struct clk_pllv2 *pll = to_clk_pllv2(hw);
0115 
0116     pllbase = pll->base;
0117 
0118     dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
0119     dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
0120     dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
0121     dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
0122 
0123     return __clk_pllv2_recalc_rate(parent_rate, dp_ctl, dp_op, dp_mfd, dp_mfn);
0124 }
0125 
0126 static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate,
0127         u32 *dp_op, u32 *dp_mfd, u32 *dp_mfn)
0128 {
0129     u32 reg;
0130     long mfi, pdf, mfn, mfd = 999999;
0131     u64 temp64;
0132     unsigned long quad_parent_rate;
0133 
0134     quad_parent_rate = 4 * parent_rate;
0135     pdf = mfi = -1;
0136     while (++pdf < 16 && mfi < 5)
0137         mfi = rate * (pdf+1) / quad_parent_rate;
0138     if (mfi > 15)
0139         return -EINVAL;
0140     pdf--;
0141 
0142     temp64 = rate * (pdf + 1) - quad_parent_rate * mfi;
0143     do_div(temp64, quad_parent_rate / 1000000);
0144     mfn = (long)temp64;
0145 
0146     reg = mfi << 4 | pdf;
0147 
0148     *dp_op = reg;
0149     *dp_mfd = mfd;
0150     *dp_mfn = mfn;
0151 
0152     return 0;
0153 }
0154 
0155 static int clk_pllv2_set_rate(struct clk_hw *hw, unsigned long rate,
0156         unsigned long parent_rate)
0157 {
0158     struct clk_pllv2 *pll = to_clk_pllv2(hw);
0159     void __iomem *pllbase;
0160     u32 dp_ctl, dp_op, dp_mfd, dp_mfn;
0161     int ret;
0162 
0163     pllbase = pll->base;
0164 
0165 
0166     ret = __clk_pllv2_set_rate(rate, parent_rate, &dp_op, &dp_mfd, &dp_mfn);
0167     if (ret)
0168         return ret;
0169 
0170     dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
0171     /* use dpdck0_2 */
0172     __raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
0173 
0174     __raw_writel(dp_op, pllbase + MXC_PLL_DP_OP);
0175     __raw_writel(dp_mfd, pllbase + MXC_PLL_DP_MFD);
0176     __raw_writel(dp_mfn, pllbase + MXC_PLL_DP_MFN);
0177 
0178     return 0;
0179 }
0180 
0181 static long clk_pllv2_round_rate(struct clk_hw *hw, unsigned long rate,
0182         unsigned long *prate)
0183 {
0184     u32 dp_op, dp_mfd, dp_mfn;
0185     int ret;
0186 
0187     ret = __clk_pllv2_set_rate(rate, *prate, &dp_op, &dp_mfd, &dp_mfn);
0188     if (ret)
0189         return ret;
0190 
0191     return __clk_pllv2_recalc_rate(*prate, MXC_PLL_DP_CTL_DPDCK0_2_EN,
0192             dp_op, dp_mfd, dp_mfn);
0193 }
0194 
0195 static int clk_pllv2_prepare(struct clk_hw *hw)
0196 {
0197     struct clk_pllv2 *pll = to_clk_pllv2(hw);
0198     u32 reg;
0199     void __iomem *pllbase;
0200     int i = 0;
0201 
0202     pllbase = pll->base;
0203     reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
0204     __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
0205 
0206     /* Wait for lock */
0207     do {
0208         reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
0209         if (reg & MXC_PLL_DP_CTL_LRF)
0210             break;
0211 
0212         udelay(1);
0213     } while (++i < MAX_DPLL_WAIT_TRIES);
0214 
0215     if (i == MAX_DPLL_WAIT_TRIES) {
0216         pr_err("MX5: pll locking failed\n");
0217         return -EINVAL;
0218     }
0219 
0220     return 0;
0221 }
0222 
0223 static void clk_pllv2_unprepare(struct clk_hw *hw)
0224 {
0225     struct clk_pllv2 *pll = to_clk_pllv2(hw);
0226     u32 reg;
0227     void __iomem *pllbase;
0228 
0229     pllbase = pll->base;
0230     reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
0231     __raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
0232 }
0233 
0234 static const struct clk_ops clk_pllv2_ops = {
0235     .prepare = clk_pllv2_prepare,
0236     .unprepare = clk_pllv2_unprepare,
0237     .recalc_rate = clk_pllv2_recalc_rate,
0238     .round_rate = clk_pllv2_round_rate,
0239     .set_rate = clk_pllv2_set_rate,
0240 };
0241 
0242 struct clk_hw *imx_clk_hw_pllv2(const char *name, const char *parent,
0243         void __iomem *base)
0244 {
0245     struct clk_pllv2 *pll;
0246     struct clk_hw *hw;
0247     struct clk_init_data init;
0248     int ret;
0249 
0250     pll = kzalloc(sizeof(*pll), GFP_KERNEL);
0251     if (!pll)
0252         return ERR_PTR(-ENOMEM);
0253 
0254     pll->base = base;
0255 
0256     init.name = name;
0257     init.ops = &clk_pllv2_ops;
0258     init.flags = 0;
0259     init.parent_names = &parent;
0260     init.num_parents = 1;
0261 
0262     pll->hw.init = &init;
0263     hw = &pll->hw;
0264 
0265     ret = clk_hw_register(NULL, hw);
0266     if (ret) {
0267         kfree(pll);
0268         return ERR_PTR(ret);
0269     }
0270 
0271     return hw;
0272 }