u-boot/drivers/clk/clk-composite.c
Dario Binacchi 16bdc85b48 clk: set flags in the ccf registration routines
The top-level framework flags are passed as parameter to the common
clock framework (ccf) registration routines without being used.
Checks of the flags setting added by the patch have been added in the
ccf test.

Signed-off-by: Dario Binacchi <dariobin@libero.it>
2020-08-24 11:03:26 +02:00

183 lines
4.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved.
* Copyright 2019 NXP
*/
#include <common.h>
#include <asm/io.h>
#include <malloc.h>
#include <clk-uclass.h>
#include <dm/device.h>
#include <dm/devres.h>
#include <linux/clk-provider.h>
#include <clk.h>
#include <linux/err.h>
#include "clk.h"
#define UBOOT_DM_CLK_COMPOSITE "clk_composite"
static u8 clk_composite_get_parent(struct clk *clk)
{
struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
struct clk *mux = composite->mux;
if (mux)
return clk_mux_get_parent(mux);
else
return 0;
}
static int clk_composite_set_parent(struct clk *clk, struct clk *parent)
{
struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk *mux = composite->mux;
if (mux && mux_ops)
return mux_ops->set_parent(mux, parent);
else
return -ENOTSUPP;
}
static unsigned long clk_composite_recalc_rate(struct clk *clk)
{
struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk *rate = composite->rate;
if (rate && rate_ops)
return rate_ops->get_rate(rate);
else
return clk_get_parent_rate(clk);
}
static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate)
{
struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
const struct clk_ops *rate_ops = composite->rate_ops;
struct clk *clk_rate = composite->rate;
if (rate && rate_ops)
return rate_ops->set_rate(clk_rate, rate);
else
return clk_get_rate(clk);
}
static int clk_composite_enable(struct clk *clk)
{
struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk *gate = composite->gate;
if (gate && gate_ops)
return gate_ops->enable(gate);
else
return 0;
}
static int clk_composite_disable(struct clk *clk)
{
struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ?
(struct clk *)dev_get_clk_ptr(clk->dev) : clk);
const struct clk_ops *gate_ops = composite->gate_ops;
struct clk *gate = composite->gate;
if (gate && gate_ops)
return gate_ops->disable(gate);
else
return 0;
}
struct clk *clk_register_composite(struct device *dev, const char *name,
const char * const *parent_names,
int num_parents, struct clk *mux,
const struct clk_ops *mux_ops,
struct clk *rate,
const struct clk_ops *rate_ops,
struct clk *gate,
const struct clk_ops *gate_ops,
unsigned long flags)
{
struct clk *clk;
struct clk_composite *composite;
int ret;
if (!num_parents || (num_parents != 1 && !mux))
return ERR_PTR(-EINVAL);
composite = kzalloc(sizeof(*composite), GFP_KERNEL);
if (!composite)
return ERR_PTR(-ENOMEM);
if (mux && mux_ops) {
composite->mux = mux;
composite->mux_ops = mux_ops;
mux->data = (ulong)composite;
}
if (rate && rate_ops) {
if (!rate_ops->get_rate) {
clk = ERR_PTR(-EINVAL);
goto err;
}
composite->rate = rate;
composite->rate_ops = rate_ops;
rate->data = (ulong)composite;
}
if (gate && gate_ops) {
if (!gate_ops->enable || !gate_ops->disable) {
clk = ERR_PTR(-EINVAL);
goto err;
}
composite->gate = gate;
composite->gate_ops = gate_ops;
gate->data = (ulong)composite;
}
clk = &composite->clk;
clk->flags = flags;
ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
parent_names[clk_composite_get_parent(clk)]);
if (ret) {
clk = ERR_PTR(ret);
goto err;
}
if (composite->mux)
composite->mux->dev = clk->dev;
if (composite->rate)
composite->rate->dev = clk->dev;
if (composite->gate)
composite->gate->dev = clk->dev;
return clk;
err:
kfree(composite);
return clk;
}
static const struct clk_ops clk_composite_ops = {
.set_parent = clk_composite_set_parent,
.get_rate = clk_composite_recalc_rate,
.set_rate = clk_composite_set_rate,
.enable = clk_composite_enable,
.disable = clk_composite_disable,
};
U_BOOT_DRIVER(clk_composite) = {
.name = UBOOT_DM_CLK_COMPOSITE,
.id = UCLASS_CLK,
.ops = &clk_composite_ops,
.flags = DM_FLAG_PRE_RELOC,
};