root/sound/soc/codecs/tlv320aic32x4-clk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clk_aic32x4_pll_prepare
  2. clk_aic32x4_pll_unprepare
  3. clk_aic32x4_pll_is_prepared
  4. clk_aic32x4_pll_get_muldiv
  5. clk_aic32x4_pll_set_muldiv
  6. clk_aic32x4_pll_calc_rate
  7. clk_aic32x4_pll_calc_muldiv
  8. clk_aic32x4_pll_recalc_rate
  9. clk_aic32x4_pll_round_rate
  10. clk_aic32x4_pll_set_rate
  11. clk_aic32x4_pll_set_parent
  12. clk_aic32x4_pll_get_parent
  13. clk_aic32x4_codec_clkin_set_parent
  14. clk_aic32x4_codec_clkin_get_parent
  15. clk_aic32x4_div_prepare
  16. clk_aic32x4_div_unprepare
  17. clk_aic32x4_div_set_rate
  18. clk_aic32x4_div_round_rate
  19. clk_aic32x4_div_recalc_rate
  20. clk_aic32x4_bdiv_set_parent
  21. clk_aic32x4_bdiv_get_parent
  22. aic32x4_register_clk
  23. aic32x4_register_clocks

   1 /* SPDX-License-Identifier: GPL-2.0
   2  *
   3  * Clock Tree for the Texas Instruments TLV320AIC32x4
   4  *
   5  * Copyright 2019 Annaliese McDermond
   6  *
   7  * Author: Annaliese McDermond <nh6z@nh6z.net>
   8  */
   9 
  10 #include <linux/clk-provider.h>
  11 #include <linux/clkdev.h>
  12 #include <linux/regmap.h>
  13 #include <linux/device.h>
  14 
  15 #include "tlv320aic32x4.h"
  16 
  17 #define to_clk_aic32x4(_hw) container_of(_hw, struct clk_aic32x4, hw)
  18 struct clk_aic32x4 {
  19         struct clk_hw hw;
  20         struct device *dev;
  21         struct regmap *regmap;
  22         unsigned int reg;
  23 };
  24 
  25 /*
  26  * struct clk_aic32x4_pll_muldiv - Multiplier/divider settings
  27  * @p:          Divider
  28  * @r:          first multiplier
  29  * @j:          integer part of second multiplier
  30  * @d:          decimal part of second multiplier
  31  */
  32 struct clk_aic32x4_pll_muldiv {
  33         u8 p;
  34         u16 r;
  35         u8 j;
  36         u16 d;
  37 };
  38 
  39 struct aic32x4_clkdesc {
  40         const char *name;
  41         const char * const *parent_names;
  42         unsigned int num_parents;
  43         const struct clk_ops *ops;
  44         unsigned int reg;
  45 };
  46 
  47 static int clk_aic32x4_pll_prepare(struct clk_hw *hw)
  48 {
  49         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
  50 
  51         return regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
  52                                 AIC32X4_PLLEN, AIC32X4_PLLEN);
  53 }
  54 
  55 static void clk_aic32x4_pll_unprepare(struct clk_hw *hw)
  56 {
  57         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
  58 
  59         regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
  60                                 AIC32X4_PLLEN, 0);
  61 }
  62 
  63 static int clk_aic32x4_pll_is_prepared(struct clk_hw *hw)
  64 {
  65         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
  66 
  67         unsigned int val;
  68         int ret;
  69 
  70         ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
  71         if (ret < 0)
  72                 return ret;
  73 
  74         return !!(val & AIC32X4_PLLEN);
  75 }
  76 
  77 static int clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll,
  78                         struct clk_aic32x4_pll_muldiv *settings)
  79 {
  80         /*      Change to use regmap_bulk_read? */
  81         unsigned int val;
  82         int ret;
  83 
  84         ret = regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
  85         if (ret < 0)
  86                 return ret;
  87         settings->r = val & AIC32X4_PLL_R_MASK;
  88         settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT;
  89 
  90         ret = regmap_read(pll->regmap, AIC32X4_PLLJ, &val);
  91         if (ret < 0)
  92                 return ret;
  93         settings->j = val;
  94 
  95         ret = regmap_read(pll->regmap, AIC32X4_PLLDMSB, &val);
  96         if (ret < 0)
  97                 return ret;
  98         settings->d = val << 8;
  99 
 100         ret = regmap_read(pll->regmap, AIC32X4_PLLDLSB,  &val);
 101         if (ret < 0)
 102                 return ret;
 103         settings->d |= val;
 104 
 105         return 0;
 106 }
 107 
 108 static int clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll,
 109                         struct clk_aic32x4_pll_muldiv *settings)
 110 {
 111         int ret;
 112         /*      Change to use regmap_bulk_write for some if not all? */
 113 
 114         ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
 115                                 AIC32X4_PLL_R_MASK, settings->r);
 116         if (ret < 0)
 117                 return ret;
 118 
 119         ret = regmap_update_bits(pll->regmap, AIC32X4_PLLPR,
 120                                 AIC32X4_PLL_P_MASK,
 121                                 settings->p << AIC32X4_PLL_P_SHIFT);
 122         if (ret < 0)
 123                 return ret;
 124 
 125         ret = regmap_write(pll->regmap, AIC32X4_PLLJ, settings->j);
 126         if (ret < 0)
 127                 return ret;
 128 
 129         ret = regmap_write(pll->regmap, AIC32X4_PLLDMSB, (settings->d >> 8));
 130         if (ret < 0)
 131                 return ret;
 132         ret = regmap_write(pll->regmap, AIC32X4_PLLDLSB, (settings->d & 0xff));
 133         if (ret < 0)
 134                 return ret;
 135 
 136         return 0;
 137 }
 138 
 139 static unsigned long clk_aic32x4_pll_calc_rate(
 140                         struct clk_aic32x4_pll_muldiv *settings,
 141                         unsigned long parent_rate)
 142 {
 143         u64 rate;
 144         /*
 145          * We scale j by 10000 to account for the decimal part of P and divide
 146          * it back out later.
 147          */
 148         rate = (u64) parent_rate * settings->r *
 149                                 ((settings->j * 10000) + settings->d);
 150 
 151         return (unsigned long) DIV_ROUND_UP_ULL(rate, settings->p * 10000);
 152 }
 153 
 154 static int clk_aic32x4_pll_calc_muldiv(struct clk_aic32x4_pll_muldiv *settings,
 155                         unsigned long rate, unsigned long parent_rate)
 156 {
 157         u64 multiplier;
 158 
 159         settings->p = parent_rate / AIC32X4_MAX_PLL_CLKIN + 1;
 160         if (settings->p > 8)
 161                 return -1;
 162 
 163         /*
 164          * We scale this figure by 10000 so that we can get the decimal part
 165          * of the multiplier.   This is because we can't do floating point
 166          * math in the kernel.
 167          */
 168         multiplier = (u64) rate * settings->p * 10000;
 169         do_div(multiplier, parent_rate);
 170 
 171         /*
 172          * J can't be over 64, so R can scale this.
 173          * R can't be greater than 4.
 174          */
 175         settings->r = ((u32) multiplier / 640000) + 1;
 176         if (settings->r > 4)
 177                 return -1;
 178         do_div(multiplier, settings->r);
 179 
 180         /*
 181          * J can't be < 1.
 182          */
 183         if (multiplier < 10000)
 184                 return -1;
 185 
 186         /* Figure out the integer part, J, and the fractional part, D. */
 187         settings->j = (u32) multiplier / 10000;
 188         settings->d = (u32) multiplier % 10000;
 189 
 190         return 0;
 191 }
 192 
 193 static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw,
 194                         unsigned long parent_rate)
 195 {
 196         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
 197         struct clk_aic32x4_pll_muldiv settings;
 198         int ret;
 199 
 200         ret =  clk_aic32x4_pll_get_muldiv(pll, &settings);
 201         if (ret < 0)
 202                 return 0;
 203 
 204         return clk_aic32x4_pll_calc_rate(&settings, parent_rate);
 205 }
 206 
 207 static long clk_aic32x4_pll_round_rate(struct clk_hw *hw,
 208                         unsigned long rate,
 209                         unsigned long *parent_rate)
 210 {
 211         struct clk_aic32x4_pll_muldiv settings;
 212         int ret;
 213 
 214         ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, *parent_rate);
 215         if (ret < 0)
 216                 return 0;
 217 
 218         return clk_aic32x4_pll_calc_rate(&settings, *parent_rate);
 219 }
 220 
 221 static int clk_aic32x4_pll_set_rate(struct clk_hw *hw,
 222                         unsigned long rate,
 223                         unsigned long parent_rate)
 224 {
 225         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
 226         struct clk_aic32x4_pll_muldiv settings;
 227         int ret;
 228 
 229         ret = clk_aic32x4_pll_calc_muldiv(&settings, rate, parent_rate);
 230         if (ret < 0)
 231                 return -EINVAL;
 232 
 233         return clk_aic32x4_pll_set_muldiv(pll, &settings);
 234 }
 235 
 236 static int clk_aic32x4_pll_set_parent(struct clk_hw *hw, u8 index)
 237 {
 238         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
 239 
 240         return regmap_update_bits(pll->regmap,
 241                                 AIC32X4_CLKMUX,
 242                                 AIC32X4_PLL_CLKIN_MASK,
 243                                 index << AIC32X4_PLL_CLKIN_SHIFT);
 244 }
 245 
 246 static u8 clk_aic32x4_pll_get_parent(struct clk_hw *hw)
 247 {
 248         struct clk_aic32x4 *pll = to_clk_aic32x4(hw);
 249         unsigned int val;
 250 
 251         regmap_read(pll->regmap, AIC32X4_PLLPR, &val);
 252 
 253         return (val & AIC32X4_PLL_CLKIN_MASK) >> AIC32X4_PLL_CLKIN_SHIFT;
 254 }
 255 
 256 
 257 static const struct clk_ops aic32x4_pll_ops = {
 258         .prepare = clk_aic32x4_pll_prepare,
 259         .unprepare = clk_aic32x4_pll_unprepare,
 260         .is_prepared = clk_aic32x4_pll_is_prepared,
 261         .recalc_rate = clk_aic32x4_pll_recalc_rate,
 262         .round_rate = clk_aic32x4_pll_round_rate,
 263         .set_rate = clk_aic32x4_pll_set_rate,
 264         .set_parent = clk_aic32x4_pll_set_parent,
 265         .get_parent = clk_aic32x4_pll_get_parent,
 266 };
 267 
 268 static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index)
 269 {
 270         struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
 271 
 272         return regmap_update_bits(mux->regmap,
 273                 AIC32X4_CLKMUX,
 274                 AIC32X4_CODEC_CLKIN_MASK, index << AIC32X4_CODEC_CLKIN_SHIFT);
 275 }
 276 
 277 static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw)
 278 {
 279         struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
 280         unsigned int val;
 281 
 282         regmap_read(mux->regmap, AIC32X4_CLKMUX, &val);
 283 
 284         return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT;
 285 }
 286 
 287 static const struct clk_ops aic32x4_codec_clkin_ops = {
 288         .set_parent = clk_aic32x4_codec_clkin_set_parent,
 289         .get_parent = clk_aic32x4_codec_clkin_get_parent,
 290 };
 291 
 292 static int clk_aic32x4_div_prepare(struct clk_hw *hw)
 293 {
 294         struct clk_aic32x4 *div = to_clk_aic32x4(hw);
 295 
 296         return regmap_update_bits(div->regmap, div->reg,
 297                                 AIC32X4_DIVEN, AIC32X4_DIVEN);
 298 }
 299 
 300 static void clk_aic32x4_div_unprepare(struct clk_hw *hw)
 301 {
 302         struct clk_aic32x4 *div = to_clk_aic32x4(hw);
 303 
 304         regmap_update_bits(div->regmap, div->reg,
 305                         AIC32X4_DIVEN, 0);
 306 }
 307 
 308 static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate,
 309                                 unsigned long parent_rate)
 310 {
 311         struct clk_aic32x4 *div = to_clk_aic32x4(hw);
 312         u8 divisor;
 313 
 314         divisor = DIV_ROUND_UP(parent_rate, rate);
 315         if (divisor > 128)
 316                 return -EINVAL;
 317 
 318         return regmap_update_bits(div->regmap, div->reg,
 319                                 AIC32X4_DIV_MASK, divisor);
 320 }
 321 
 322 static long clk_aic32x4_div_round_rate(struct clk_hw *hw, unsigned long rate,
 323                                 unsigned long *parent_rate)
 324 {
 325         unsigned long divisor;
 326 
 327         divisor = DIV_ROUND_UP(*parent_rate, rate);
 328         if (divisor > 128)
 329                 return -EINVAL;
 330 
 331         return DIV_ROUND_UP(*parent_rate, divisor);
 332 }
 333 
 334 static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw,
 335                                                 unsigned long parent_rate)
 336 {
 337         struct clk_aic32x4 *div = to_clk_aic32x4(hw);
 338 
 339         unsigned int val;
 340 
 341         regmap_read(div->regmap, div->reg, &val);
 342 
 343         return DIV_ROUND_UP(parent_rate, val & AIC32X4_DIV_MASK);
 344 }
 345 
 346 static const struct clk_ops aic32x4_div_ops = {
 347         .prepare = clk_aic32x4_div_prepare,
 348         .unprepare = clk_aic32x4_div_unprepare,
 349         .set_rate = clk_aic32x4_div_set_rate,
 350         .round_rate = clk_aic32x4_div_round_rate,
 351         .recalc_rate = clk_aic32x4_div_recalc_rate,
 352 };
 353 
 354 static int clk_aic32x4_bdiv_set_parent(struct clk_hw *hw, u8 index)
 355 {
 356         struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
 357 
 358         return regmap_update_bits(mux->regmap, AIC32X4_IFACE3,
 359                                 AIC32X4_BDIVCLK_MASK, index);
 360 }
 361 
 362 static u8 clk_aic32x4_bdiv_get_parent(struct clk_hw *hw)
 363 {
 364         struct clk_aic32x4 *mux = to_clk_aic32x4(hw);
 365         unsigned int val;
 366 
 367         regmap_read(mux->regmap, AIC32X4_IFACE3, &val);
 368 
 369         return val & AIC32X4_BDIVCLK_MASK;
 370 }
 371 
 372 static const struct clk_ops aic32x4_bdiv_ops = {
 373         .prepare = clk_aic32x4_div_prepare,
 374         .unprepare = clk_aic32x4_div_unprepare,
 375         .set_parent = clk_aic32x4_bdiv_set_parent,
 376         .get_parent = clk_aic32x4_bdiv_get_parent,
 377         .set_rate = clk_aic32x4_div_set_rate,
 378         .round_rate = clk_aic32x4_div_round_rate,
 379         .recalc_rate = clk_aic32x4_div_recalc_rate,
 380 };
 381 
 382 static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = {
 383         {
 384                 .name = "pll",
 385                 .parent_names =
 386                         (const char* []) { "mclk", "bclk", "gpio", "din" },
 387                 .num_parents = 4,
 388                 .ops = &aic32x4_pll_ops,
 389                 .reg = 0,
 390         },
 391         {
 392                 .name = "codec_clkin",
 393                 .parent_names =
 394                         (const char *[]) { "mclk", "bclk", "gpio", "pll" },
 395                 .num_parents = 4,
 396                 .ops = &aic32x4_codec_clkin_ops,
 397                 .reg = 0,
 398         },
 399         {
 400                 .name = "ndac",
 401                 .parent_names = (const char * []) { "codec_clkin" },
 402                 .num_parents = 1,
 403                 .ops = &aic32x4_div_ops,
 404                 .reg = AIC32X4_NDAC,
 405         },
 406         {
 407                 .name = "mdac",
 408                 .parent_names = (const char * []) { "ndac" },
 409                 .num_parents = 1,
 410                 .ops = &aic32x4_div_ops,
 411                 .reg = AIC32X4_MDAC,
 412         },
 413         {
 414                 .name = "nadc",
 415                 .parent_names = (const char * []) { "codec_clkin" },
 416                 .num_parents = 1,
 417                 .ops = &aic32x4_div_ops,
 418                 .reg = AIC32X4_NADC,
 419         },
 420         {
 421                 .name = "madc",
 422                 .parent_names = (const char * []) { "nadc" },
 423                 .num_parents = 1,
 424                 .ops = &aic32x4_div_ops,
 425                 .reg = AIC32X4_MADC,
 426         },
 427         {
 428                 .name = "bdiv",
 429                 .parent_names =
 430                         (const char *[]) { "ndac", "mdac", "nadc", "madc" },
 431                 .num_parents = 4,
 432                 .ops = &aic32x4_bdiv_ops,
 433                 .reg = AIC32X4_BCLKN,
 434         },
 435 };
 436 
 437 static struct clk *aic32x4_register_clk(struct device *dev,
 438                         struct aic32x4_clkdesc *desc)
 439 {
 440         struct clk_init_data init;
 441         struct clk_aic32x4 *priv;
 442         const char *devname = dev_name(dev);
 443 
 444         init.ops = desc->ops;
 445         init.name = desc->name;
 446         init.parent_names = desc->parent_names;
 447         init.num_parents = desc->num_parents;
 448         init.flags = 0;
 449 
 450         priv = devm_kzalloc(dev, sizeof(struct clk_aic32x4), GFP_KERNEL);
 451         if (priv == NULL)
 452                 return (struct clk *) -ENOMEM;
 453 
 454         priv->dev = dev;
 455         priv->hw.init = &init;
 456         priv->regmap = dev_get_regmap(dev, NULL);
 457         priv->reg = desc->reg;
 458 
 459         clk_hw_register_clkdev(&priv->hw, desc->name, devname);
 460         return devm_clk_register(dev, &priv->hw);
 461 }
 462 
 463 int aic32x4_register_clocks(struct device *dev, const char *mclk_name)
 464 {
 465         int i;
 466 
 467         /*
 468          * These lines are here to preserve the current functionality of
 469          * the driver with regard to the DT.  These should eventually be set
 470          * by DT nodes so that the connections can be set up in configuration
 471          * rather than code.
 472          */
 473         aic32x4_clkdesc_array[0].parent_names =
 474                         (const char* []) { mclk_name, "bclk", "gpio", "din" };
 475         aic32x4_clkdesc_array[1].parent_names =
 476                         (const char *[]) { mclk_name, "bclk", "gpio", "pll" };
 477 
 478         for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i)
 479                 aic32x4_register_clk(dev, &aic32x4_clkdesc_array[i]);
 480 
 481         return 0;
 482 }
 483 EXPORT_SYMBOL_GPL(aic32x4_register_clocks);

/* [<][>][^][v][top][bottom][index][help] */