uboot/drivers/clk/clk_sandbox.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) Copyright 2015 Google, Inc
   4 */
   5
   6#include <common.h>
   7#include <clk-uclass.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <malloc.h>
  11#include <asm/clk.h>
  12#include <linux/clk-provider.h>
  13
  14static ulong sandbox_clk_get_rate(struct clk *clk)
  15{
  16        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
  17
  18        if (!priv->probed)
  19                return -ENODEV;
  20
  21        if (clk->id >= SANDBOX_CLK_ID_COUNT)
  22                return -EINVAL;
  23
  24        return priv->rate[clk->id];
  25}
  26
  27static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
  28{
  29        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
  30
  31        if (!priv->probed)
  32                return -ENODEV;
  33
  34        if (clk->id >= SANDBOX_CLK_ID_COUNT)
  35                return -EINVAL;
  36
  37        if (!rate)
  38                return -EINVAL;
  39
  40        return rate;
  41}
  42
  43static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
  44{
  45        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
  46        ulong old_rate;
  47
  48        if (!priv->probed)
  49                return -ENODEV;
  50
  51        if (clk->id >= SANDBOX_CLK_ID_COUNT)
  52                return -EINVAL;
  53
  54        if (!rate)
  55                return -EINVAL;
  56
  57        old_rate = priv->rate[clk->id];
  58        priv->rate[clk->id] = rate;
  59
  60        return old_rate;
  61}
  62
  63static int sandbox_clk_enable(struct clk *clk)
  64{
  65        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
  66
  67        if (!priv->probed)
  68                return -ENODEV;
  69
  70        if (clk->id >= SANDBOX_CLK_ID_COUNT)
  71                return -EINVAL;
  72
  73        priv->enabled[clk->id] = true;
  74
  75        return 0;
  76}
  77
  78static int sandbox_clk_disable(struct clk *clk)
  79{
  80        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
  81
  82        if (!priv->probed)
  83                return -ENODEV;
  84
  85        if (clk->id >= SANDBOX_CLK_ID_COUNT)
  86                return -EINVAL;
  87
  88        priv->enabled[clk->id] = false;
  89
  90        return 0;
  91}
  92
  93static int sandbox_clk_request(struct clk *clk)
  94{
  95        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
  96
  97        if (clk->id >= SANDBOX_CLK_ID_COUNT)
  98                return -EINVAL;
  99
 100        priv->requested[clk->id] = true;
 101        return 0;
 102}
 103
 104static void sandbox_clk_free(struct clk *clk)
 105{
 106        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
 107
 108        if (clk->id >= SANDBOX_CLK_ID_COUNT)
 109                return;
 110
 111        priv->requested[clk->id] = false;
 112        return;
 113}
 114
 115static struct clk_ops sandbox_clk_ops = {
 116        .round_rate     = sandbox_clk_round_rate,
 117        .get_rate       = sandbox_clk_get_rate,
 118        .set_rate       = sandbox_clk_set_rate,
 119        .enable         = sandbox_clk_enable,
 120        .disable        = sandbox_clk_disable,
 121        .request        = sandbox_clk_request,
 122        .rfree          = sandbox_clk_free,
 123};
 124
 125static int sandbox_clk_probe(struct udevice *dev)
 126{
 127        struct sandbox_clk_priv *priv = dev_get_priv(dev);
 128
 129        priv->probed = true;
 130        return 0;
 131}
 132
 133static const struct udevice_id sandbox_clk_ids[] = {
 134        { .compatible = "sandbox,clk" },
 135        { }
 136};
 137
 138U_BOOT_DRIVER(sandbox_clk) = {
 139        .name           = "sandbox_clk",
 140        .id             = UCLASS_CLK,
 141        .of_match       = sandbox_clk_ids,
 142        .ops            = &sandbox_clk_ops,
 143        .probe          = sandbox_clk_probe,
 144        .priv_auto      = sizeof(struct sandbox_clk_priv),
 145};
 146
 147ulong sandbox_clk_query_rate(struct udevice *dev, int id)
 148{
 149        struct sandbox_clk_priv *priv = dev_get_priv(dev);
 150
 151        if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
 152                return -EINVAL;
 153
 154        return priv->rate[id];
 155}
 156
 157int sandbox_clk_query_enable(struct udevice *dev, int id)
 158{
 159        struct sandbox_clk_priv *priv = dev_get_priv(dev);
 160
 161        if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
 162                return -EINVAL;
 163
 164        return priv->enabled[id];
 165}
 166
 167int sandbox_clk_query_requested(struct udevice *dev, int id)
 168{
 169        struct sandbox_clk_priv *priv = dev_get_priv(dev);
 170
 171        if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
 172                return -EINVAL;
 173        return priv->requested[id];
 174}
 175
 176int clk_fixed_rate_of_to_plat(struct udevice *dev)
 177{
 178        struct clk_fixed_rate *cplat;
 179
 180#if CONFIG_IS_ENABLED(OF_PLATDATA)
 181        struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
 182
 183        cplat = &plat->fixed;
 184        cplat->fixed_rate = plat->dtplat.clock_frequency;
 185#else
 186        cplat = to_clk_fixed_rate(dev);
 187#endif
 188        clk_fixed_rate_ofdata_to_plat_(dev, cplat);
 189
 190        return 0;
 191}
 192
 193static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
 194        { .compatible = "sandbox,fixed-clock" },
 195        { /* sentinel */ }
 196};
 197
 198U_BOOT_DRIVER(sandbox_fixed_clock) = {
 199        .name = "sandbox_fixed_clock",
 200        .id = UCLASS_CLK,
 201        .of_match = sandbox_clk_fixed_rate_match,
 202        .of_to_plat = clk_fixed_rate_of_to_plat,
 203        .plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
 204        .ops = &clk_fixed_rate_ops,
 205        .flags = DM_FLAG_PRE_RELOC,
 206};
 207