mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-12-19 00:11:30 +01:00
In clk_set_default_get_by_id ret is passed to ERR_PTR but nothing is done with the value that this calculates which is obviously not the intention of the code. This is confirmed by the code around where this function is called. Instead return the value from ERR_PTR. Then fixup the sandbox code so that the test dm_test_clk does not fail as it relied on the broken behaviour. Finally disable part of the test that does not work correctly with CLK_AUTO_ID This issue found by Smatch. Signed-off-by: Andrew Goodbody <andrew.goodbody@linaro.org>
217 lines
4.2 KiB
C
217 lines
4.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* (C) Copyright 2015 Google, Inc
|
|
*/
|
|
|
|
#include <clk-uclass.h>
|
|
#include <dm.h>
|
|
#include <errno.h>
|
|
#include <malloc.h>
|
|
#include <asm/clk.h>
|
|
#include <dm/device-internal.h>
|
|
#include <linux/clk-provider.h>
|
|
|
|
static int sandbox_clk_of_to_plat(struct udevice *dev)
|
|
{
|
|
struct clk *clk;
|
|
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
clk = &priv->clk;
|
|
|
|
/* FIXME: This is not allowed */
|
|
dev_set_uclass_priv(dev, clk);
|
|
|
|
clk->dev = dev;
|
|
return 0;
|
|
}
|
|
|
|
static ulong sandbox_clk_get_rate(struct clk *clk)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
|
ulong id = clk_get_id(clk);
|
|
|
|
if (!priv->probed)
|
|
return -ENODEV;
|
|
|
|
if (id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
return priv->rate[id];
|
|
}
|
|
|
|
static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
|
ulong id = clk_get_id(clk);
|
|
|
|
if (!priv->probed)
|
|
return -ENODEV;
|
|
|
|
if (id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
if (!rate)
|
|
return -EINVAL;
|
|
|
|
return rate;
|
|
}
|
|
|
|
static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
|
ulong old_rate;
|
|
ulong id = clk_get_id(clk);
|
|
|
|
if (!priv->probed)
|
|
return -ENODEV;
|
|
|
|
if (id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
if (!rate)
|
|
return -EINVAL;
|
|
|
|
old_rate = priv->rate[id];
|
|
priv->rate[id] = rate;
|
|
|
|
return old_rate;
|
|
}
|
|
|
|
static int sandbox_clk_enable(struct clk *clk)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
|
ulong id = clk_get_id(clk);
|
|
|
|
if (!priv->probed)
|
|
return -ENODEV;
|
|
|
|
if (id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
priv->enabled[id] = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sandbox_clk_disable(struct clk *clk)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
|
ulong id = clk_get_id(clk);
|
|
|
|
if (!priv->probed)
|
|
return -ENODEV;
|
|
|
|
if (id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
priv->enabled[id] = false;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int sandbox_clk_request(struct clk *clk)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
|
|
ulong id = clk_get_id(clk);
|
|
|
|
if (id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
priv->clk.id = id;
|
|
priv->requested[id] = true;
|
|
return 0;
|
|
}
|
|
|
|
static struct clk_ops sandbox_clk_ops = {
|
|
.round_rate = sandbox_clk_round_rate,
|
|
.get_rate = sandbox_clk_get_rate,
|
|
.set_rate = sandbox_clk_set_rate,
|
|
.enable = sandbox_clk_enable,
|
|
.disable = sandbox_clk_disable,
|
|
.request = sandbox_clk_request,
|
|
};
|
|
|
|
static int sandbox_clk_probe(struct udevice *dev)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
priv->probed = true;
|
|
return 0;
|
|
}
|
|
|
|
static const struct udevice_id sandbox_clk_ids[] = {
|
|
{ .compatible = "sandbox,clk" },
|
|
{ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(sandbox_clk) = {
|
|
.name = "sandbox_clk",
|
|
.id = UCLASS_CLK,
|
|
.of_match = sandbox_clk_ids,
|
|
.of_to_plat = sandbox_clk_of_to_plat,
|
|
.ops = &sandbox_clk_ops,
|
|
.probe = sandbox_clk_probe,
|
|
.priv_auto = sizeof(struct sandbox_clk_priv),
|
|
};
|
|
|
|
ulong sandbox_clk_query_rate(struct udevice *dev, int id)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
return priv->rate[id];
|
|
}
|
|
|
|
int sandbox_clk_query_enable(struct udevice *dev, int id)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
|
|
return priv->enabled[id];
|
|
}
|
|
|
|
int sandbox_clk_query_requested(struct udevice *dev, int id)
|
|
{
|
|
struct sandbox_clk_priv *priv = dev_get_priv(dev);
|
|
|
|
if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
|
|
return -EINVAL;
|
|
return priv->requested[id];
|
|
}
|
|
|
|
int clk_fixed_rate_of_to_plat(struct udevice *dev)
|
|
{
|
|
struct clk_fixed_rate *cplat;
|
|
|
|
#if CONFIG_IS_ENABLED(OF_PLATDATA)
|
|
struct sandbox_clk_fixed_rate_plat *plat = dev_get_plat(dev);
|
|
|
|
cplat = &plat->fixed;
|
|
cplat->fixed_rate = plat->dtplat.clock_frequency;
|
|
#else
|
|
cplat = to_clk_fixed_rate(dev);
|
|
#endif
|
|
clk_fixed_rate_ofdata_to_plat_(dev, cplat);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct udevice_id sandbox_clk_fixed_rate_match[] = {
|
|
{ .compatible = "sandbox,fixed-clock" },
|
|
{ /* sentinel */ }
|
|
};
|
|
|
|
U_BOOT_DRIVER(sandbox_fixed_clock) = {
|
|
.name = "sandbox_fixed_clock",
|
|
.id = UCLASS_CLK,
|
|
.of_match = sandbox_clk_fixed_rate_match,
|
|
.of_to_plat = clk_fixed_rate_of_to_plat,
|
|
.plat_auto = sizeof(struct sandbox_clk_fixed_rate_plat),
|
|
.ops = &clk_fixed_rate_ops,
|
|
.flags = DM_FLAG_PRE_RELOC,
|
|
};
|