Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * CS2000  --  CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier
0004  *
0005  * Copyright (C) 2015 Renesas Electronics Corporation
0006  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
0007  */
0008 #include <linux/clk-provider.h>
0009 #include <linux/delay.h>
0010 #include <linux/clk.h>
0011 #include <linux/i2c.h>
0012 #include <linux/of_device.h>
0013 #include <linux/module.h>
0014 #include <linux/regmap.h>
0015 
0016 #define CH_MAX 4
0017 #define RATIO_REG_SIZE 4
0018 
0019 #define DEVICE_ID   0x1
0020 #define DEVICE_CTRL 0x2
0021 #define DEVICE_CFG1 0x3
0022 #define DEVICE_CFG2 0x4
0023 #define GLOBAL_CFG  0x5
0024 #define Ratio_Add(x, nth)   (6 + (x * 4) + (nth))
0025 #define Ratio_Val(x, nth)   ((x >> (24 - (8 * nth))) & 0xFF)
0026 #define Val_Ratio(x, nth)   ((x & 0xFF) << (24 - (8 * nth)))
0027 #define FUNC_CFG1   0x16
0028 #define FUNC_CFG2   0x17
0029 
0030 /* DEVICE_ID */
0031 #define REVISION_MASK   (0x7)
0032 #define REVISION_B2_B3  (0x4)
0033 #define REVISION_C1 (0x6)
0034 
0035 /* DEVICE_CTRL */
0036 #define PLL_UNLOCK  (1 << 7)
0037 #define AUXOUTDIS   (1 << 1)
0038 #define CLKOUTDIS   (1 << 0)
0039 
0040 /* DEVICE_CFG1 */
0041 #define RSEL(x)     (((x) & 0x3) << 3)
0042 #define RSEL_MASK   RSEL(0x3)
0043 #define AUXOUTSRC(x)    (((x) & 0x3) << 1)
0044 #define AUXOUTSRC_MASK  AUXOUTSRC(0x3)
0045 #define ENDEV1      (0x1)
0046 
0047 /* DEVICE_CFG2 */
0048 #define AUTORMOD    (1 << 3)
0049 #define LOCKCLK(x)  (((x) & 0x3) << 1)
0050 #define LOCKCLK_MASK    LOCKCLK(0x3)
0051 #define FRACNSRC_MASK   (1 << 0)
0052 #define FRACNSRC_STATIC     (0 << 0)
0053 #define FRACNSRC_DYNAMIC    (1 << 0)
0054 
0055 /* GLOBAL_CFG */
0056 #define FREEZE      (1 << 7)
0057 #define ENDEV2      (0x1)
0058 
0059 /* FUNC_CFG1 */
0060 #define CLKSKIPEN   (1 << 7)
0061 #define REFCLKDIV(x)    (((x) & 0x3) << 3)
0062 #define REFCLKDIV_MASK  REFCLKDIV(0x3)
0063 
0064 /* FUNC_CFG2 */
0065 #define LFRATIO_MASK    (1 << 3)
0066 #define LFRATIO_20_12   (0 << 3)
0067 #define LFRATIO_12_20   (1 << 3)
0068 
0069 #define CH_SIZE_ERR(ch)     ((ch < 0) || (ch >= CH_MAX))
0070 #define hw_to_priv(_hw)     container_of(_hw, struct cs2000_priv, hw)
0071 #define priv_to_client(priv)    (priv->client)
0072 #define priv_to_dev(priv)   (&(priv_to_client(priv)->dev))
0073 
0074 #define CLK_IN  0
0075 #define REF_CLK 1
0076 #define CLK_MAX 2
0077 
0078 static bool cs2000_readable_reg(struct device *dev, unsigned int reg)
0079 {
0080     return reg > 0;
0081 }
0082 
0083 static bool cs2000_writeable_reg(struct device *dev, unsigned int reg)
0084 {
0085     return reg != DEVICE_ID;
0086 }
0087 
0088 static bool cs2000_volatile_reg(struct device *dev, unsigned int reg)
0089 {
0090     return reg == DEVICE_CTRL;
0091 }
0092 
0093 static const struct regmap_config cs2000_regmap_config = {
0094     .reg_bits   = 8,
0095     .val_bits   = 8,
0096     .max_register   = FUNC_CFG2,
0097     .readable_reg   = cs2000_readable_reg,
0098     .writeable_reg  = cs2000_writeable_reg,
0099     .volatile_reg   = cs2000_volatile_reg,
0100 };
0101 
0102 struct cs2000_priv {
0103     struct clk_hw hw;
0104     struct i2c_client *client;
0105     struct clk *clk_in;
0106     struct clk *ref_clk;
0107     struct regmap *regmap;
0108 
0109     bool dynamic_mode;
0110     bool lf_ratio;
0111     bool clk_skip;
0112 
0113     /* suspend/resume */
0114     unsigned long saved_rate;
0115     unsigned long saved_parent_rate;
0116 };
0117 
0118 static const struct of_device_id cs2000_of_match[] = {
0119     { .compatible = "cirrus,cs2000-cp", },
0120     {},
0121 };
0122 MODULE_DEVICE_TABLE(of, cs2000_of_match);
0123 
0124 static const struct i2c_device_id cs2000_id[] = {
0125     { "cs2000-cp", },
0126     {}
0127 };
0128 MODULE_DEVICE_TABLE(i2c, cs2000_id);
0129 
0130 static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
0131 {
0132     int ret;
0133 
0134     ret = regmap_update_bits(priv->regmap, DEVICE_CFG1, ENDEV1,
0135                  enable ? ENDEV1 : 0);
0136     if (ret < 0)
0137         return ret;
0138 
0139     ret = regmap_update_bits(priv->regmap, GLOBAL_CFG,  ENDEV2,
0140                  enable ? ENDEV2 : 0);
0141     if (ret < 0)
0142         return ret;
0143 
0144     ret = regmap_update_bits(priv->regmap, FUNC_CFG1, CLKSKIPEN,
0145                  (enable && priv->clk_skip) ? CLKSKIPEN : 0);
0146     if (ret < 0)
0147         return ret;
0148 
0149     return 0;
0150 }
0151 
0152 static int cs2000_ref_clk_bound_rate(struct cs2000_priv *priv,
0153                      u32 rate_in)
0154 {
0155     u32 val;
0156 
0157     if (rate_in >= 32000000 && rate_in < 56000000)
0158         val = 0x0;
0159     else if (rate_in >= 16000000 && rate_in < 28000000)
0160         val = 0x1;
0161     else if (rate_in >= 8000000 && rate_in < 14000000)
0162         val = 0x2;
0163     else
0164         return -EINVAL;
0165 
0166     return regmap_update_bits(priv->regmap, FUNC_CFG1,
0167                   REFCLKDIV_MASK,
0168                   REFCLKDIV(val));
0169 }
0170 
0171 static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
0172 {
0173     struct device *dev = priv_to_dev(priv);
0174     unsigned int i, val;
0175     int ret;
0176 
0177     for (i = 0; i < 256; i++) {
0178         ret = regmap_read(priv->regmap, DEVICE_CTRL, &val);
0179         if (ret < 0)
0180             return ret;
0181         if (!(val & PLL_UNLOCK))
0182             return 0;
0183         udelay(1);
0184     }
0185 
0186     dev_err(dev, "pll lock failed\n");
0187 
0188     return -ETIMEDOUT;
0189 }
0190 
0191 static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable)
0192 {
0193     /* enable both AUX_OUT, CLK_OUT */
0194     return regmap_update_bits(priv->regmap, DEVICE_CTRL,
0195                   (AUXOUTDIS | CLKOUTDIS),
0196                   enable ? 0 :
0197                   (AUXOUTDIS | CLKOUTDIS));
0198 }
0199 
0200 static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out, bool lf_ratio)
0201 {
0202     u64 ratio;
0203     u32 multiplier = lf_ratio ? 12 : 20;
0204 
0205     /*
0206      * ratio = rate_out / rate_in * 2^multiplier
0207      *
0208      * To avoid over flow, rate_out is u64.
0209      * The result should be u32.
0210      */
0211     ratio = (u64)rate_out << multiplier;
0212     do_div(ratio, rate_in);
0213 
0214     return ratio;
0215 }
0216 
0217 static unsigned long cs2000_ratio_to_rate(u32 ratio, u32 rate_in, bool lf_ratio)
0218 {
0219     u64 rate_out;
0220     u32 multiplier = lf_ratio ? 12 : 20;
0221 
0222     /*
0223      * ratio = rate_out / rate_in * 2^multiplier
0224      *
0225      * To avoid over flow, rate_out is u64.
0226      * The result should be u32 or unsigned long.
0227      */
0228 
0229     rate_out = (u64)ratio * rate_in;
0230     return rate_out >> multiplier;
0231 }
0232 
0233 static int cs2000_ratio_set(struct cs2000_priv *priv,
0234                 int ch, u32 rate_in, u32 rate_out)
0235 {
0236     u32 val;
0237     unsigned int i;
0238     int ret;
0239 
0240     if (CH_SIZE_ERR(ch))
0241         return -EINVAL;
0242 
0243     val = cs2000_rate_to_ratio(rate_in, rate_out, priv->lf_ratio);
0244     for (i = 0; i < RATIO_REG_SIZE; i++) {
0245         ret = regmap_write(priv->regmap,
0246                    Ratio_Add(ch, i),
0247                    Ratio_Val(val, i));
0248         if (ret < 0)
0249             return ret;
0250     }
0251 
0252     return 0;
0253 }
0254 
0255 static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch)
0256 {
0257     unsigned int tmp, i;
0258     u32 val;
0259     int ret;
0260 
0261     val = 0;
0262     for (i = 0; i < RATIO_REG_SIZE; i++) {
0263         ret = regmap_read(priv->regmap, Ratio_Add(ch, i), &tmp);
0264         if (ret < 0)
0265             return 0;
0266 
0267         val |= Val_Ratio(tmp, i);
0268     }
0269 
0270     return val;
0271 }
0272 
0273 static int cs2000_ratio_select(struct cs2000_priv *priv, int ch)
0274 {
0275     int ret;
0276     u8 fracnsrc;
0277 
0278     if (CH_SIZE_ERR(ch))
0279         return -EINVAL;
0280 
0281     ret = regmap_update_bits(priv->regmap, DEVICE_CFG1, RSEL_MASK, RSEL(ch));
0282     if (ret < 0)
0283         return ret;
0284 
0285     fracnsrc = priv->dynamic_mode ? FRACNSRC_DYNAMIC : FRACNSRC_STATIC;
0286 
0287     ret = regmap_update_bits(priv->regmap, DEVICE_CFG2,
0288                  AUTORMOD | LOCKCLK_MASK | FRACNSRC_MASK,
0289                  LOCKCLK(ch) | fracnsrc);
0290     if (ret < 0)
0291         return ret;
0292 
0293     return 0;
0294 }
0295 
0296 static unsigned long cs2000_recalc_rate(struct clk_hw *hw,
0297                     unsigned long parent_rate)
0298 {
0299     struct cs2000_priv *priv = hw_to_priv(hw);
0300     int ch = 0; /* it uses ch0 only at this point */
0301     u32 ratio;
0302 
0303     ratio = cs2000_ratio_get(priv, ch);
0304 
0305     return cs2000_ratio_to_rate(ratio, parent_rate, priv->lf_ratio);
0306 }
0307 
0308 static long cs2000_round_rate(struct clk_hw *hw, unsigned long rate,
0309                   unsigned long *parent_rate)
0310 {
0311     struct cs2000_priv *priv = hw_to_priv(hw);
0312     u32 ratio;
0313 
0314     ratio = cs2000_rate_to_ratio(*parent_rate, rate, priv->lf_ratio);
0315 
0316     return cs2000_ratio_to_rate(ratio, *parent_rate, priv->lf_ratio);
0317 }
0318 
0319 static int cs2000_select_ratio_mode(struct cs2000_priv *priv,
0320                     unsigned long rate,
0321                     unsigned long parent_rate)
0322 {
0323     /*
0324      * From the datasheet:
0325      *
0326      * | It is recommended that the 12.20 High-Resolution format be
0327      * | utilized whenever the desired ratio is less than 4096 since
0328      * | the output frequency accuracy of the PLL is directly proportional
0329      * | to the accuracy of the timing reference clock and the resolution
0330      * | of the R_UD.
0331      *
0332      * This mode is only available in dynamic mode.
0333      */
0334     priv->lf_ratio = priv->dynamic_mode && ((rate / parent_rate) > 4096);
0335 
0336     return regmap_update_bits(priv->regmap, FUNC_CFG2, LFRATIO_MASK,
0337                   priv->lf_ratio ? LFRATIO_20_12 : LFRATIO_12_20);
0338 }
0339 
0340 static int __cs2000_set_rate(struct cs2000_priv *priv, int ch,
0341                  unsigned long rate, unsigned long parent_rate)
0342 
0343 {
0344     int ret;
0345 
0346     ret = regmap_update_bits(priv->regmap, GLOBAL_CFG, FREEZE, FREEZE);
0347     if (ret < 0)
0348         return ret;
0349 
0350     ret = cs2000_select_ratio_mode(priv, rate, parent_rate);
0351     if (ret < 0)
0352         return ret;
0353 
0354     ret = cs2000_ratio_set(priv, ch, parent_rate, rate);
0355     if (ret < 0)
0356         return ret;
0357 
0358     ret = cs2000_ratio_select(priv, ch);
0359     if (ret < 0)
0360         return ret;
0361 
0362     ret = regmap_update_bits(priv->regmap, GLOBAL_CFG, FREEZE, 0);
0363     if (ret < 0)
0364         return ret;
0365 
0366     priv->saved_rate    = rate;
0367     priv->saved_parent_rate = parent_rate;
0368 
0369     return 0;
0370 }
0371 
0372 static int cs2000_set_rate(struct clk_hw *hw,
0373                unsigned long rate, unsigned long parent_rate)
0374 {
0375     struct cs2000_priv *priv = hw_to_priv(hw);
0376     int ch = 0; /* it uses ch0 only at this point */
0377 
0378     return __cs2000_set_rate(priv, ch, rate, parent_rate);
0379 }
0380 
0381 static int cs2000_set_saved_rate(struct cs2000_priv *priv)
0382 {
0383     int ch = 0; /* it uses ch0 only at this point */
0384 
0385     return __cs2000_set_rate(priv, ch,
0386                  priv->saved_rate,
0387                  priv->saved_parent_rate);
0388 }
0389 
0390 static int cs2000_enable(struct clk_hw *hw)
0391 {
0392     struct cs2000_priv *priv = hw_to_priv(hw);
0393     int ret;
0394 
0395     ret = cs2000_enable_dev_config(priv, true);
0396     if (ret < 0)
0397         return ret;
0398 
0399     ret = cs2000_clk_out_enable(priv, true);
0400     if (ret < 0)
0401         return ret;
0402 
0403     ret = cs2000_wait_pll_lock(priv);
0404     if (ret < 0)
0405         return ret;
0406 
0407     return ret;
0408 }
0409 
0410 static void cs2000_disable(struct clk_hw *hw)
0411 {
0412     struct cs2000_priv *priv = hw_to_priv(hw);
0413 
0414     cs2000_enable_dev_config(priv, false);
0415 
0416     cs2000_clk_out_enable(priv, false);
0417 }
0418 
0419 static u8 cs2000_get_parent(struct clk_hw *hw)
0420 {
0421     struct cs2000_priv *priv = hw_to_priv(hw);
0422 
0423     /*
0424      * In dynamic mode, output rates are derived from CLK_IN.
0425      * In static mode, CLK_IN is ignored, so we return REF_CLK instead.
0426      */
0427     return priv->dynamic_mode ? CLK_IN : REF_CLK;
0428 }
0429 
0430 static const struct clk_ops cs2000_ops = {
0431     .get_parent = cs2000_get_parent,
0432     .recalc_rate    = cs2000_recalc_rate,
0433     .round_rate = cs2000_round_rate,
0434     .set_rate   = cs2000_set_rate,
0435     .prepare    = cs2000_enable,
0436     .unprepare  = cs2000_disable,
0437 };
0438 
0439 static int cs2000_clk_get(struct cs2000_priv *priv)
0440 {
0441     struct device *dev = priv_to_dev(priv);
0442     struct clk *clk_in, *ref_clk;
0443 
0444     clk_in = devm_clk_get(dev, "clk_in");
0445     /* not yet provided */
0446     if (IS_ERR(clk_in))
0447         return -EPROBE_DEFER;
0448 
0449     ref_clk = devm_clk_get(dev, "ref_clk");
0450     /* not yet provided */
0451     if (IS_ERR(ref_clk))
0452         return -EPROBE_DEFER;
0453 
0454     priv->clk_in    = clk_in;
0455     priv->ref_clk   = ref_clk;
0456 
0457     return 0;
0458 }
0459 
0460 static int cs2000_clk_register(struct cs2000_priv *priv)
0461 {
0462     struct device *dev = priv_to_dev(priv);
0463     struct device_node *np = dev->of_node;
0464     struct clk_init_data init;
0465     const char *name = np->name;
0466     static const char *parent_names[CLK_MAX];
0467     u32 aux_out = 0;
0468     int ref_clk_rate;
0469     int ch = 0; /* it uses ch0 only at this point */
0470     int ret;
0471 
0472     of_property_read_string(np, "clock-output-names", &name);
0473 
0474     priv->dynamic_mode = of_property_read_bool(np, "cirrus,dynamic-mode");
0475     dev_info(dev, "operating in %s mode\n",
0476          priv->dynamic_mode ? "dynamic" : "static");
0477 
0478     of_property_read_u32(np, "cirrus,aux-output-source", &aux_out);
0479     ret = regmap_update_bits(priv->regmap, DEVICE_CFG1,
0480                  AUXOUTSRC_MASK, AUXOUTSRC(aux_out));
0481     if (ret < 0)
0482         return ret;
0483 
0484     priv->clk_skip = of_property_read_bool(np, "cirrus,clock-skip");
0485 
0486     ref_clk_rate = clk_get_rate(priv->ref_clk);
0487     ret = cs2000_ref_clk_bound_rate(priv, ref_clk_rate);
0488     if (ret < 0)
0489         return ret;
0490 
0491     if (priv->dynamic_mode) {
0492         /* Default to low-frequency mode to allow for large ratios */
0493         priv->lf_ratio = true;
0494     } else {
0495         /*
0496          * set default rate as 1/1.
0497          * otherwise .set_rate which setup ratio
0498          * is never called if user requests 1/1 rate
0499          */
0500         ret = __cs2000_set_rate(priv, ch, ref_clk_rate, ref_clk_rate);
0501         if (ret < 0)
0502             return ret;
0503     }
0504 
0505     parent_names[CLK_IN]    = __clk_get_name(priv->clk_in);
0506     parent_names[REF_CLK]   = __clk_get_name(priv->ref_clk);
0507 
0508     init.name       = name;
0509     init.ops        = &cs2000_ops;
0510     init.flags      = CLK_SET_RATE_GATE;
0511     init.parent_names   = parent_names;
0512     init.num_parents    = ARRAY_SIZE(parent_names);
0513 
0514     priv->hw.init = &init;
0515 
0516     ret = clk_hw_register(dev, &priv->hw);
0517     if (ret)
0518         return ret;
0519 
0520     ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw);
0521     if (ret < 0) {
0522         clk_hw_unregister(&priv->hw);
0523         return ret;
0524     }
0525 
0526     return 0;
0527 }
0528 
0529 static int cs2000_version_print(struct cs2000_priv *priv)
0530 {
0531     struct device *dev = priv_to_dev(priv);
0532     const char *revision;
0533     unsigned int val;
0534     int ret;
0535 
0536     ret = regmap_read(priv->regmap, DEVICE_ID, &val);
0537     if (ret < 0)
0538         return ret;
0539 
0540     /* CS2000 should be 0x0 */
0541     if (val >> 3)
0542         return -EIO;
0543 
0544     switch (val & REVISION_MASK) {
0545     case REVISION_B2_B3:
0546         revision = "B2 / B3";
0547         break;
0548     case REVISION_C1:
0549         revision = "C1";
0550         break;
0551     default:
0552         return -EIO;
0553     }
0554 
0555     dev_info(dev, "revision - %s\n", revision);
0556 
0557     return 0;
0558 }
0559 
0560 static int cs2000_remove(struct i2c_client *client)
0561 {
0562     struct cs2000_priv *priv = i2c_get_clientdata(client);
0563     struct device *dev = priv_to_dev(priv);
0564     struct device_node *np = dev->of_node;
0565 
0566     of_clk_del_provider(np);
0567 
0568     clk_hw_unregister(&priv->hw);
0569 
0570     return 0;
0571 }
0572 
0573 static int cs2000_probe(struct i2c_client *client)
0574 {
0575     struct cs2000_priv *priv;
0576     struct device *dev = &client->dev;
0577     int ret;
0578 
0579     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0580     if (!priv)
0581         return -ENOMEM;
0582 
0583     priv->client = client;
0584     i2c_set_clientdata(client, priv);
0585 
0586     priv->regmap = devm_regmap_init_i2c(client, &cs2000_regmap_config);
0587     if (IS_ERR(priv->regmap))
0588         return PTR_ERR(priv->regmap);
0589 
0590     ret = cs2000_clk_get(priv);
0591     if (ret < 0)
0592         return ret;
0593 
0594     ret = cs2000_clk_register(priv);
0595     if (ret < 0)
0596         return ret;
0597 
0598     ret = cs2000_version_print(priv);
0599     if (ret < 0)
0600         goto probe_err;
0601 
0602     return 0;
0603 
0604 probe_err:
0605     cs2000_remove(client);
0606 
0607     return ret;
0608 }
0609 
0610 static int __maybe_unused cs2000_resume(struct device *dev)
0611 {
0612     struct cs2000_priv *priv = dev_get_drvdata(dev);
0613 
0614     return cs2000_set_saved_rate(priv);
0615 }
0616 
0617 static const struct dev_pm_ops cs2000_pm_ops = {
0618     SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, cs2000_resume)
0619 };
0620 
0621 static struct i2c_driver cs2000_driver = {
0622     .driver = {
0623         .name = "cs2000-cp",
0624         .pm = &cs2000_pm_ops,
0625         .of_match_table = cs2000_of_match,
0626     },
0627     .probe_new  = cs2000_probe,
0628     .remove     = cs2000_remove,
0629     .id_table   = cs2000_id,
0630 };
0631 
0632 module_i2c_driver(cs2000_driver);
0633 
0634 MODULE_DESCRIPTION("CS2000-CP driver");
0635 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
0636 MODULE_LICENSE("GPL v2");