Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * OMAP clkctrl clock support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (C) 2017 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Tero Kristo <t-kristo@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * it under the terms of the GNU General Public License version 2 as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * kind, whether express or implied; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/clk/ti.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/timekeeping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include "clock.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define NO_IDLEST			0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define OMAP4_MODULEMODE_MASK		0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define MODULEMODE_HWCTRL		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define MODULEMODE_SWCTRL		0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define OMAP4_IDLEST_MASK		(0x3 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define OMAP4_IDLEST_SHIFT		16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define OMAP4_STBYST_MASK		BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define OMAP4_STBYST_SHIFT		18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define CLKCTRL_IDLEST_FUNCTIONAL	0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define CLKCTRL_IDLEST_INTERFACE_IDLE	0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define CLKCTRL_IDLEST_DISABLED		0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) /* These timeouts are in us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define OMAP4_MAX_MODULE_READY_TIME	2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define OMAP4_MAX_MODULE_DISABLE_TIME	5000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static bool _early_timeout = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) struct omap_clkctrl_provider {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	struct list_head clocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	char *clkdm_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) struct omap_clkctrl_clk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	struct clk_hw *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	u16 reg_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	int bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	struct list_head node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) union omap4_timeout {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	u32 cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	ktime_t start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static const struct omap_clkctrl_data default_clkctrl_data[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	{ 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static u32 _omap4_idlest(u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	val &= OMAP4_IDLEST_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	val >>= OMAP4_IDLEST_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) static bool _omap4_is_idle(u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	val = _omap4_idlest(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	return val == CLKCTRL_IDLEST_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static bool _omap4_is_ready(u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	val = _omap4_idlest(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return val == CLKCTRL_IDLEST_FUNCTIONAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	       val == CLKCTRL_IDLEST_INTERFACE_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static bool _omap4_is_timeout(union omap4_timeout *time, u32 timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	 * There are two special cases where ktime_to_ns() can't be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * used to track the timeouts. First one is during early boot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 * when the timers haven't been initialized yet. The second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 * one is during suspend-resume cycle while timekeeping is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 * being suspended / resumed. Clocksource for the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	 * can be from a timer that requires pm_runtime access, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	 * will eventually bring us here with timekeeping_suspended,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	 * during both suspend entry and resume paths. This happens
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	 * at least on am43xx platform. Account for flakeyness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	 * with udelay() by multiplying the timeout value by 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	if (unlikely(_early_timeout || timekeeping_suspended)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		if (time->cycles++ < timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			udelay(1 * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		if (!ktime_to_ns(time->start)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 			time->start = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		if (ktime_us_delta(ktime_get(), time->start) < timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int __init _omap4_disable_early_timeout(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	_early_timeout = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) arch_initcall(_omap4_disable_early_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static int _omap4_clkctrl_clk_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	union omap4_timeout timeout = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	if (clk->clkdm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		ret = ti_clk_ll_ops->clkdm_clk_enable(clk->clkdm, hw->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			WARN(1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			     "%s: could not enable %s's clockdomain %s: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			     __func__, clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			     clk->clkdm_name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	if (!clk->enable_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	val &= ~OMAP4_MODULEMODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	val |= clk->enable_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	ti_clk_ll_ops->clk_writel(val, &clk->enable_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (test_bit(NO_IDLEST, &clk->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/* Wait until module is enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			pr_err("%s: failed to enable\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 			return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static void _omap4_clkctrl_clk_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	union omap4_timeout timeout = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	if (!clk->enable_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	val &= ~OMAP4_MODULEMODE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	ti_clk_ll_ops->clk_writel(val, &clk->enable_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	if (test_bit(NO_IDLEST, &clk->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	/* Wait until module is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		if (_omap4_is_timeout(&timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 				      OMAP4_MAX_MODULE_DISABLE_TIME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 			pr_err("%s: failed to disable\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (clk->clkdm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int _omap4_clkctrl_clk_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	val = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	if (val & clk->enable_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static const struct clk_ops omap4_clkctrl_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	.enable		= _omap4_clkctrl_clk_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	.disable	= _omap4_clkctrl_clk_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	.is_enabled	= _omap4_clkctrl_clk_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	.init		= omap2_init_clk_clkdm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static struct clk_hw *_ti_omap4_clkctrl_xlate(struct of_phandle_args *clkspec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 					      void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	struct omap_clkctrl_provider *provider = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	struct omap_clkctrl_clk *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	if (clkspec->args_count != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	pr_debug("%s: looking for %x:%x\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		 clkspec->args[0], clkspec->args[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	list_for_each_entry(entry, &provider->clocks, node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		if (entry->reg_offset == clkspec->args[0] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		    entry->bit_offset == clkspec->args[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	return entry->clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* Get clkctrl clock base name based on clkctrl_name or dts node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static const char * __init clkctrl_get_clock_name(struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 						  const char *clkctrl_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 						  int offset, int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 						  bool legacy_naming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	char *clock_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	/* l4per-clkctrl:1234:0 style naming based on clkctrl_name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (clkctrl_name && !legacy_naming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		clock_name = kasprintf(GFP_KERNEL, "%s-clkctrl:%04x:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 				       clkctrl_name, offset, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		strreplace(clock_name, '_', '-');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		return clock_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	/* l4per:1234:0 old style naming based on clkctrl_name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	if (clkctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		return kasprintf(GFP_KERNEL, "%s_cm:clk:%04x:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 				 clkctrl_name, offset, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	/* l4per_cm:1234:0 old style naming based on parent node name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	if (legacy_naming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		return kasprintf(GFP_KERNEL, "%pOFn:clk:%04x:%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 				 np->parent, offset, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	/* l4per-clkctrl:1234:0 style naming based on node name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	return kasprintf(GFP_KERNEL, "%pOFn:%04x:%d", np, offset, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			 struct device_node *node, struct clk_hw *clk_hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			 u16 offset, u8 bit, const char * const *parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			 int num_parents, const struct clk_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 			 const char *clkctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	struct clk_init_data init = { NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	struct omap_clkctrl_clk *clkctrl_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	init.name = clkctrl_get_clock_name(node, clkctrl_name, offset, bit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 					   ti_clk_get_features()->flags &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 					   TI_CLK_CLKCTRL_COMPAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	if (!init.name || !clkctrl_clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	clk_hw->init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	init.parent_names = parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	init.ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	clk = ti_clk_register(NULL, clk_hw, init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	if (IS_ERR_OR_NULL(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	clkctrl_clk->reg_offset = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	clkctrl_clk->bit_offset = bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	clkctrl_clk->clk = clk_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	list_add(&clkctrl_clk->node, &provider->clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	kfree(init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	kfree(clkctrl_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) _ti_clkctrl_setup_gate(struct omap_clkctrl_provider *provider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		       struct device_node *node, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		       const struct omap_clkctrl_bit_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		       void __iomem *reg, const char *clkctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	struct clk_hw_omap *clk_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	if (!clk_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	clk_hw->enable_bit = data->bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	clk_hw->enable_reg.ptr = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	if (_ti_clkctrl_clk_register(provider, node, &clk_hw->hw, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 				     data->bit, data->parents, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 				     &omap_gate_clk_ops, clkctrl_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		kfree(clk_hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) _ti_clkctrl_setup_mux(struct omap_clkctrl_provider *provider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		      struct device_node *node, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		      const struct omap_clkctrl_bit_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		      void __iomem *reg, const char *clkctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	struct clk_omap_mux *mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	int num_parents = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	const char * const *pname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	if (!mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	pname = data->parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	while (*pname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		num_parents++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 		pname++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	mux->mask = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	if (!(mux->flags & CLK_MUX_INDEX_ONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 		mux->mask--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	mux->mask = (1 << fls(mux->mask)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	mux->shift = data->bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	mux->reg.ptr = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	if (_ti_clkctrl_clk_register(provider, node, &mux->hw, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 				     data->bit, data->parents, num_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 				     &ti_clk_mux_ops, clkctrl_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		kfree(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) _ti_clkctrl_setup_div(struct omap_clkctrl_provider *provider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 		      struct device_node *node, u16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 		      const struct omap_clkctrl_bit_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 		      void __iomem *reg, const char *clkctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct clk_omap_divider *div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	const struct omap_clkctrl_div_data *div_data = data->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	u8 div_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	div = kzalloc(sizeof(*div), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	if (!div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	div->reg.ptr = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	div->shift = data->bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	div->flags = div_data->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	if (div->flags & CLK_DIVIDER_POWER_OF_TWO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		div_flags |= CLKF_INDEX_POWER_OF_TWO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	if (ti_clk_parse_divider_data((int *)div_data->dividers, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 				      div_data->max_div, div_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 				      div)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		pr_err("%s: Data parsing for %pOF:%04x:%d failed\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 		       node, offset, data->bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		kfree(div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	if (_ti_clkctrl_clk_register(provider, node, &div->hw, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 				     data->bit, data->parents, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 				     &ti_clk_divider_ops, clkctrl_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		kfree(div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) static void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) _ti_clkctrl_setup_subclks(struct omap_clkctrl_provider *provider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 			  struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 			  const struct omap_clkctrl_reg_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 			  void __iomem *reg, const char *clkctrl_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	const struct omap_clkctrl_bit_data *bits = data->bit_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	if (!bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	while (bits->bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		switch (bits->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		case TI_CLK_GATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 			_ti_clkctrl_setup_gate(provider, node, data->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 					       bits, reg, clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		case TI_CLK_DIVIDER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 			_ti_clkctrl_setup_div(provider, node, data->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 					      bits, reg, clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 		case TI_CLK_MUX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 			_ti_clkctrl_setup_mux(provider, node, data->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 					      bits, reg, clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 			pr_err("%s: bad subclk type: %d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 			       bits->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		bits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static void __init _clkctrl_add_provider(void *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 					 struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	of_clk_add_hw_provider(np, _ti_omap4_clkctrl_xlate, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* Get clock name based on compatible string for clkctrl */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static char * __init clkctrl_get_name(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	const int prefix_len = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	const char *compat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	of_property_for_each_string(np, "compatible", prop, compat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		if (!strncmp("ti,clkctrl-", compat, prefix_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 			/* Two letter minimum name length for l3, l4 etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 			if (strnlen(compat + prefix_len, 16) < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 			name = kasprintf(GFP_KERNEL, "%s", compat + prefix_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 			if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 			strreplace(name, '-', '_');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 			return name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	struct omap_clkctrl_provider *provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	const struct omap_clkctrl_data *data = default_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	const struct omap_clkctrl_reg_data *reg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	struct clk_init_data init = { NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	struct clk_hw_omap *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	struct omap_clkctrl_clk *clkctrl_clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	const __be32 *addrp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	bool legacy_naming;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	char *clkctrl_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	char *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	u16 soc_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	if (!(ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	    of_node_name_eq(node, "clk"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		ti_clk_features.flags |= TI_CLK_CLKCTRL_COMPAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	addrp = of_get_address(node, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	addr = (u32)of_translate_address(node, addrp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #ifdef CONFIG_ARCH_OMAP4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	if (of_machine_is_compatible("ti,omap4"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		data = omap4_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) #ifdef CONFIG_SOC_OMAP5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	if (of_machine_is_compatible("ti,omap5"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		data = omap5_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #ifdef CONFIG_SOC_DRA7XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	if (of_machine_is_compatible("ti,dra7")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			data = dra7_clkctrl_compat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 			data = dra7_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	if (of_machine_is_compatible("ti,dra72"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		soc_mask = CLKF_SOC_DRA72;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	if (of_machine_is_compatible("ti,dra74"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 		soc_mask = CLKF_SOC_DRA74;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	if (of_machine_is_compatible("ti,dra76"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		soc_mask = CLKF_SOC_DRA76;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) #ifdef CONFIG_SOC_AM33XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	if (of_machine_is_compatible("ti,am33xx")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 			data = am3_clkctrl_compat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 			data = am3_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) #ifdef CONFIG_SOC_AM43XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	if (of_machine_is_compatible("ti,am4372")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 			data = am4_clkctrl_compat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 			data = am4_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	if (of_machine_is_compatible("ti,am438x")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		if (ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 			data = am438x_clkctrl_compat_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 			data = am438x_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #ifdef CONFIG_SOC_TI81XX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 	if (of_machine_is_compatible("ti,dm814"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		data = dm814_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	if (of_machine_is_compatible("ti,dm816"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 		data = dm816_clkctrl_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	if (ti_clk_get_features()->flags & TI_CLK_DEVICE_TYPE_GP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		soc_mask |= CLKF_SOC_NONSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 	while (data->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		if (addr == data->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		data++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	if (!data->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		pr_err("%pOF not found from clkctrl data.\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	provider = kzalloc(sizeof(*provider), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	if (!provider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	provider->base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	legacy_naming = ti_clk_get_features()->flags & TI_CLK_CLKCTRL_COMPAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	clkctrl_name = clkctrl_get_name(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	if (clkctrl_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 		provider->clkdm_name = kasprintf(GFP_KERNEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 						 "%s_clkdm", clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 		goto clkdm_found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	 * The code below can be removed when all clkctrl nodes use domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	 * specific compatible proprerty and standard clock node naming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	if (legacy_naming) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		provider->clkdm_name = kasprintf(GFP_KERNEL, "%pOFnxxx", node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		if (!provider->clkdm_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 			kfree(provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 		 * Create default clkdm name, replace _cm from end of parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 		 * node name with _clkdm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 		provider->clkdm_name[strlen(provider->clkdm_name) - 2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 		provider->clkdm_name = kasprintf(GFP_KERNEL, "%pOFn", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 		if (!provider->clkdm_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 			kfree(provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		 * Create default clkdm name, replace _clkctrl from end of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		 * node name with _clkdm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		provider->clkdm_name[strlen(provider->clkdm_name) - 7] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	strcat(provider->clkdm_name, "clkdm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	/* Replace any dash from the clkdm name with underscore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	c = provider->clkdm_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	while (*c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 		if (*c == '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 			*c = '_';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		c++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) clkdm_found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	INIT_LIST_HEAD(&provider->clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	/* Generate clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	reg_data = data->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	while (reg_data->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		if ((reg_data->flags & CLKF_SOC_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 		    (reg_data->flags & soc_mask) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 			reg_data++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 		hw = kzalloc(sizeof(*hw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 		if (!hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 		hw->enable_reg.ptr = provider->base + reg_data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 		_ti_clkctrl_setup_subclks(provider, node, reg_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 					  hw->enable_reg.ptr, clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		if (reg_data->flags & CLKF_SW_SUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 			hw->enable_bit = MODULEMODE_SWCTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		if (reg_data->flags & CLKF_HW_SUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 			hw->enable_bit = MODULEMODE_HWCTRL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 		if (reg_data->flags & CLKF_NO_IDLEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 			set_bit(NO_IDLEST, &hw->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		if (reg_data->clkdm_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 			hw->clkdm_name = reg_data->clkdm_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 			hw->clkdm_name = provider->clkdm_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		init.parent_names = &reg_data->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 		init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 		if (reg_data->flags & CLKF_SET_RATE_PARENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 			init.flags |= CLK_SET_RATE_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 		init.name = clkctrl_get_clock_name(node, clkctrl_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 						   reg_data->offset, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 						   legacy_naming);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 		if (!init.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 			goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 		clkctrl_clk = kzalloc(sizeof(*clkctrl_clk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 		if (!clkctrl_clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 			goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 		init.ops = &omap4_clkctrl_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 		hw->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 		clk = ti_clk_register_omap_hw(NULL, &hw->hw, init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		if (IS_ERR_OR_NULL(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 			goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 		clkctrl_clk->reg_offset = reg_data->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 		clkctrl_clk->clk = &hw->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 		list_add(&clkctrl_clk->node, &provider->clocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 		reg_data++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	ret = of_clk_add_hw_provider(node, _ti_omap4_clkctrl_xlate, provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 		ti_clk_retry_init(node, provider, _clkctrl_add_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	kfree(clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	kfree(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	kfree(init.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	kfree(clkctrl_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	kfree(clkctrl_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) CLK_OF_DECLARE(ti_omap4_clkctrl_clock, "ti,clkctrl",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	       _ti_omap4_clkctrl_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)  * ti_clk_is_in_standby - Check if clkctrl clock is in standby or not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)  * @clk: clock to check standby status for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)  * Finds whether the provided clock is in standby mode or not. Returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)  * true if the provided clock is a clkctrl type clock and it is in standby,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)  * false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) bool ti_clk_is_in_standby(struct clk *clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	struct clk_hw_omap *hwclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	hw = __clk_get_hw(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	if (!omap2_clk_is_hw_omap(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	hwclk = to_clk_hw_omap(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	val = ti_clk_ll_ops->clk_readl(&hwclk->enable_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 	if (val & OMAP4_STBYST_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);