linux/drivers/clk/keystone/sci-clk.c
<<
>>
Prefs
   1/*
   2 * SCI Clock driver for keystone based devices
   3 *
   4 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
   5 *      Tero Kristo <t-kristo@ti.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  12 * kind, whether express or implied; without even the implied warranty
  13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16#include <linux/clk-provider.h>
  17#include <linux/err.h>
  18#include <linux/io.h>
  19#include <linux/module.h>
  20#include <linux/of_address.h>
  21#include <linux/of_device.h>
  22#include <linux/platform_device.h>
  23#include <linux/slab.h>
  24#include <linux/soc/ti/ti_sci_protocol.h>
  25#include <linux/bsearch.h>
  26
  27#define SCI_CLK_SSC_ENABLE              BIT(0)
  28#define SCI_CLK_ALLOW_FREQ_CHANGE       BIT(1)
  29#define SCI_CLK_INPUT_TERMINATION       BIT(2)
  30
  31/**
  32 * struct sci_clk_provider - TI SCI clock provider representation
  33 * @sci: Handle to the System Control Interface protocol handler
  34 * @ops: Pointer to the SCI ops to be used by the clocks
  35 * @dev: Device pointer for the clock provider
  36 * @clocks: Clocks array for this device
  37 * @num_clocks: Total number of clocks for this provider
  38 */
  39struct sci_clk_provider {
  40        const struct ti_sci_handle *sci;
  41        const struct ti_sci_clk_ops *ops;
  42        struct device *dev;
  43        struct sci_clk **clocks;
  44        int num_clocks;
  45};
  46
  47/**
  48 * struct sci_clk - TI SCI clock representation
  49 * @hw:          Hardware clock cookie for common clock framework
  50 * @dev_id:      Device index
  51 * @clk_id:      Clock index
  52 * @num_parents: Number of parents for this clock
  53 * @provider:    Master clock provider
  54 * @flags:       Flags for the clock
  55 */
  56struct sci_clk {
  57        struct clk_hw hw;
  58        u16 dev_id;
  59        u8 clk_id;
  60        u8 num_parents;
  61        struct sci_clk_provider *provider;
  62        u8 flags;
  63};
  64
  65#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
  66
  67/**
  68 * sci_clk_prepare - Prepare (enable) a TI SCI clock
  69 * @hw: clock to prepare
  70 *
  71 * Prepares a clock to be actively used. Returns the SCI protocol status.
  72 */
  73static int sci_clk_prepare(struct clk_hw *hw)
  74{
  75        struct sci_clk *clk = to_sci_clk(hw);
  76        bool enable_ssc = clk->flags & SCI_CLK_SSC_ENABLE;
  77        bool allow_freq_change = clk->flags & SCI_CLK_ALLOW_FREQ_CHANGE;
  78        bool input_termination = clk->flags & SCI_CLK_INPUT_TERMINATION;
  79
  80        return clk->provider->ops->get_clock(clk->provider->sci, clk->dev_id,
  81                                             clk->clk_id, enable_ssc,
  82                                             allow_freq_change,
  83                                             input_termination);
  84}
  85
  86/**
  87 * sci_clk_unprepare - Un-prepares (disables) a TI SCI clock
  88 * @hw: clock to unprepare
  89 *
  90 * Un-prepares a clock from active state.
  91 */
  92static void sci_clk_unprepare(struct clk_hw *hw)
  93{
  94        struct sci_clk *clk = to_sci_clk(hw);
  95        int ret;
  96
  97        ret = clk->provider->ops->put_clock(clk->provider->sci, clk->dev_id,
  98                                            clk->clk_id);
  99        if (ret)
 100                dev_err(clk->provider->dev,
 101                        "unprepare failed for dev=%d, clk=%d, ret=%d\n",
 102                        clk->dev_id, clk->clk_id, ret);
 103}
 104
 105/**
 106 * sci_clk_is_prepared - Check if a TI SCI clock is prepared or not
 107 * @hw: clock to check status for
 108 *
 109 * Checks if a clock is prepared (enabled) in hardware. Returns non-zero
 110 * value if clock is enabled, zero otherwise.
 111 */
 112static int sci_clk_is_prepared(struct clk_hw *hw)
 113{
 114        struct sci_clk *clk = to_sci_clk(hw);
 115        bool req_state, current_state;
 116        int ret;
 117
 118        ret = clk->provider->ops->is_on(clk->provider->sci, clk->dev_id,
 119                                        clk->clk_id, &req_state,
 120                                        &current_state);
 121        if (ret) {
 122                dev_err(clk->provider->dev,
 123                        "is_prepared failed for dev=%d, clk=%d, ret=%d\n",
 124                        clk->dev_id, clk->clk_id, ret);
 125                return 0;
 126        }
 127
 128        return req_state;
 129}
 130
 131/**
 132 * sci_clk_recalc_rate - Get clock rate for a TI SCI clock
 133 * @hw: clock to get rate for
 134 * @parent_rate: parent rate provided by common clock framework, not used
 135 *
 136 * Gets the current clock rate of a TI SCI clock. Returns the current
 137 * clock rate, or zero in failure.
 138 */
 139static unsigned long sci_clk_recalc_rate(struct clk_hw *hw,
 140                                         unsigned long parent_rate)
 141{
 142        struct sci_clk *clk = to_sci_clk(hw);
 143        u64 freq;
 144        int ret;
 145
 146        ret = clk->provider->ops->get_freq(clk->provider->sci, clk->dev_id,
 147                                           clk->clk_id, &freq);
 148        if (ret) {
 149                dev_err(clk->provider->dev,
 150                        "recalc-rate failed for dev=%d, clk=%d, ret=%d\n",
 151                        clk->dev_id, clk->clk_id, ret);
 152                return 0;
 153        }
 154
 155        return freq;
 156}
 157
 158/**
 159 * sci_clk_determine_rate - Determines a clock rate a clock can be set to
 160 * @hw: clock to change rate for
 161 * @req: requested rate configuration for the clock
 162 *
 163 * Determines a suitable clock rate and parent for a TI SCI clock.
 164 * The parent handling is un-used, as generally the parent clock rates
 165 * are not known by the kernel; instead these are internally handled
 166 * by the firmware. Returns 0 on success, negative error value on failure.
 167 */
 168static int sci_clk_determine_rate(struct clk_hw *hw,
 169                                  struct clk_rate_request *req)
 170{
 171        struct sci_clk *clk = to_sci_clk(hw);
 172        int ret;
 173        u64 new_rate;
 174
 175        ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
 176                                                      clk->dev_id,
 177                                                      clk->clk_id,
 178                                                      req->min_rate,
 179                                                      req->rate,
 180                                                      req->max_rate,
 181                                                      &new_rate);
 182        if (ret) {
 183                dev_err(clk->provider->dev,
 184                        "determine-rate failed for dev=%d, clk=%d, ret=%d\n",
 185                        clk->dev_id, clk->clk_id, ret);
 186                return ret;
 187        }
 188
 189        req->rate = new_rate;
 190
 191        return 0;
 192}
 193
 194/**
 195 * sci_clk_set_rate - Set rate for a TI SCI clock
 196 * @hw: clock to change rate for
 197 * @rate: target rate for the clock
 198 * @parent_rate: rate of the clock parent, not used for TI SCI clocks
 199 *
 200 * Sets a clock frequency for a TI SCI clock. Returns the TI SCI
 201 * protocol status.
 202 */
 203static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 204                            unsigned long parent_rate)
 205{
 206        struct sci_clk *clk = to_sci_clk(hw);
 207
 208        return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
 209                                            clk->clk_id, rate, rate, rate);
 210}
 211
 212/**
 213 * sci_clk_get_parent - Get the current parent of a TI SCI clock
 214 * @hw: clock to get parent for
 215 *
 216 * Returns the index of the currently selected parent for a TI SCI clock.
 217 */
 218static u8 sci_clk_get_parent(struct clk_hw *hw)
 219{
 220        struct sci_clk *clk = to_sci_clk(hw);
 221        u8 parent_id;
 222        int ret;
 223
 224        ret = clk->provider->ops->get_parent(clk->provider->sci, clk->dev_id,
 225                                             clk->clk_id, &parent_id);
 226        if (ret) {
 227                dev_err(clk->provider->dev,
 228                        "get-parent failed for dev=%d, clk=%d, ret=%d\n",
 229                        clk->dev_id, clk->clk_id, ret);
 230                return 0;
 231        }
 232
 233        return parent_id - clk->clk_id - 1;
 234}
 235
 236/**
 237 * sci_clk_set_parent - Set the parent of a TI SCI clock
 238 * @hw: clock to set parent for
 239 * @index: new parent index for the clock
 240 *
 241 * Sets the parent of a TI SCI clock. Return TI SCI protocol status.
 242 */
 243static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
 244{
 245        struct sci_clk *clk = to_sci_clk(hw);
 246
 247        return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
 248                                              clk->clk_id,
 249                                              index + 1 + clk->clk_id);
 250}
 251
 252static const struct clk_ops sci_clk_ops = {
 253        .prepare = sci_clk_prepare,
 254        .unprepare = sci_clk_unprepare,
 255        .is_prepared = sci_clk_is_prepared,
 256        .recalc_rate = sci_clk_recalc_rate,
 257        .determine_rate = sci_clk_determine_rate,
 258        .set_rate = sci_clk_set_rate,
 259        .get_parent = sci_clk_get_parent,
 260        .set_parent = sci_clk_set_parent,
 261};
 262
 263/**
 264 * _sci_clk_get - Gets a handle for an SCI clock
 265 * @provider: Handle to SCI clock provider
 266 * @sci_clk: Handle to the SCI clock to populate
 267 *
 268 * Gets a handle to an existing TI SCI hw clock, or builds a new clock
 269 * entry and registers it with the common clock framework. Called from
 270 * the common clock framework, when a corresponding of_clk_get call is
 271 * executed, or recursively from itself when parsing parent clocks.
 272 * Returns 0 on success, negative error code on failure.
 273 */
 274static int _sci_clk_build(struct sci_clk_provider *provider,
 275                          struct sci_clk *sci_clk)
 276{
 277        struct clk_init_data init = { NULL };
 278        char *name = NULL;
 279        char **parent_names = NULL;
 280        int i;
 281        int ret = 0;
 282
 283        name = kasprintf(GFP_KERNEL, "%s:%d:%d", dev_name(provider->dev),
 284                         sci_clk->dev_id, sci_clk->clk_id);
 285
 286        init.name = name;
 287
 288        /*
 289         * From kernel point of view, we only care about a clocks parents,
 290         * if it has more than 1 possible parent. In this case, it is going
 291         * to have mux functionality. Otherwise it is going to act as a root
 292         * clock.
 293         */
 294        if (sci_clk->num_parents < 2)
 295                sci_clk->num_parents = 0;
 296
 297        if (sci_clk->num_parents) {
 298                parent_names = kcalloc(sci_clk->num_parents, sizeof(char *),
 299                                       GFP_KERNEL);
 300
 301                if (!parent_names) {
 302                        ret = -ENOMEM;
 303                        goto err;
 304                }
 305
 306                for (i = 0; i < sci_clk->num_parents; i++) {
 307                        char *parent_name;
 308
 309                        parent_name = kasprintf(GFP_KERNEL, "%s:%d:%d",
 310                                                dev_name(provider->dev),
 311                                                sci_clk->dev_id,
 312                                                sci_clk->clk_id + 1 + i);
 313                        if (!parent_name) {
 314                                ret = -ENOMEM;
 315                                goto err;
 316                        }
 317                        parent_names[i] = parent_name;
 318                }
 319                init.parent_names = (void *)parent_names;
 320        }
 321
 322        init.ops = &sci_clk_ops;
 323        init.num_parents = sci_clk->num_parents;
 324        sci_clk->hw.init = &init;
 325
 326        ret = devm_clk_hw_register(provider->dev, &sci_clk->hw);
 327        if (ret)
 328                dev_err(provider->dev, "failed clk register with %d\n", ret);
 329
 330err:
 331        if (parent_names) {
 332                for (i = 0; i < sci_clk->num_parents; i++)
 333                        kfree(parent_names[i]);
 334
 335                kfree(parent_names);
 336        }
 337
 338        kfree(name);
 339
 340        return ret;
 341}
 342
 343static int _cmp_sci_clk(const void *a, const void *b)
 344{
 345        const struct sci_clk *ca = a;
 346        const struct sci_clk *cb = *(struct sci_clk **)b;
 347
 348        if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id)
 349                return 0;
 350        if (ca->dev_id > cb->dev_id ||
 351            (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id))
 352                return 1;
 353        return -1;
 354}
 355
 356/**
 357 * sci_clk_get - Xlate function for getting clock handles
 358 * @clkspec: device tree clock specifier
 359 * @data: pointer to the clock provider
 360 *
 361 * Xlate function for retrieving clock TI SCI hw clock handles based on
 362 * device tree clock specifier. Called from the common clock framework,
 363 * when a corresponding of_clk_get call is executed. Returns a pointer
 364 * to the TI SCI hw clock struct, or ERR_PTR value in failure.
 365 */
 366static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data)
 367{
 368        struct sci_clk_provider *provider = data;
 369        struct sci_clk **clk;
 370        struct sci_clk key;
 371
 372        if (clkspec->args_count != 2)
 373                return ERR_PTR(-EINVAL);
 374
 375        key.dev_id = clkspec->args[0];
 376        key.clk_id = clkspec->args[1];
 377
 378        clk = bsearch(&key, provider->clocks, provider->num_clocks,
 379                      sizeof(clk), _cmp_sci_clk);
 380
 381        if (!clk)
 382                return ERR_PTR(-ENODEV);
 383
 384        return &(*clk)->hw;
 385}
 386
 387static int ti_sci_init_clocks(struct sci_clk_provider *p)
 388{
 389        int i;
 390        int ret;
 391
 392        for (i = 0; i < p->num_clocks; i++) {
 393                ret = _sci_clk_build(p, p->clocks[i]);
 394                if (ret)
 395                        return ret;
 396        }
 397
 398        return 0;
 399}
 400
 401static const struct of_device_id ti_sci_clk_of_match[] = {
 402        { .compatible = "ti,k2g-sci-clk" },
 403        { /* Sentinel */ },
 404};
 405MODULE_DEVICE_TABLE(of, ti_sci_clk_of_match);
 406
 407/**
 408 * ti_sci_clk_probe - Probe function for the TI SCI clock driver
 409 * @pdev: platform device pointer to be probed
 410 *
 411 * Probes the TI SCI clock device. Allocates a new clock provider
 412 * and registers this to the common clock framework. Also applies
 413 * any required flags to the identified clocks via clock lists
 414 * supplied from DT. Returns 0 for success, negative error value
 415 * for failure.
 416 */
 417static int ti_sci_clk_probe(struct platform_device *pdev)
 418{
 419        struct device *dev = &pdev->dev;
 420        struct device_node *np = dev->of_node;
 421        struct sci_clk_provider *provider;
 422        const struct ti_sci_handle *handle;
 423        int ret;
 424        int num_clks = 0;
 425        struct sci_clk **clks = NULL;
 426        struct sci_clk **tmp_clks;
 427        struct sci_clk *sci_clk;
 428        int max_clks = 0;
 429        int clk_id = 0;
 430        int dev_id = 0;
 431        u8 num_parents;
 432        int gap_size = 0;
 433
 434        handle = devm_ti_sci_get_handle(dev);
 435        if (IS_ERR(handle))
 436                return PTR_ERR(handle);
 437
 438        provider = devm_kzalloc(dev, sizeof(*provider), GFP_KERNEL);
 439        if (!provider)
 440                return -ENOMEM;
 441
 442        provider->sci = handle;
 443        provider->ops = &handle->ops.clk_ops;
 444        provider->dev = dev;
 445
 446        while (1) {
 447                ret = provider->ops->get_num_parents(provider->sci, dev_id,
 448                                                     clk_id, &num_parents);
 449                if (ret) {
 450                        gap_size++;
 451                        if (!clk_id) {
 452                                if (gap_size >= 5)
 453                                        break;
 454                                dev_id++;
 455                        } else {
 456                                if (gap_size >= 2) {
 457                                        dev_id++;
 458                                        clk_id = 0;
 459                                        gap_size = 0;
 460                                } else {
 461                                        clk_id++;
 462                                }
 463                        }
 464                        continue;
 465                }
 466
 467                gap_size = 0;
 468
 469                if (num_clks == max_clks) {
 470                        tmp_clks = devm_kmalloc_array(dev, max_clks + 64,
 471                                                      sizeof(sci_clk),
 472                                                      GFP_KERNEL);
 473                        memcpy(tmp_clks, clks, max_clks * sizeof(sci_clk));
 474                        if (max_clks)
 475                                devm_kfree(dev, clks);
 476                        max_clks += 64;
 477                        clks = tmp_clks;
 478                }
 479
 480                sci_clk = devm_kzalloc(dev, sizeof(*sci_clk), GFP_KERNEL);
 481                if (!sci_clk)
 482                        return -ENOMEM;
 483                sci_clk->dev_id = dev_id;
 484                sci_clk->clk_id = clk_id;
 485                sci_clk->provider = provider;
 486                sci_clk->num_parents = num_parents;
 487
 488                clks[num_clks] = sci_clk;
 489
 490                clk_id++;
 491                num_clks++;
 492        }
 493
 494        provider->clocks = devm_kmalloc_array(dev, num_clks, sizeof(sci_clk),
 495                                              GFP_KERNEL);
 496        if (!provider->clocks)
 497                return -ENOMEM;
 498
 499        memcpy(provider->clocks, clks, num_clks * sizeof(sci_clk));
 500
 501        provider->num_clocks = num_clks;
 502
 503        devm_kfree(dev, clks);
 504
 505        ret = ti_sci_init_clocks(provider);
 506        if (ret) {
 507                pr_err("ti-sci-init-clocks failed.\n");
 508                return ret;
 509        }
 510
 511        return of_clk_add_hw_provider(np, sci_clk_get, provider);
 512}
 513
 514/**
 515 * ti_sci_clk_remove - Remove TI SCI clock device
 516 * @pdev: platform device pointer for the device to be removed
 517 *
 518 * Removes the TI SCI device. Unregisters the clock provider registered
 519 * via common clock framework. Any memory allocated for the device will
 520 * be free'd silently via the devm framework. Returns 0 always.
 521 */
 522static int ti_sci_clk_remove(struct platform_device *pdev)
 523{
 524        of_clk_del_provider(pdev->dev.of_node);
 525
 526        return 0;
 527}
 528
 529static struct platform_driver ti_sci_clk_driver = {
 530        .probe = ti_sci_clk_probe,
 531        .remove = ti_sci_clk_remove,
 532        .driver = {
 533                .name = "ti-sci-clk",
 534                .of_match_table = of_match_ptr(ti_sci_clk_of_match),
 535        },
 536};
 537module_platform_driver(ti_sci_clk_driver);
 538
 539MODULE_LICENSE("GPL v2");
 540MODULE_DESCRIPTION("TI System Control Interface(SCI) Clock driver");
 541MODULE_AUTHOR("Tero Kristo");
 542MODULE_ALIAS("platform:ti-sci-clk");
 543