linux/drivers/clk/clk-wm831x.c
<<
>>
Prefs
   1/*
   2 * WM831x clock control
   3 *
   4 * Copyright 2011-2 Wolfson Microelectronics PLC.
   5 *
   6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 *
  13 */
  14
  15#include <linux/clk.h>
  16#include <linux/clk-provider.h>
  17#include <linux/delay.h>
  18#include <linux/module.h>
  19#include <linux/slab.h>
  20#include <linux/platform_device.h>
  21#include <linux/mfd/wm831x/core.h>
  22
  23struct wm831x_clk {
  24        struct wm831x *wm831x;
  25        struct clk_hw xtal_hw;
  26        struct clk_hw fll_hw;
  27        struct clk_hw clkout_hw;
  28        struct clk *xtal;
  29        struct clk *fll;
  30        struct clk *clkout;
  31        bool xtal_ena;
  32};
  33
  34static int wm831x_xtal_is_enabled(struct clk_hw *hw)
  35{
  36        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  37                                                  xtal_hw);
  38
  39        return clkdata->xtal_ena;
  40}
  41
  42static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw,
  43                                             unsigned long parent_rate)
  44{
  45        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  46                                                  xtal_hw);
  47
  48        if (clkdata->xtal_ena)
  49                return 32768;
  50        else
  51                return 0;
  52}
  53
  54static const struct clk_ops wm831x_xtal_ops = {
  55        .is_enabled = wm831x_xtal_is_enabled,
  56        .recalc_rate = wm831x_xtal_recalc_rate,
  57};
  58
  59static struct clk_init_data wm831x_xtal_init = {
  60        .name = "xtal",
  61        .ops = &wm831x_xtal_ops,
  62        .flags = CLK_IS_ROOT,
  63};
  64
  65static const unsigned long wm831x_fll_auto_rates[] = {
  66         2048000,
  67        11289600,
  68        12000000,
  69        12288000,
  70        19200000,
  71        22579600,
  72        24000000,
  73        24576000,
  74};
  75
  76static int wm831x_fll_is_enabled(struct clk_hw *hw)
  77{
  78        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  79                                                  fll_hw);
  80        struct wm831x *wm831x = clkdata->wm831x;
  81        int ret;
  82
  83        ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
  84        if (ret < 0) {
  85                dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
  86                        ret);
  87                return true;
  88        }
  89
  90        return (ret & WM831X_FLL_ENA) != 0;
  91}
  92
  93static int wm831x_fll_prepare(struct clk_hw *hw)
  94{
  95        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
  96                                                  fll_hw);
  97        struct wm831x *wm831x = clkdata->wm831x;
  98        int ret;
  99
 100        ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
 101                              WM831X_FLL_ENA, WM831X_FLL_ENA);
 102        if (ret != 0)
 103                dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
 104
 105        usleep_range(2000, 2000);
 106
 107        return ret;
 108}
 109
 110static void wm831x_fll_unprepare(struct clk_hw *hw)
 111{
 112        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 113                                                  fll_hw);
 114        struct wm831x *wm831x = clkdata->wm831x;
 115        int ret;
 116
 117        ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
 118        if (ret != 0)
 119                dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
 120}
 121
 122static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
 123                                            unsigned long parent_rate)
 124{
 125        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 126                                                  fll_hw);
 127        struct wm831x *wm831x = clkdata->wm831x;
 128        int ret;
 129
 130        ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
 131        if (ret < 0) {
 132                dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
 133                        ret);
 134                return 0;
 135        }
 136
 137        if (ret & WM831X_FLL_AUTO)
 138                return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
 139
 140        dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
 141
 142        return 0;
 143}
 144
 145static long wm831x_fll_round_rate(struct clk_hw *hw, unsigned long rate,
 146                                  unsigned long *unused)
 147{
 148        int best = 0;
 149        int i;
 150
 151        for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
 152                if (abs(wm831x_fll_auto_rates[i] - rate) <
 153                    abs(wm831x_fll_auto_rates[best] - rate))
 154                        best = i;
 155
 156        return wm831x_fll_auto_rates[best];
 157}
 158
 159static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
 160                               unsigned long parent_rate)
 161{
 162        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 163                                                  fll_hw);
 164        struct wm831x *wm831x = clkdata->wm831x;
 165        int i;
 166
 167        for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
 168                if (wm831x_fll_auto_rates[i] == rate)
 169                        break;
 170        if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
 171                return -EINVAL;
 172
 173        if (wm831x_fll_is_enabled(hw))
 174                return -EPERM;
 175
 176        return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
 177                               WM831X_FLL_AUTO_FREQ_MASK, i);
 178}
 179
 180static const char *wm831x_fll_parents[] = {
 181        "xtal",
 182        "clkin",
 183};
 184
 185static u8 wm831x_fll_get_parent(struct clk_hw *hw)
 186{
 187        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 188                                                  fll_hw);
 189        struct wm831x *wm831x = clkdata->wm831x;
 190        int ret;
 191
 192        /* AUTO mode is always clocked from the crystal */
 193        ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
 194        if (ret < 0) {
 195                dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
 196                        ret);
 197                return 0;
 198        }
 199
 200        if (ret & WM831X_FLL_AUTO)
 201                return 0;
 202
 203        ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
 204        if (ret < 0) {
 205                dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
 206                        ret);
 207                return 0;
 208        }
 209
 210        switch (ret & WM831X_FLL_CLK_SRC_MASK) {
 211        case 0:
 212                return 0;
 213        case 1:
 214                return 1;
 215        default:
 216                dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
 217                        ret & WM831X_FLL_CLK_SRC_MASK);
 218                return 0;
 219        }
 220}
 221
 222static const struct clk_ops wm831x_fll_ops = {
 223        .is_enabled = wm831x_fll_is_enabled,
 224        .prepare = wm831x_fll_prepare,
 225        .unprepare = wm831x_fll_unprepare,
 226        .round_rate = wm831x_fll_round_rate,
 227        .recalc_rate = wm831x_fll_recalc_rate,
 228        .set_rate = wm831x_fll_set_rate,
 229        .get_parent = wm831x_fll_get_parent,
 230};
 231
 232static struct clk_init_data wm831x_fll_init = {
 233        .name = "fll",
 234        .ops = &wm831x_fll_ops,
 235        .parent_names = wm831x_fll_parents,
 236        .num_parents = ARRAY_SIZE(wm831x_fll_parents),
 237        .flags = CLK_SET_RATE_GATE,
 238};
 239
 240static int wm831x_clkout_is_enabled(struct clk_hw *hw)
 241{
 242        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 243                                                  clkout_hw);
 244        struct wm831x *wm831x = clkdata->wm831x;
 245        int ret;
 246
 247        ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
 248        if (ret < 0) {
 249                dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
 250                        ret);
 251                return true;
 252        }
 253
 254        return (ret & WM831X_CLKOUT_ENA) != 0;
 255}
 256
 257static int wm831x_clkout_prepare(struct clk_hw *hw)
 258{
 259        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 260                                                  clkout_hw);
 261        struct wm831x *wm831x = clkdata->wm831x;
 262        int ret;
 263
 264        ret = wm831x_reg_unlock(wm831x);
 265        if (ret != 0) {
 266                dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
 267                return ret;
 268        }
 269
 270        ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
 271                              WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
 272        if (ret != 0)
 273                dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
 274
 275        wm831x_reg_lock(wm831x);
 276
 277        return ret;
 278}
 279
 280static void wm831x_clkout_unprepare(struct clk_hw *hw)
 281{
 282        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 283                                                  clkout_hw);
 284        struct wm831x *wm831x = clkdata->wm831x;
 285        int ret;
 286
 287        ret = wm831x_reg_unlock(wm831x);
 288        if (ret != 0) {
 289                dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
 290                return;
 291        }
 292
 293        ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
 294                              WM831X_CLKOUT_ENA, 0);
 295        if (ret != 0)
 296                dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
 297
 298        wm831x_reg_lock(wm831x);
 299}
 300
 301static const char *wm831x_clkout_parents[] = {
 302        "xtal",
 303        "fll",
 304};
 305
 306static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
 307{
 308        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 309                                                  clkout_hw);
 310        struct wm831x *wm831x = clkdata->wm831x;
 311        int ret;
 312
 313        ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
 314        if (ret < 0) {
 315                dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
 316                        ret);
 317                return 0;
 318        }
 319
 320        if (ret & WM831X_CLKOUT_SRC)
 321                return 0;
 322        else
 323                return 1;
 324}
 325
 326static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
 327{
 328        struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
 329                                                  clkout_hw);
 330        struct wm831x *wm831x = clkdata->wm831x;
 331
 332        return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
 333                               WM831X_CLKOUT_SRC,
 334                               parent << WM831X_CLKOUT_SRC_SHIFT);
 335}
 336
 337static const struct clk_ops wm831x_clkout_ops = {
 338        .is_enabled = wm831x_clkout_is_enabled,
 339        .prepare = wm831x_clkout_prepare,
 340        .unprepare = wm831x_clkout_unprepare,
 341        .get_parent = wm831x_clkout_get_parent,
 342        .set_parent = wm831x_clkout_set_parent,
 343};
 344
 345static struct clk_init_data wm831x_clkout_init = {
 346        .name = "clkout",
 347        .ops = &wm831x_clkout_ops,
 348        .parent_names = wm831x_clkout_parents,
 349        .num_parents = ARRAY_SIZE(wm831x_clkout_parents),
 350        .flags = CLK_SET_RATE_PARENT,
 351};
 352
 353static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 354{
 355        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 356        struct wm831x_clk *clkdata;
 357        int ret;
 358
 359        clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
 360        if (!clkdata)
 361                return -ENOMEM;
 362
 363        /* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
 364        ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
 365        if (ret < 0) {
 366                dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
 367                        ret);
 368                return ret;
 369        }
 370        clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
 371
 372        clkdata->xtal_hw.init = &wm831x_xtal_init;
 373        clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
 374        if (!clkdata->xtal)
 375                return -EINVAL;
 376
 377        clkdata->fll_hw.init = &wm831x_fll_init;
 378        clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
 379        if (!clkdata->fll) {
 380                ret = -EINVAL;
 381                goto err_xtal;
 382        }
 383
 384        clkdata->clkout_hw.init = &wm831x_clkout_init;
 385        clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
 386        if (!clkdata->clkout) {
 387                ret = -EINVAL;
 388                goto err_fll;
 389        }
 390
 391        dev_set_drvdata(&pdev->dev, clkdata);
 392
 393        return 0;
 394
 395err_fll:
 396        clk_unregister(clkdata->fll);
 397err_xtal:
 398        clk_unregister(clkdata->xtal);
 399        return ret;
 400}
 401
 402static int __devexit wm831x_clk_remove(struct platform_device *pdev)
 403{
 404        struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
 405
 406        clk_unregister(clkdata->clkout);
 407        clk_unregister(clkdata->fll);
 408        clk_unregister(clkdata->xtal);
 409
 410        return 0;
 411}
 412
 413static struct platform_driver wm831x_clk_driver = {
 414        .probe = wm831x_clk_probe,
 415        .remove = __devexit_p(wm831x_clk_remove),
 416        .driver         = {
 417                .name   = "wm831x-clk",
 418                .owner  = THIS_MODULE,
 419        },
 420};
 421
 422module_platform_driver(wm831x_clk_driver);
 423
 424/* Module information */
 425MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 426MODULE_DESCRIPTION("WM831x clock driver");
 427MODULE_LICENSE("GPL");
 428MODULE_ALIAS("platform:wm831x-clk");
 429
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.