xref: /openbmc/linux/drivers/clk/ti/clkctrl.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
15a729246SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
288a17252STero Kristo /*
388a17252STero Kristo  * OMAP clkctrl clock support
488a17252STero Kristo  *
588a17252STero Kristo  * Copyright (C) 2017 Texas Instruments, Inc.
688a17252STero Kristo  *
788a17252STero Kristo  * Tero Kristo <t-kristo@ti.com>
888a17252STero Kristo  */
988a17252STero Kristo 
1088a17252STero Kristo #include <linux/clk-provider.h>
1188a17252STero Kristo #include <linux/slab.h>
1288a17252STero Kristo #include <linux/of.h>
1388a17252STero Kristo #include <linux/of_address.h>
1488a17252STero Kristo #include <linux/clk/ti.h>
1588a17252STero Kristo #include <linux/delay.h>
16*bb362d0eSAndy Shevchenko #include <linux/string_helpers.h>
173d8598fbSTero Kristo #include <linux/timekeeping.h>
1888a17252STero Kristo #include "clock.h"
1988a17252STero Kristo 
2022a6564fSTero Kristo #define NO_IDLEST			0
2188a17252STero Kristo 
2288a17252STero Kristo #define OMAP4_MODULEMODE_MASK		0x3
2388a17252STero Kristo 
2488a17252STero Kristo #define MODULEMODE_HWCTRL		0x1
2588a17252STero Kristo #define MODULEMODE_SWCTRL		0x2
2688a17252STero Kristo 
2788a17252STero Kristo #define OMAP4_IDLEST_MASK		(0x3 << 16)
2888a17252STero Kristo #define OMAP4_IDLEST_SHIFT		16
2988a17252STero Kristo 
302209b72dSTero Kristo #define OMAP4_STBYST_MASK		BIT(18)
312209b72dSTero Kristo #define OMAP4_STBYST_SHIFT		18
322209b72dSTero Kristo 
3388a17252STero Kristo #define CLKCTRL_IDLEST_FUNCTIONAL	0x0
3488a17252STero Kristo #define CLKCTRL_IDLEST_INTERFACE_IDLE	0x2
3588a17252STero Kristo #define CLKCTRL_IDLEST_DISABLED		0x3
3688a17252STero Kristo 
3788a17252STero Kristo /* These timeouts are in us */
3888a17252STero Kristo #define OMAP4_MAX_MODULE_READY_TIME	2000
3988a17252STero Kristo #define OMAP4_MAX_MODULE_DISABLE_TIME	5000
4088a17252STero Kristo 
4188a17252STero Kristo static bool _early_timeout = true;
4288a17252STero Kristo 
4388a17252STero Kristo struct omap_clkctrl_provider {
4488a17252STero Kristo 	void __iomem *base;
4588a17252STero Kristo 	struct list_head clocks;
46ddfb183eSTero Kristo 	char *clkdm_name;
4788a17252STero Kristo };
4888a17252STero Kristo 
4988a17252STero Kristo struct omap_clkctrl_clk {
5088a17252STero Kristo 	struct clk_hw *clk;
5188a17252STero Kristo 	u16 reg_offset;
5288a17252STero Kristo 	int bit_offset;
5388a17252STero Kristo 	struct list_head node;
5488a17252STero Kristo };
5588a17252STero Kristo 
5688a17252STero Kristo union omap4_timeout {
5788a17252STero Kristo 	u32 cycles;
5888a17252STero Kristo 	ktime_t start;
5988a17252STero Kristo };
6088a17252STero Kristo 
6188a17252STero Kristo static const struct omap_clkctrl_data default_clkctrl_data[] __initconst = {
6288a17252STero Kristo 	{ 0 },
6388a17252STero Kristo };
6488a17252STero Kristo 
_omap4_idlest(u32 val)6588a17252STero Kristo static u32 _omap4_idlest(u32 val)
6688a17252STero Kristo {
6788a17252STero Kristo 	val &= OMAP4_IDLEST_MASK;
6888a17252STero Kristo 	val >>= OMAP4_IDLEST_SHIFT;
6988a17252STero Kristo 
7088a17252STero Kristo 	return val;
7188a17252STero Kristo }
7288a17252STero Kristo 
_omap4_is_idle(u32 val)7388a17252STero Kristo static bool _omap4_is_idle(u32 val)
7488a17252STero Kristo {
7588a17252STero Kristo 	val = _omap4_idlest(val);
7688a17252STero Kristo 
7788a17252STero Kristo 	return val == CLKCTRL_IDLEST_DISABLED;
7888a17252STero Kristo }
7988a17252STero Kristo 
_omap4_is_ready(u32 val)8088a17252STero Kristo static bool _omap4_is_ready(u32 val)
8188a17252STero Kristo {
8288a17252STero Kristo 	val = _omap4_idlest(val);
8388a17252STero Kristo 
8488a17252STero Kristo 	return val == CLKCTRL_IDLEST_FUNCTIONAL ||
8588a17252STero Kristo 	       val == CLKCTRL_IDLEST_INTERFACE_IDLE;
8688a17252STero Kristo }
8788a17252STero Kristo 
_omap4_is_timeout(union omap4_timeout * time,u32 timeout)8888a17252STero Kristo static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
8988a17252STero Kristo {
903d8598fbSTero Kristo 	/*
913d8598fbSTero Kristo 	 * There are two special cases where ktime_to_ns() can't be
923d8598fbSTero Kristo 	 * used to track the timeouts. First one is during early boot
933d8598fbSTero Kristo 	 * when the timers haven't been initialized yet. The second
943d8598fbSTero Kristo 	 * one is during suspend-resume cycle while timekeeping is
953d8598fbSTero Kristo 	 * being suspended / resumed. Clocksource for the system
963d8598fbSTero Kristo 	 * can be from a timer that requires pm_runtime access, which
973d8598fbSTero Kristo 	 * will eventually bring us here with timekeeping_suspended,
983d8598fbSTero Kristo 	 * during both suspend entry and resume paths. This happens
9981a41901STony Lindgren 	 * at least on am43xx platform. Account for flakeyness
10081a41901STony Lindgren 	 * with udelay() by multiplying the timeout value by 2.
1013d8598fbSTero Kristo 	 */
1023d8598fbSTero Kristo 	if (unlikely(_early_timeout || timekeeping_suspended)) {
10388a17252STero Kristo 		if (time->cycles++ < timeout) {
10481a41901STony Lindgren 			udelay(1 * 2);
10588a17252STero Kristo 			return false;
10688a17252STero Kristo 		}
10788a17252STero Kristo 	} else {
10888a17252STero Kristo 		if (!ktime_to_ns(time->start)) {
10988a17252STero Kristo 			time->start = ktime_get();
11088a17252STero Kristo 			return false;
11188a17252STero Kristo 		}
11288a17252STero Kristo 
11388a17252STero Kristo 		if (ktime_us_delta(ktime_get(), time->start) < timeout) {
11488a17252STero Kristo 			cpu_relax();
11588a17252STero Kristo 			return false;
11688a17252STero Kristo 		}
11788a17252STero Kristo 	}
11888a17252STero Kristo 
11988a17252STero Kristo 	return true;
12088a17252STero Kristo }
12188a17252STero Kristo 
_omap4_disable_early_timeout(void)12288a17252STero Kristo static int __init _omap4_disable_early_timeout(void)
12388a17252STero Kristo {
12488a17252STero Kristo 	_early_timeout = false;
12588a17252STero Kristo 
12688a17252STero Kristo 	return 0;
12788a17252STero Kristo }
12888a17252STero Kristo arch_initcall(_omap4_disable_early_timeout);
12988a17252STero Kristo 
_omap4_clkctrl_clk_enable(struct clk_hw * hw)13088a17252STero Kristo static int _omap4_clkctrl_clk_enable(struct clk_hw *hw)
13188a17252STero Kristo {
13288a17252STero Kristo 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
13388a17252STero Kristo 	u32 val;
13488a17252STero Kristo 	int ret;
13588a17252STero Kristo 	union omap4_timeout timeout = { 0 };
13688a17252STero Kristo 
13788a17252STero Kristo 	if (clk->clkdm) {
13888a17252STero Kristo 		ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
13988a17252STero Kristo 		if (ret) {
14088a17252STero Kristo 			WARN(1,
14188a17252STero Kristo 			     "%s: could not enable %s's clockdomain %s: %d\n",
14288a17252STero Kristo 			     __func__, clk_hw_get_name(hw),
14388a17252STero Kristo 			     clk->clkdm_name, ret);
14488a17252STero Kristo 			return ret;
14588a17252STero Kristo 		}
14688a17252STero Kristo 	}
14788a17252STero Kristo 
1481cc54078STony Lindgren 	if (!clk->enable_bit)
1491cc54078STony Lindgren 		return 0;
1501cc54078STony Lindgren 
15188a17252STero Kristo 	val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
15288a17252STero Kristo 
15388a17252STero Kristo 	val &= ~OMAP4_MODULEMODE_MASK;
15488a17252STero Kristo 	val |= clk->enable_bit;
15588a17252STero Kristo 
15688a17252STero Kristo 	ti_clk_ll_ops->clk_writel(val, &clk->enable_reg);
15788a17252STero Kristo 
15822a6564fSTero Kristo 	if (test_bit(NO_IDLEST, &clk->flags))
15988a17252STero Kristo 		return 0;
16088a17252STero Kristo 
16188a17252STero Kristo 	/* Wait until module is enabled */
16288a17252STero Kristo 	while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
16388a17252STero Kristo 		if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
16488a17252STero Kristo 			pr_err("%s: failed to enable\n", clk_hw_get_name(hw));
16588a17252STero Kristo 			return -EBUSY;
16688a17252STero Kristo 		}
16788a17252STero Kristo 	}
16888a17252STero Kristo 
16988a17252STero Kristo 	return 0;
17088a17252STero Kristo }
17188a17252STero Kristo 
_omap4_clkctrl_clk_disable(struct clk_hw * hw)17288a17252STero Kristo static void _omap4_clkctrl_clk_disable(struct clk_hw *hw)
17388a17252STero Kristo {
17488a17252STero Kristo 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
17588a17252STero Kristo 	u32 val;
17688a17252STero Kristo 	union omap4_timeout timeout = { 0 };
17788a17252STero Kristo 
17888a17252STero Kristo 	if (!clk->enable_bit)
1791cc54078STony Lindgren 		goto exit;
18088a17252STero Kristo 
18188a17252STero Kristo 	val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
18288a17252STero Kristo 
18388a17252STero Kristo 	val &= ~OMAP4_MODULEMODE_MASK;
18488a17252STero Kristo 
18588a17252STero Kristo 	ti_clk_ll_ops->clk_writel(val, &clk->enable_reg);
18688a17252STero Kristo 
18722a6564fSTero Kristo 	if (test_bit(NO_IDLEST, &clk->flags))
18888a17252STero Kristo 		goto exit;
18988a17252STero Kristo 
19088a17252STero Kristo 	/* Wait until module is disabled */
19188a17252STero Kristo 	while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
19288a17252STero Kristo 		if (_omap4_is_timeout(&timeout,
19388a17252STero Kristo 				      OMAP4_MAX_MODULE_DISABLE_TIME)) {
19488a17252STero Kristo 			pr_err("%s: failed to disable\n", clk_hw_get_name(hw));
19588a17252STero Kristo 			break;
19688a17252STero Kristo 		}
19788a17252STero Kristo 	}
19888a17252STero Kristo 
19988a17252STero Kristo exit:
20088a17252STero Kristo 	if (clk->clkdm)
20188a17252STero Kristo 		ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
20288a17252STero Kristo }
20388a17252STero Kristo 
_omap4_clkctrl_clk_is_enabled(struct clk_hw * hw)20488a17252STero Kristo static int _omap4_clkctrl_clk_is_enabled(struct clk_hw *hw)
20588a17252STero Kristo {
20688a17252STero Kristo 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
20788a17252STero Kristo 	u32 val;
20888a17252STero Kristo 
20988a17252STero Kristo 	val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
21088a17252STero Kristo 
21188a17252STero Kristo 	if (val & clk->enable_bit)
21288a17252STero Kristo 		return 1;
21388a17252STero Kristo 
21488a17252STero Kristo 	return 0;
21588a17252STero Kristo }
21688a17252STero Kristo 
21788a17252STero Kristo static const struct clk_ops omap4_clkctrl_clk_ops = {
21888a17252STero Kristo 	.enable		= _omap4_clkctrl_clk_enable,
21988a17252STero Kristo 	.disable	= _omap4_clkctrl_clk_disable,
22088a17252STero Kristo 	.is_enabled	= _omap4_clkctrl_clk_is_enabled,
221ddfb183eSTero Kristo 	.init		= omap2_init_clk_clkdm,
22288a17252STero Kristo };
22388a17252STero Kristo 
_ti_omap4_clkctrl_xlate(struct of_phandle_args * clkspec,void * data)22488a17252STero Kristo static struct clk_hw *_ti_omap4_clkctrl_xlate(struct of_phandle_args *clkspec,
22588a17252STero Kristo 					      void *data)
22688a17252STero Kristo {
22788a17252STero Kristo 	struct omap_clkctrl_provider *provider = data;
228560a3164SJakob Koschel 	struct omap_clkctrl_clk *entry = NULL, *iter;
22988a17252STero Kristo 
23088a17252STero Kristo 	if (clkspec->args_count != 2)
23188a17252STero Kristo 		return ERR_PTR(-EINVAL);
23288a17252STero Kristo 
23388a17252STero Kristo 	pr_debug("%s: looking for %x:%x\n", __func__,
23488a17252STero Kristo 		 clkspec->args[0], clkspec->args[1]);
23588a17252STero Kristo 
236560a3164SJakob Koschel 	list_for_each_entry(iter, &provider->clocks, node) {
237560a3164SJakob Koschel 		if (iter->reg_offset == clkspec->args[0] &&
238560a3164SJakob Koschel 		    iter->bit_offset == clkspec->args[1]) {
239560a3164SJakob Koschel 			entry = iter;
24088a17252STero Kristo 			break;
24188a17252STero Kristo 		}
24241b3588dSTony Lindgren 	}
24388a17252STero Kristo 
244560a3164SJakob Koschel 	if (!entry)
24588a17252STero Kristo 		return ERR_PTR(-EINVAL);
24688a17252STero Kristo 
24788a17252STero Kristo 	return entry->clk;
24888a17252STero Kristo }
24988a17252STero Kristo 
25085204959STero Kristo /* Get clkctrl clock base name based on clkctrl_name or dts node */
clkctrl_get_clock_name(struct device_node * np,const char * clkctrl_name,int offset,int index,bool legacy_naming)25185204959STero Kristo static const char * __init clkctrl_get_clock_name(struct device_node *np,
25285204959STero Kristo 						  const char *clkctrl_name,
25385204959STero Kristo 						  int offset, int index,
25485204959STero Kristo 						  bool legacy_naming)
25585204959STero Kristo {
25685204959STero Kristo 	char *clock_name;
25785204959STero Kristo 
25885204959STero Kristo 	/* l4per-clkctrl:1234:0 style naming based on clkctrl_name */
25985204959STero Kristo 	if (clkctrl_name && !legacy_naming) {
26085204959STero Kristo 		clock_name = kasprintf(GFP_KERNEL, "%s-clkctrl:%04x:%d",
26185204959STero Kristo 				       clkctrl_name, offset, index);
262bd46cd0bSClaudiu Beznea 		if (!clock_name)
263bd46cd0bSClaudiu Beznea 			return NULL;
264bd46cd0bSClaudiu Beznea 
26585204959STero Kristo 		strreplace(clock_name, '_', '-');
26685204959STero Kristo 
26785204959STero Kristo 		return clock_name;
26885204959STero Kristo 	}
26985204959STero Kristo 
27085204959STero Kristo 	/* l4per:1234:0 old style naming based on clkctrl_name */
27185204959STero Kristo 	if (clkctrl_name)
27285204959STero Kristo 		return kasprintf(GFP_KERNEL, "%s_cm:clk:%04x:%d",
27385204959STero Kristo 				 clkctrl_name, offset, index);
27485204959STero Kristo 
27585204959STero Kristo 	/* l4per_cm:1234:0 old style naming based on parent node name */
27685204959STero Kristo 	if (legacy_naming)
27785204959STero Kristo 		return kasprintf(GFP_KERNEL, "%pOFn:clk:%04x:%d",
27885204959STero Kristo 				 np->parent, offset, index);
27985204959STero Kristo 
28085204959STero Kristo 	/* l4per-clkctrl:1234:0 style naming based on node name */
28185204959STero Kristo 	return kasprintf(GFP_KERNEL, "%pOFn:%04x:%d", np, offset, index);
28285204959STero Kristo }
28385204959STero Kristo 
28488a17252STero Kristo static int __init
_ti_clkctrl_clk_register(struct omap_clkctrl_provider * provider,struct device_node * node,struct clk_hw * clk_hw,u16 offset,u8 bit,const char * const * parents,int num_parents,const struct clk_ops * ops,const char * clkctrl_name)28588a17252STero Kristo _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
28688a17252STero Kristo 			 struct device_node *node, struct clk_hw *clk_hw,
28788a17252STero Kristo 			 u16 offset, u8 bit, const char * const *parents,
28885204959STero Kristo 			 int num_parents, const struct clk_ops *ops,
28985204959STero Kristo 			 const char *clkctrl_name)
29088a17252STero Kristo {
29188a17252STero Kristo 	struct clk_init_data init = { NULL };
29288a17252STero Kristo 	struct clk *clk;
29388a17252STero Kristo 	struct omap_clkctrl_clk *clkctrl_clk;
29488a17252STero Kristo 	int ret = 0;
29588a17252STero Kristo 
29685204959STero Kristo 	init.name = clkctrl_get_clock_name(node, clkctrl_name, offset, bit,
29785204959STero Kristo 					   ti_clk_get_features()->flags &
29885204959STero Kristo 					   TI_CLK_CLKCTRL_COMPAT);
29985204959STero Kristo 
30088a17252STero Kristo 	clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
30188a17252STero Kristo 	if (!init.name || !clkctrl_clk) {
30288a17252STero Kristo 		ret = -ENOMEM;
30388a17252STero Kristo 		goto cleanup;
30488a17252STero Kristo 	}
30588a17252STero Kristo 
30688a17252STero Kristo 	clk_hw->init = &init;
30788a17252STero Kristo 	init.parent_names = parents;
30888a17252STero Kristo 	init.num_parents = num_parents;
30988a17252STero Kristo 	init.ops = ops;
3108aa09cf3STero Kristo 	init.flags = 0;
31188a17252STero Kristo 
3123400d546SDario Binacchi 	clk = of_ti_clk_register(node, clk_hw, init.name);
31388a17252STero Kristo 	if (IS_ERR_OR_NULL(clk)) {
31488a17252STero Kristo 		ret = -EINVAL;
31588a17252STero Kristo 		goto cleanup;
31688a17252STero Kristo 	}
31788a17252STero Kristo 
31888a17252STero Kristo 	clkctrl_clk->reg_offset = offset;
31988a17252STero Kristo 	clkctrl_clk->bit_offset = bit;
32088a17252STero Kristo 	clkctrl_clk->clk = clk_hw;
32188a17252STero Kristo 
32288a17252STero Kristo 	list_add(&clkctrl_clk->node, &provider->clocks);
32388a17252STero Kristo 
32488a17252STero Kristo 	return 0;
32588a17252STero Kristo 
32688a17252STero Kristo cleanup:
32788a17252STero Kristo 	kfree(init.name);
32888a17252STero Kristo 	kfree(clkctrl_clk);
32988a17252STero Kristo 	return ret;
33088a17252STero Kristo }
33188a17252STero Kristo 
33288a17252STero Kristo static void __init
_ti_clkctrl_setup_gate(struct omap_clkctrl_provider * provider,struct device_node * node,u16 offset,const struct omap_clkctrl_bit_data * data,void __iomem * reg,const char * clkctrl_name)33388a17252STero Kristo _ti_clkctrl_setup_gate(struct omap_clkctrl_provider *provider,
33488a17252STero Kristo 		       struct device_node *node, u16 offset,
33588a17252STero Kristo 		       const struct omap_clkctrl_bit_data *data,
33685204959STero Kristo 		       void __iomem *reg, const char *clkctrl_name)
33788a17252STero Kristo {
33888a17252STero Kristo 	struct clk_hw_omap *clk_hw;
33988a17252STero Kristo 
34088a17252STero Kristo 	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
34188a17252STero Kristo 	if (!clk_hw)
34288a17252STero Kristo 		return;
34388a17252STero Kristo 
34488a17252STero Kristo 	clk_hw->enable_bit = data->bit;
34588a17252STero Kristo 	clk_hw->enable_reg.ptr = reg;
34688a17252STero Kristo 
34788a17252STero Kristo 	if (_ti_clkctrl_clk_register(provider, node, &clk_hw->hw, offset,
34888a17252STero Kristo 				     data->bit, data->parents, 1,
34985204959STero Kristo 				     &omap_gate_clk_ops, clkctrl_name))
35088a17252STero Kristo 		kfree(clk_hw);
35188a17252STero Kristo }
35288a17252STero Kristo 
35388a17252STero Kristo static void __init
_ti_clkctrl_setup_mux(struct omap_clkctrl_provider * provider,struct device_node * node,u16 offset,const struct omap_clkctrl_bit_data * data,void __iomem * reg,const char * clkctrl_name)35488a17252STero Kristo _ti_clkctrl_setup_mux(struct omap_clkctrl_provider *provider,
35588a17252STero Kristo 		      struct device_node *node, u16 offset,
35688a17252STero Kristo 		      const struct omap_clkctrl_bit_data *data,
35785204959STero Kristo 		      void __iomem *reg, const char *clkctrl_name)
35888a17252STero Kristo {
35988a17252STero Kristo 	struct clk_omap_mux *mux;
36088a17252STero Kristo 	int num_parents = 0;
36188a17252STero Kristo 	const char * const *pname;
36288a17252STero Kristo 
36388a17252STero Kristo 	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
36488a17252STero Kristo 	if (!mux)
36588a17252STero Kristo 		return;
36688a17252STero Kristo 
36788a17252STero Kristo 	pname = data->parents;
36888a17252STero Kristo 	while (*pname) {
36988a17252STero Kristo 		num_parents++;
37088a17252STero Kristo 		pname++;
37188a17252STero Kristo 	}
37288a17252STero Kristo 
37388a17252STero Kristo 	mux->mask = num_parents;
37449eec6fbSTero Kristo 	if (!(mux->flags & CLK_MUX_INDEX_ONE))
37549eec6fbSTero Kristo 		mux->mask--;
37649eec6fbSTero Kristo 
37788a17252STero Kristo 	mux->mask = (1 << fls(mux->mask)) - 1;
37888a17252STero Kristo 
37988a17252STero Kristo 	mux->shift = data->bit;
38088a17252STero Kristo 	mux->reg.ptr = reg;
38188a17252STero Kristo 
38288a17252STero Kristo 	if (_ti_clkctrl_clk_register(provider, node, &mux->hw, offset,
38388a17252STero Kristo 				     data->bit, data->parents, num_parents,
38485204959STero Kristo 				     &ti_clk_mux_ops, clkctrl_name))
38588a17252STero Kristo 		kfree(mux);
38688a17252STero Kristo }
38788a17252STero Kristo 
38888a17252STero Kristo static void __init
_ti_clkctrl_setup_div(struct omap_clkctrl_provider * provider,struct device_node * node,u16 offset,const struct omap_clkctrl_bit_data * data,void __iomem * reg,const char * clkctrl_name)38988a17252STero Kristo _ti_clkctrl_setup_div(struct omap_clkctrl_provider *provider,
39088a17252STero Kristo 		      struct device_node *node, u16 offset,
39188a17252STero Kristo 		      const struct omap_clkctrl_bit_data *data,
39285204959STero Kristo 		      void __iomem *reg, const char *clkctrl_name)
39388a17252STero Kristo {
39488a17252STero Kristo 	struct clk_omap_divider *div;
39588a17252STero Kristo 	const struct omap_clkctrl_div_data *div_data = data->data;
39649eec6fbSTero Kristo 	u8 div_flags = 0;
39788a17252STero Kristo 
39888a17252STero Kristo 	div = kzalloc(sizeof(*div), GFP_KERNEL);
39988a17252STero Kristo 	if (!div)
40088a17252STero Kristo 		return;
40188a17252STero Kristo 
40288a17252STero Kristo 	div->reg.ptr = reg;
40388a17252STero Kristo 	div->shift = data->bit;
40449eec6fbSTero Kristo 	div->flags = div_data->flags;
40588a17252STero Kristo 
40649eec6fbSTero Kristo 	if (div->flags & CLK_DIVIDER_POWER_OF_TWO)
40749eec6fbSTero Kristo 		div_flags |= CLKF_INDEX_POWER_OF_TWO;
40849eec6fbSTero Kristo 
40949eec6fbSTero Kristo 	if (ti_clk_parse_divider_data((int *)div_data->dividers, 0,
41049eec6fbSTero Kristo 				      div_data->max_div, div_flags,
411a229965cSTero Kristo 				      div)) {
412c2c296c3STero Kristo 		pr_err("%s: Data parsing for %pOF:%04x:%d failed\n", __func__,
413c2c296c3STero Kristo 		       node, offset, data->bit);
41488a17252STero Kristo 		kfree(div);
41588a17252STero Kristo 		return;
41688a17252STero Kristo 	}
41788a17252STero Kristo 
41888a17252STero Kristo 	if (_ti_clkctrl_clk_register(provider, node, &div->hw, offset,
41988a17252STero Kristo 				     data->bit, data->parents, 1,
42085204959STero Kristo 				     &ti_clk_divider_ops, clkctrl_name))
42188a17252STero Kristo 		kfree(div);
42288a17252STero Kristo }
42388a17252STero Kristo 
42488a17252STero Kristo static void __init
_ti_clkctrl_setup_subclks(struct omap_clkctrl_provider * provider,struct device_node * node,const struct omap_clkctrl_reg_data * data,void __iomem * reg,const char * clkctrl_name)42588a17252STero Kristo _ti_clkctrl_setup_subclks(struct omap_clkctrl_provider *provider,
42688a17252STero Kristo 			  struct device_node *node,
42788a17252STero Kristo 			  const struct omap_clkctrl_reg_data *data,
42885204959STero Kristo 			  void __iomem *reg, const char *clkctrl_name)
42988a17252STero Kristo {
43088a17252STero Kristo 	const struct omap_clkctrl_bit_data *bits = data->bit_data;
43188a17252STero Kristo 
43288a17252STero Kristo 	if (!bits)
43388a17252STero Kristo 		return;
43488a17252STero Kristo 
43588a17252STero Kristo 	while (bits->bit) {
43688a17252STero Kristo 		switch (bits->type) {
43788a17252STero Kristo 		case TI_CLK_GATE:
43888a17252STero Kristo 			_ti_clkctrl_setup_gate(provider, node, data->offset,
43985204959STero Kristo 					       bits, reg, clkctrl_name);
44088a17252STero Kristo 			break;
44188a17252STero Kristo 
44288a17252STero Kristo 		case TI_CLK_DIVIDER:
44388a17252STero Kristo 			_ti_clkctrl_setup_div(provider, node, data->offset,
44485204959STero Kristo 					      bits, reg, clkctrl_name);
44588a17252STero Kristo 			break;
44688a17252STero Kristo 
44788a17252STero Kristo 		case TI_CLK_MUX:
44888a17252STero Kristo 			_ti_clkctrl_setup_mux(provider, node, data->offset,
44985204959STero Kristo 					      bits, reg, clkctrl_name);
45088a17252STero Kristo 			break;
45188a17252STero Kristo 
45288a17252STero Kristo 		default:
45388a17252STero Kristo 			pr_err("%s: bad subclk type: %d\n", __func__,
45488a17252STero Kristo 			       bits->type);
45588a17252STero Kristo 			return;
45688a17252STero Kristo 		}
45788a17252STero Kristo 		bits++;
45888a17252STero Kristo 	}
45988a17252STero Kristo }
46088a17252STero Kristo 
_clkctrl_add_provider(void * data,struct device_node * np)461729e13bfSTero Kristo static void __init _clkctrl_add_provider(void *data,
462729e13bfSTero Kristo 					 struct device_node *np)
463729e13bfSTero Kristo {
464729e13bfSTero Kristo 	of_clk_add_hw_provider(np, _ti_omap4_clkctrl_xlate, data);
465729e13bfSTero Kristo }
466729e13bfSTero Kristo 
467d02747e9STony Lindgren /*
468d02747e9STony Lindgren  * Get clock name based on "clock-output-names" property or the
469d02747e9STony Lindgren  * compatible property for clkctrl.
470d02747e9STony Lindgren  */
clkctrl_get_name(struct device_node * np)471d02747e9STony Lindgren static const char * __init clkctrl_get_name(struct device_node *np)
4726c309052STony Lindgren {
4736c309052STony Lindgren 	struct property *prop;
4746c309052STony Lindgren 	const int prefix_len = 11;
4756c309052STony Lindgren 	const char *compat;
476d02747e9STony Lindgren 	const char *output;
477*bb362d0eSAndy Shevchenko 	const char *end;
4786c309052STony Lindgren 	char *name;
4796c309052STony Lindgren 
480d02747e9STony Lindgren 	if (!of_property_read_string_index(np, "clock-output-names", 0,
481d02747e9STony Lindgren 					   &output)) {
482d02747e9STony Lindgren 		int len;
483d02747e9STony Lindgren 
484d02747e9STony Lindgren 		len = strlen(output);
485d02747e9STony Lindgren 		end = strstr(output, "_clkctrl");
486d02747e9STony Lindgren 		if (end)
487d02747e9STony Lindgren 			len -= strlen(end);
488d02747e9STony Lindgren 		name = kstrndup(output, len, GFP_KERNEL);
489d02747e9STony Lindgren 
490d02747e9STony Lindgren 		return name;
491d02747e9STony Lindgren 	}
492d02747e9STony Lindgren 
4936c309052STony Lindgren 	of_property_for_each_string(np, "compatible", prop, compat) {
4946c309052STony Lindgren 		if (!strncmp("ti,clkctrl-", compat, prefix_len)) {
495*bb362d0eSAndy Shevchenko 			end = compat + prefix_len;
4966c309052STony Lindgren 			/* Two letter minimum name length for l3, l4 etc */
497*bb362d0eSAndy Shevchenko 			if (strnlen(end, 16) < 2)
4986c309052STony Lindgren 				continue;
499*bb362d0eSAndy Shevchenko 			name = kstrdup_and_replace(end, '-', '_', GFP_KERNEL);
5006c309052STony Lindgren 			if (!name)
5016c309052STony Lindgren 				continue;
5026c309052STony Lindgren 
5036c309052STony Lindgren 			return name;
5046c309052STony Lindgren 		}
5056c309052STony Lindgren 	}
5066c309052STony Lindgren 
5076c309052STony Lindgren 	return NULL;
5086c309052STony Lindgren }
5096c309052STony Lindgren 
_ti_omap4_clkctrl_setup(struct device_node * node)51088a17252STero Kristo static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
51188a17252STero Kristo {
51288a17252STero Kristo 	struct omap_clkctrl_provider *provider;
51388a17252STero Kristo 	const struct omap_clkctrl_data *data = default_clkctrl_data;
51488a17252STero Kristo 	const struct omap_clkctrl_reg_data *reg_data;
51588a17252STero Kristo 	struct clk_init_data init = { NULL };
51688a17252STero Kristo 	struct clk_hw_omap *hw;
51788a17252STero Kristo 	struct clk *clk;
5186c309052STony Lindgren 	struct omap_clkctrl_clk *clkctrl_clk = NULL;
5196c309052STony Lindgren 	bool legacy_naming;
52078ab3a9aSTony Lindgren 	const char *clkctrl_name;
52188a17252STero Kristo 	u32 addr;
522729e13bfSTero Kristo 	int ret;
5231dc88f78STero Kristo 	char *c;
5242b1202d7STero Kristo 	u16 soc_mask = 0;
52581fe523aSRob Herring 	struct resource res;
52688a17252STero Kristo 
52781fe523aSRob Herring 	of_address_to_resource(node, 0, &res);
52881fe523aSRob Herring 	addr = (u32)res.start;
52988a17252STero Kristo 
5301c881b5aSTero Kristo #ifdef CONFIG_ARCH_OMAP4
5311c881b5aSTero Kristo 	if (of_machine_is_compatible("ti,omap4"))
5321c881b5aSTero Kristo 		data = omap4_clkctrl_data;
5331c881b5aSTero Kristo #endif
5340ad902f6STero Kristo #ifdef CONFIG_SOC_OMAP5
5350ad902f6STero Kristo 	if (of_machine_is_compatible("ti,omap5"))
5360ad902f6STero Kristo 		data = omap5_clkctrl_data;
5370ad902f6STero Kristo #endif
53824d504a3STero Kristo #ifdef CONFIG_SOC_DRA7XX
539579cdf58STony Lindgren 	if (of_machine_is_compatible("ti,dra7"))
54024d504a3STero Kristo 		data = dra7_clkctrl_data;
5412b1202d7STero Kristo 	if (of_machine_is_compatible("ti,dra72"))
5422b1202d7STero Kristo 		soc_mask = CLKF_SOC_DRA72;
5432b1202d7STero Kristo 	if (of_machine_is_compatible("ti,dra74"))
5442b1202d7STero Kristo 		soc_mask = CLKF_SOC_DRA74;
5452b1202d7STero Kristo 	if (of_machine_is_compatible("ti,dra76"))
5462b1202d7STero Kristo 		soc_mask = CLKF_SOC_DRA76;
54724d504a3STero Kristo #endif
548df54bfc5STero Kristo #ifdef CONFIG_SOC_AM33XX
5498850c3eaSTony Lindgren 	if (of_machine_is_compatible("ti,am33xx"))
550df54bfc5STero Kristo 		data = am3_clkctrl_data;
551df54bfc5STero Kristo #endif
552a3da10b7STero Kristo #ifdef CONFIG_SOC_AM43XX
553e65eb2efSTony Lindgren 	if (of_machine_is_compatible("ti,am4372"))
554a3da10b7STero Kristo 		data = am4_clkctrl_data;
55576a1049bSTero Kristo 
556e65eb2efSTony Lindgren 	if (of_machine_is_compatible("ti,am438x"))
557a3da10b7STero Kristo 		data = am438x_clkctrl_data;
558a3da10b7STero Kristo #endif
55926ca2e97STero Kristo #ifdef CONFIG_SOC_TI81XX
56026ca2e97STero Kristo 	if (of_machine_is_compatible("ti,dm814"))
56126ca2e97STero Kristo 		data = dm814_clkctrl_data;
56250ef5089STero Kristo 
56350ef5089STero Kristo 	if (of_machine_is_compatible("ti,dm816"))
56450ef5089STero Kristo 		data = dm816_clkctrl_data;
56526ca2e97STero Kristo #endif
5661c881b5aSTero Kristo 
567869decd1STero Kristo 	if (ti_clk_get_features()->flags & TI_CLK_DEVICE_TYPE_GP)
568869decd1STero Kristo 		soc_mask |= CLKF_SOC_NONSEC;
569869decd1STero Kristo 
57088a17252STero Kristo 	while (data->addr) {
57188a17252STero Kristo 		if (addr == data->addr)
57288a17252STero Kristo 			break;
57388a17252STero Kristo 
57488a17252STero Kristo 		data++;
57588a17252STero Kristo 	}
57688a17252STero Kristo 
57788a17252STero Kristo 	if (!data->addr) {
578c2c296c3STero Kristo 		pr_err("%pOF not found from clkctrl data.\n", node);
57988a17252STero Kristo 		return;
58088a17252STero Kristo 	}
58188a17252STero Kristo 
58288a17252STero Kristo 	provider = kzalloc(sizeof(*provider), GFP_KERNEL);
58388a17252STero Kristo 	if (!provider)
58488a17252STero Kristo 		return;
58588a17252STero Kristo 
58688a17252STero Kristo 	provider->base = of_iomap(node, 0);
58788a17252STero Kristo 
5886c309052STony Lindgren 	legacy_naming = ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT;
5896c309052STony Lindgren 	clkctrl_name = clkctrl_get_name(node);
5906c309052STony Lindgren 	if (clkctrl_name) {
5916c309052STony Lindgren 		provider->clkdm_name = kasprintf(GFP_KERNEL,
5926c309052STony Lindgren 						 "%s_clkdm", clkctrl_name);
593bd46cd0bSClaudiu Beznea 		if (!provider->clkdm_name) {
594bd46cd0bSClaudiu Beznea 			kfree(provider);
595bd46cd0bSClaudiu Beznea 			return;
596bd46cd0bSClaudiu Beznea 		}
5976c309052STony Lindgren 		goto clkdm_found;
5986c309052STony Lindgren 	}
5996c309052STony Lindgren 
6006c309052STony Lindgren 	/*
6016c309052STony Lindgren 	 * The code below can be removed when all clkctrl nodes use domain
6026a6c2389SJulia Lawall 	 * specific compatible property and standard clock node naming
6036c309052STony Lindgren 	 */
6046c309052STony Lindgren 	if (legacy_naming) {
605e665f029SRob Herring 		provider->clkdm_name = kasprintf(GFP_KERNEL, "%pOFnxxx", node->parent);
606ddfb183eSTero Kristo 		if (!provider->clkdm_name) {
607ddfb183eSTero Kristo 			kfree(provider);
608ddfb183eSTero Kristo 			return;
609ddfb183eSTero Kristo 		}
610ddfb183eSTero Kristo 
611ddfb183eSTero Kristo 		/*
61247b00dcfSTero Kristo 		 * Create default clkdm name, replace _cm from end of parent
61347b00dcfSTero Kristo 		 * node name with _clkdm
614ddfb183eSTero Kristo 		 */
615d17a718dSTony Lindgren 		provider->clkdm_name[strlen(provider->clkdm_name) - 2] = 0;
61647b00dcfSTero Kristo 	} else {
617a72d7850SStephen Boyd 		provider->clkdm_name = kasprintf(GFP_KERNEL, "%pOFn", node);
61847b00dcfSTero Kristo 		if (!provider->clkdm_name) {
61947b00dcfSTero Kristo 			kfree(provider);
62047b00dcfSTero Kristo 			return;
62147b00dcfSTero Kristo 		}
62247b00dcfSTero Kristo 
62347b00dcfSTero Kristo 		/*
62447b00dcfSTero Kristo 		 * Create default clkdm name, replace _clkctrl from end of
62547b00dcfSTero Kristo 		 * node name with _clkdm
62647b00dcfSTero Kristo 		 */
62747b00dcfSTero Kristo 		provider->clkdm_name[strlen(provider->clkdm_name) - 7] = 0;
62847b00dcfSTero Kristo 	}
62947b00dcfSTero Kristo 
630ddfb183eSTero Kristo 	strcat(provider->clkdm_name, "clkdm");
631ddfb183eSTero Kristo 
6321dc88f78STero Kristo 	/* Replace any dash from the clkdm name with underscore */
6331dc88f78STero Kristo 	c = provider->clkdm_name;
6341dc88f78STero Kristo 
6351dc88f78STero Kristo 	while (*c) {
6361dc88f78STero Kristo 		if (*c == '-')
6371dc88f78STero Kristo 			*c = '_';
6381dc88f78STero Kristo 		c++;
6391dc88f78STero Kristo 	}
6406c309052STony Lindgren clkdm_found:
64188a17252STero Kristo 	INIT_LIST_HEAD(&provider->clocks);
64288a17252STero Kristo 
64388a17252STero Kristo 	/* Generate clocks */
64488a17252STero Kristo 	reg_data = data->regs;
64588a17252STero Kristo 
64688a17252STero Kristo 	while (reg_data->parent) {
6472b1202d7STero Kristo 		if ((reg_data->flags & CLKF_SOC_MASK) &&
6482b1202d7STero Kristo 		    (reg_data->flags & soc_mask) == 0) {
6492b1202d7STero Kristo 			reg_data++;
6502b1202d7STero Kristo 			continue;
6512b1202d7STero Kristo 		}
6522b1202d7STero Kristo 
65388a17252STero Kristo 		hw = kzalloc(sizeof(*hw), GFP_KERNEL);
65488a17252STero Kristo 		if (!hw)
65588a17252STero Kristo 			return;
65688a17252STero Kristo 
65788a17252STero Kristo 		hw->enable_reg.ptr = provider->base + reg_data->offset;
65888a17252STero Kristo 
65988a17252STero Kristo 		_ti_clkctrl_setup_subclks(provider, node, reg_data,
66085204959STero Kristo 					  hw->enable_reg.ptr, clkctrl_name);
66188a17252STero Kristo 
66288a17252STero Kristo 		if (reg_data->flags & CLKF_SW_SUP)
66388a17252STero Kristo 			hw->enable_bit = MODULEMODE_SWCTRL;
66488a17252STero Kristo 		if (reg_data->flags & CLKF_HW_SUP)
66588a17252STero Kristo 			hw->enable_bit = MODULEMODE_HWCTRL;
66688a17252STero Kristo 		if (reg_data->flags & CLKF_NO_IDLEST)
66722a6564fSTero Kristo 			set_bit(NO_IDLEST, &hw->flags);
66888a17252STero Kristo 
669ddfb183eSTero Kristo 		if (reg_data->clkdm_name)
670ddfb183eSTero Kristo 			hw->clkdm_name = reg_data->clkdm_name;
671ddfb183eSTero Kristo 		else
672ddfb183eSTero Kristo 			hw->clkdm_name = provider->clkdm_name;
673ddfb183eSTero Kristo 
67488a17252STero Kristo 		init.parent_names = &reg_data->parent;
67588a17252STero Kristo 		init.num_parents = 1;
67688a17252STero Kristo 		init.flags = 0;
67749159a9dSTero Kristo 		if (reg_data->flags & CLKF_SET_RATE_PARENT)
67849159a9dSTero Kristo 			init.flags |= CLK_SET_RATE_PARENT;
6796c309052STony Lindgren 
6806c309052STony Lindgren 		init.name = clkctrl_get_clock_name(node, clkctrl_name,
6816c309052STony Lindgren 						   reg_data->offset, 0,
6826c309052STony Lindgren 						   legacy_naming);
6836c309052STony Lindgren 		if (!init.name)
6846c309052STony Lindgren 			goto cleanup;
6856c309052STony Lindgren 
68688a17252STero Kristo 		clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
6876c309052STony Lindgren 		if (!clkctrl_clk)
68888a17252STero Kristo 			goto cleanup;
68988a17252STero Kristo 
69088a17252STero Kristo 		init.ops = &omap4_clkctrl_clk_ops;
69188a17252STero Kristo 		hw->hw.init = &init;
69288a17252STero Kristo 
6933400d546SDario Binacchi 		clk = of_ti_clk_register_omap_hw(node, &hw->hw, init.name);
69488a17252STero Kristo 		if (IS_ERR_OR_NULL(clk))
69588a17252STero Kristo 			goto cleanup;
69688a17252STero Kristo 
69788a17252STero Kristo 		clkctrl_clk->reg_offset = reg_data->offset;
69888a17252STero Kristo 		clkctrl_clk->clk = &hw->hw;
69988a17252STero Kristo 
70088a17252STero Kristo 		list_add(&clkctrl_clk->node, &provider->clocks);
70188a17252STero Kristo 
70288a17252STero Kristo 		reg_data++;
70388a17252STero Kristo 	}
70488a17252STero Kristo 
705729e13bfSTero Kristo 	ret = of_clk_add_hw_provider(node, _ti_omap4_clkctrl_xlate, provider);
706729e13bfSTero Kristo 	if (ret == -EPROBE_DEFER)
707729e13bfSTero Kristo 		ti_clk_retry_init(node, provider, _clkctrl_add_provider);
708729e13bfSTero Kristo 
7096c309052STony Lindgren 	kfree(clkctrl_name);
7106c309052STony Lindgren 
71188a17252STero Kristo 	return;
71288a17252STero Kristo 
71388a17252STero Kristo cleanup:
71488a17252STero Kristo 	kfree(hw);
71588a17252STero Kristo 	kfree(init.name);
7166c309052STony Lindgren 	kfree(clkctrl_name);
71788a17252STero Kristo 	kfree(clkctrl_clk);
71888a17252STero Kristo }
71988a17252STero Kristo CLK_OF_DECLARE(ti_omap4_clkctrl_clock, "ti,clkctrl",
72088a17252STero Kristo 	       _ti_omap4_clkctrl_setup);
7212209b72dSTero Kristo 
7222209b72dSTero Kristo /**
7232209b72dSTero Kristo  * ti_clk_is_in_standby - Check if clkctrl clock is in standby or not
7242209b72dSTero Kristo  * @clk: clock to check standby status for
7252209b72dSTero Kristo  *
7262209b72dSTero Kristo  * Finds whether the provided clock is in standby mode or not. Returns
7272209b72dSTero Kristo  * true if the provided clock is a clkctrl type clock and it is in standby,
7282209b72dSTero Kristo  * false otherwise.
7292209b72dSTero Kristo  */
ti_clk_is_in_standby(struct clk * clk)7302209b72dSTero Kristo bool ti_clk_is_in_standby(struct clk *clk)
7312209b72dSTero Kristo {
7322209b72dSTero Kristo 	struct clk_hw *hw;
7332209b72dSTero Kristo 	struct clk_hw_omap *hwclk;
7342209b72dSTero Kristo 	u32 val;
7352209b72dSTero Kristo 
7362209b72dSTero Kristo 	hw = __clk_get_hw(clk);
7372209b72dSTero Kristo 
7382209b72dSTero Kristo 	if (!omap2_clk_is_hw_omap(hw))
7392209b72dSTero Kristo 		return false;
7402209b72dSTero Kristo 
7412209b72dSTero Kristo 	hwclk = to_clk_hw_omap(hw);
7422209b72dSTero Kristo 
7432209b72dSTero Kristo 	val = ti_clk_ll_ops->clk_readl(&hwclk->enable_reg);
7442209b72dSTero Kristo 
7452209b72dSTero Kristo 	if (val & OMAP4_STBYST_MASK)
7462209b72dSTero Kristo 		return true;
7472209b72dSTero Kristo 
7482209b72dSTero Kristo 	return false;
7492209b72dSTero Kristo }
7502209b72dSTero Kristo EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
751