mirror of
https://xff.cz/git/u-boot/
synced 2025-09-29 22:41:17 +02:00
clk: add composite clk support
Import clk composite clk support from Linux Kernel 5.1-rc5 Signed-off-by: Peng Fan <peng.fan@nxp.com>
This commit is contained in:
committed by
Lukasz Majewski
parent
d669d1ae03
commit
0009763588
@@ -53,6 +53,13 @@ config SPL_CLK_CCF
|
|||||||
Enable this option if you want to (re-)use the Linux kernel's Common
|
Enable this option if you want to (re-)use the Linux kernel's Common
|
||||||
Clock Framework [CCF] code in U-Boot's SPL.
|
Clock Framework [CCF] code in U-Boot's SPL.
|
||||||
|
|
||||||
|
config SPL_CLK_COMPOSITE_CCF
|
||||||
|
bool "SPL Common Clock Framework [CCF] composite clk support "
|
||||||
|
depends on SPL_CLK_CCF
|
||||||
|
help
|
||||||
|
Enable this option if you want to (re-)use the Linux kernel's Common
|
||||||
|
Clock Framework [CCF] composite code in U-Boot's SPL.
|
||||||
|
|
||||||
config CLK_CCF
|
config CLK_CCF
|
||||||
bool "Common Clock Framework [CCF] support "
|
bool "Common Clock Framework [CCF] support "
|
||||||
depends on CLK_IMX6Q || SANDBOX_CLK_CCF
|
depends on CLK_IMX6Q || SANDBOX_CLK_CCF
|
||||||
@@ -60,6 +67,13 @@ config CLK_CCF
|
|||||||
Enable this option if you want to (re-)use the Linux kernel's Common
|
Enable this option if you want to (re-)use the Linux kernel's Common
|
||||||
Clock Framework [CCF] code in U-Boot's clock driver.
|
Clock Framework [CCF] code in U-Boot's clock driver.
|
||||||
|
|
||||||
|
config CLK_COMPOSITE_CCF
|
||||||
|
bool "Common Clock Framework [CCF] composite clk support "
|
||||||
|
depends on CLK_CCF
|
||||||
|
help
|
||||||
|
Enable this option if you want to (re-)use the Linux kernel's Common
|
||||||
|
Clock Framework [CCF] composite code in U-Boot's clock driver.
|
||||||
|
|
||||||
config CLK_STM32F
|
config CLK_STM32F
|
||||||
bool "Enable clock driver support for STM32F family"
|
bool "Enable clock driver support for STM32F family"
|
||||||
depends on CLK && (STM32F7 || STM32F4)
|
depends on CLK && (STM32F7 || STM32F4)
|
||||||
|
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_rate.o
|
|||||||
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o
|
obj-$(CONFIG_$(SPL_TPL_)CLK) += clk_fixed_factor.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o
|
obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o
|
||||||
obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o
|
obj-$(CONFIG_$(SPL_TPL_)CLK_CCF) += clk-fixed-factor.o
|
||||||
|
obj-$(CONFIG_$(SPL_TPL_)CLK_COMPOSITE_CCF) += clk-composite.o
|
||||||
|
|
||||||
obj-y += analogbits/
|
obj-y += analogbits/
|
||||||
obj-y += imx/
|
obj-y += imx/
|
||||||
|
160
drivers/clk/clk-composite.c
Normal file
160
drivers/clk/clk-composite.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
// 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 <linux/clk-provider.h>
|
||||||
|
#include <clk.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;
|
||||||
|
|
||||||
|
return clk_mux_get_parent(mux);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return mux_ops->set_parent(mux, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return rate_ops->get_rate(rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return rate_ops->set_rate(clk_rate, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return gate_ops->enable(gate);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
gate_ops->disable(gate);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct clk_ops clk_composite_ops = {
|
||||||
|
/* This will be set according to clk_register_composite */
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
struct clk_ops *composite_ops = &clk_composite_ops;
|
||||||
|
|
||||||
|
composite = kzalloc(sizeof(*composite), GFP_KERNEL);
|
||||||
|
if (!composite)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
if (mux && mux_ops) {
|
||||||
|
composite->mux = mux;
|
||||||
|
composite->mux_ops = mux_ops;
|
||||||
|
if (mux_ops->set_parent)
|
||||||
|
composite_ops->set_parent = clk_composite_set_parent;
|
||||||
|
mux->data = (ulong)composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rate && rate_ops) {
|
||||||
|
if (!rate_ops->get_rate) {
|
||||||
|
clk = ERR_PTR(-EINVAL);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
composite_ops->get_rate = clk_composite_recalc_rate;
|
||||||
|
|
||||||
|
/* .set_rate requires either .round_rate or .determine_rate */
|
||||||
|
if (rate_ops->set_rate)
|
||||||
|
composite_ops->set_rate = clk_composite_set_rate;
|
||||||
|
|
||||||
|
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;
|
||||||
|
composite_ops->enable = clk_composite_enable;
|
||||||
|
composite_ops->disable = clk_composite_disable;
|
||||||
|
gate->data = (ulong)composite;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk = &composite->clk;
|
||||||
|
ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name,
|
||||||
|
parent_names[clk_composite_get_parent(clk)]);
|
||||||
|
if (ret) {
|
||||||
|
clk = ERR_PTR(ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
|
||||||
|
err:
|
||||||
|
kfree(composite);
|
||||||
|
return clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(clk_composite) = {
|
||||||
|
.name = UBOOT_DM_CLK_COMPOSITE,
|
||||||
|
.id = UCLASS_CLK,
|
||||||
|
.ops = &clk_composite_ops,
|
||||||
|
.flags = DM_FLAG_PRE_RELOC,
|
||||||
|
};
|
@@ -137,6 +137,28 @@ struct clk_fixed_rate {
|
|||||||
|
|
||||||
#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev))
|
#define to_clk_fixed_rate(dev) ((struct clk_fixed_rate *)dev_get_platdata(dev))
|
||||||
|
|
||||||
|
struct clk_composite {
|
||||||
|
struct clk clk;
|
||||||
|
struct clk_ops ops;
|
||||||
|
|
||||||
|
struct clk *mux;
|
||||||
|
struct clk *rate;
|
||||||
|
struct clk *gate;
|
||||||
|
|
||||||
|
const struct clk_ops *mux_ops;
|
||||||
|
const struct clk_ops *rate_ops;
|
||||||
|
const struct clk_ops *gate_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define to_clk_composite(_clk) container_of(_clk, struct clk_composite, clk)
|
||||||
|
|
||||||
|
struct clk *clk_register_composite(struct device *dev, const char *name,
|
||||||
|
const char * const *parent_names, int num_parents,
|
||||||
|
struct clk *mux_clk, const struct clk_ops *mux_ops,
|
||||||
|
struct clk *rate_clk, const struct clk_ops *rate_ops,
|
||||||
|
struct clk *gate_clk, const struct clk_ops *gate_ops,
|
||||||
|
unsigned long flags);
|
||||||
|
|
||||||
int clk_register(struct clk *clk, const char *drv_name, const char *name,
|
int clk_register(struct clk *clk, const char *drv_name, const char *name,
|
||||||
const char *parent_name);
|
const char *parent_name);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user