From 1d7993d1d0efb7727de29ebbe164059b7bf71983 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 24 Jun 2019 15:50:45 +0200 Subject: clk: Port Linux common clock framework [CCF] for imx6q to U-boot (tag: v5.1.12) This patch brings the files from Linux kernel (linux-stable/linux-5.1.y SHA1: 5752b50477da)to provide clocks support as it is used on the Linux kernel with Common Clock Framework [CCF] setup. The directory structure has been preserved. The ported code only supports reading information from PLL, MUX, Divider, etc and enabling/disabling the clocks USDHCx/ECSPIx depending on used bus. Moreover, it is agnostic to the alias numbering as the information about the clock is read from the device tree. One needs to pay attention to the comments indicating necessary for U-Boot's driver model changes. If needed, the code can be extended to support the "set" part of the clock management. Signed-off-by: Lukasz Majewski --- drivers/clk/imx/clk-gate2.c | 103 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 drivers/clk/imx/clk-gate2.c (limited to 'drivers/clk/imx/clk-gate2.c') diff --git a/drivers/clk/imx/clk-gate2.c b/drivers/clk/imx/clk-gate2.c new file mode 100644 index 0000000000..571be32088 --- /dev/null +++ b/drivers/clk/imx/clk-gate2.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 DENX Software Engineering + * Lukasz Majewski, DENX Software Engineering, lukma@denx.de + * + * Copyright (C) 2010-2011 Canonical Ltd + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Gated clock implementation + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "clk.h" + +#define UBOOT_DM_CLK_IMX_GATE2 "imx_clk_gate2" + +struct clk_gate2 { + struct clk clk; + void __iomem *reg; + u8 bit_idx; + u8 cgr_val; + u8 flags; +}; + +#define to_clk_gate2(_clk) container_of(_clk, struct clk_gate2, clk) + +static int clk_gate2_enable(struct clk *clk) +{ + struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev)); + u32 reg; + + reg = readl(gate->reg); + reg &= ~(3 << gate->bit_idx); + reg |= gate->cgr_val << gate->bit_idx; + writel(reg, gate->reg); + + return 0; +} + +static int clk_gate2_disable(struct clk *clk) +{ + struct clk_gate2 *gate = to_clk_gate2(dev_get_clk_ptr(clk->dev)); + u32 reg; + + reg = readl(gate->reg); + reg &= ~(3 << gate->bit_idx); + writel(reg, gate->reg); + + return 0; +} + +static const struct clk_ops clk_gate2_ops = { + .enable = clk_gate2_enable, + .disable = clk_gate2_disable, + .get_rate = clk_generic_get_rate, +}; + +struct clk *clk_register_gate2(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, u8 cgr_val, + u8 clk_gate2_flags) +{ + struct clk_gate2 *gate; + struct clk *clk; + int ret; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->cgr_val = cgr_val; + gate->flags = clk_gate2_flags; + + clk = &gate->clk; + + ret = clk_register(clk, UBOOT_DM_CLK_IMX_GATE2, name, parent_name); + if (ret) { + kfree(gate); + return ERR_PTR(ret); + } + + return clk; +} + +U_BOOT_DRIVER(clk_gate2) = { + .name = UBOOT_DM_CLK_IMX_GATE2, + .id = UCLASS_CLK, + .ops = &clk_gate2_ops, + .flags = DM_FLAG_PRE_RELOC, +}; -- cgit