Re: [PATCH v6 4/5] clk: imx: add imx composite clock
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: 2018-08-24 07:43:59
Also in:
linux-clk, lkml
On Wed, Aug 22, 2018 at 04:48:22PM +0300, Abel Vesa wrote:
quoted hunk ↗ jump to hunk
Since a lot of clocks on imx8 are formed by a mux, gate, predivider and divider, the idea here is to combine all of those into one composite clock, but we need to deal with both predivider and divider at the same time and therefore we add the imx_clk_composite_divider_ops and register the composite clock with those. Signed-off-by: Abel Vesa <redacted> Suggested-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-composite.c | 157 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/imx/clk.h | 9 +++ 3 files changed, 167 insertions(+) create mode 100644 drivers/clk/imx/clk-composite.cdiff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index b87513c..4fabb0a 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile@@ -3,6 +3,7 @@ obj-y += \ clk.o \ clk-busy.o \ + clk-composite.o \ clk-cpu.o \ clk-fixup-div.o \ clk-fixup-mux.o \diff --git a/drivers/clk/imx/clk-composite.c b/drivers/clk/imx/clk-composite.c new file mode 100644 index 0000000..a5c0080 --- /dev/null +++ b/drivers/clk/imx/clk-composite.c@@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018 NXP + */ + +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/clk-provider.h> +#include <linux/clk.h> + +#include "clk.h" + +#define PCG_PREDIV_SHIFT 16 +#define PCG_PREDIV_WIDTH 3 + +#define PCG_DIV_SHIFT 0 +#define PCG_DIV_WIDTH 6 + +#define PCG_PCS_SHIFT 24 +#define PCG_PCS_MASK 0x7 + +#define PCG_CGC_SHIFT 28 + +static unsigned long imx_clk_composite_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_divider *divider = to_clk_divider(hw); + unsigned long prediv_rate; + unsigned int prediv_value; + unsigned int div_value; + + prediv_value = clk_readl(divider->reg) >> divider->shift; + prediv_value &= clk_div_mask(divider->width); + + prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value, + divider->table, divider->flags, + divider->width); + + div_value = clk_readl(divider->reg) >> PCG_DIV_SHIFT; + div_value &= clk_div_mask(PCG_DIV_WIDTH); + + return divider_recalc_rate(hw, prediv_rate, div_value, divider->table, + divider->flags, PCG_DIV_WIDTH);
This is no table based divider, so divider->table is NULL, right? It's clearer to just write NULL here instead. Otherwise this looks good for me now. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |