^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 = ®_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);