uboot/drivers/clk/clk-uclass.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Google, Inc
   3 * Written by Simon Glass <sjg@chromium.org>
   4 * Copyright (c) 2016, NVIDIA CORPORATION.
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <clk.h>
  11#include <clk-uclass.h>
  12#include <dm.h>
  13#include <dt-structs.h>
  14#include <errno.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18static inline struct clk_ops *clk_dev_ops(struct udevice *dev)
  19{
  20        return (struct clk_ops *)dev->driver->ops;
  21}
  22
  23#if CONFIG_IS_ENABLED(OF_CONTROL)
  24# if CONFIG_IS_ENABLED(OF_PLATDATA)
  25int clk_get_by_index_platdata(struct udevice *dev, int index,
  26                              struct phandle_2_cell *cells, struct clk *clk)
  27{
  28        int ret;
  29
  30        if (index != 0)
  31                return -ENOSYS;
  32        ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
  33        if (ret)
  34                return ret;
  35        clk->id = cells[0].id;
  36
  37        return 0;
  38}
  39# else
  40static int clk_of_xlate_default(struct clk *clk,
  41                                struct fdtdec_phandle_args *args)
  42{
  43        debug("%s(clk=%p)\n", __func__, clk);
  44
  45        if (args->args_count > 1) {
  46                debug("Invaild args_count: %d\n", args->args_count);
  47                return -EINVAL;
  48        }
  49
  50        if (args->args_count)
  51                clk->id = args->args[0];
  52        else
  53                clk->id = 0;
  54
  55        return 0;
  56}
  57
  58int clk_get_by_index(struct udevice *dev, int index, struct clk *clk)
  59{
  60        int ret;
  61        struct fdtdec_phandle_args args;
  62        struct udevice *dev_clk;
  63        struct clk_ops *ops;
  64
  65        debug("%s(dev=%p, index=%d, clk=%p)\n", __func__, dev, index, clk);
  66
  67        assert(clk);
  68        ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
  69                                             "clocks", "#clock-cells", 0, index,
  70                                             &args);
  71        if (ret) {
  72                debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
  73                      __func__, ret);
  74                return ret;
  75        }
  76
  77        ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev_clk);
  78        if (ret) {
  79                debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
  80                      __func__, ret);
  81                return ret;
  82        }
  83
  84        clk->dev = dev_clk;
  85
  86        ops = clk_dev_ops(dev_clk);
  87
  88        if (ops->of_xlate)
  89                ret = ops->of_xlate(clk, &args);
  90        else
  91                ret = clk_of_xlate_default(clk, &args);
  92        if (ret) {
  93                debug("of_xlate() failed: %d\n", ret);
  94                return ret;
  95        }
  96
  97        return clk_request(dev_clk, clk);
  98}
  99# endif /* OF_PLATDATA */
 100
 101int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
 102{
 103        int index;
 104
 105        debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
 106
 107        index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev),
 108                                      "clock-names", name);
 109        if (index < 0) {
 110                debug("fdt_stringlist_search() failed: %d\n", index);
 111                return index;
 112        }
 113
 114        return clk_get_by_index(dev, index, clk);
 115}
 116#endif /* OF_CONTROL */
 117
 118int clk_request(struct udevice *dev, struct clk *clk)
 119{
 120        struct clk_ops *ops = clk_dev_ops(dev);
 121
 122        debug("%s(dev=%p, clk=%p)\n", __func__, dev, clk);
 123
 124        clk->dev = dev;
 125
 126        if (!ops->request)
 127                return 0;
 128
 129        return ops->request(clk);
 130}
 131
 132int clk_free(struct clk *clk)
 133{
 134        struct clk_ops *ops = clk_dev_ops(clk->dev);
 135
 136        debug("%s(clk=%p)\n", __func__, clk);
 137
 138        if (!ops->free)
 139                return 0;
 140
 141        return ops->free(clk);
 142}
 143
 144ulong clk_get_rate(struct clk *clk)
 145{
 146        struct clk_ops *ops = clk_dev_ops(clk->dev);
 147
 148        debug("%s(clk=%p)\n", __func__, clk);
 149
 150        if (!ops->get_rate)
 151                return -ENOSYS;
 152
 153        return ops->get_rate(clk);
 154}
 155
 156ulong clk_set_rate(struct clk *clk, ulong rate)
 157{
 158        struct clk_ops *ops = clk_dev_ops(clk->dev);
 159
 160        debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
 161
 162        if (!ops->set_rate)
 163                return -ENOSYS;
 164
 165        return ops->set_rate(clk, rate);
 166}
 167
 168int clk_enable(struct clk *clk)
 169{
 170        struct clk_ops *ops = clk_dev_ops(clk->dev);
 171
 172        debug("%s(clk=%p)\n", __func__, clk);
 173
 174        if (!ops->enable)
 175                return -ENOSYS;
 176
 177        return ops->enable(clk);
 178}
 179
 180int clk_disable(struct clk *clk)
 181{
 182        struct clk_ops *ops = clk_dev_ops(clk->dev);
 183
 184        debug("%s(clk=%p)\n", __func__, clk);
 185
 186        if (!ops->disable)
 187                return -ENOSYS;
 188
 189        return ops->disable(clk);
 190}
 191
 192UCLASS_DRIVER(clk) = {
 193        .id             = UCLASS_CLK,
 194        .name           = "clk",
 195};
 196