0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/slab.h>
0008 #include <linux/io.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011
0012 #include <soc/tegra/fuse.h>
0013
0014 #include "clk.h"
0015
0016 static DEFINE_SPINLOCK(periph_ref_lock);
0017
0018
0019 #define read_enb(gate) \
0020 readl_relaxed(gate->clk_base + (gate->regs->enb_reg))
0021 #define write_enb_set(val, gate) \
0022 writel_relaxed(val, gate->clk_base + (gate->regs->enb_set_reg))
0023 #define write_enb_clr(val, gate) \
0024 writel_relaxed(val, gate->clk_base + (gate->regs->enb_clr_reg))
0025
0026 #define read_rst(gate) \
0027 readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
0028 #define write_rst_clr(val, gate) \
0029 writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
0030
0031 #define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32))
0032
0033 #define LVL2_CLK_GATE_OVRE 0x554
0034
0035
0036 static int clk_periph_is_enabled(struct clk_hw *hw)
0037 {
0038 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0039 int state = 1;
0040
0041 if (!(read_enb(gate) & periph_clk_to_bit(gate)))
0042 state = 0;
0043
0044 if (!(gate->flags & TEGRA_PERIPH_NO_RESET))
0045 if (read_rst(gate) & periph_clk_to_bit(gate))
0046 state = 0;
0047
0048 return state;
0049 }
0050
0051 static void clk_periph_enable_locked(struct clk_hw *hw)
0052 {
0053 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0054
0055 write_enb_set(periph_clk_to_bit(gate), gate);
0056 udelay(2);
0057
0058 if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
0059 writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
0060 writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
0061 udelay(1);
0062 writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
0063 }
0064 }
0065
0066 static void clk_periph_disable_locked(struct clk_hw *hw)
0067 {
0068 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0069
0070
0071
0072
0073
0074
0075 if (gate->flags & TEGRA_PERIPH_ON_APB)
0076 tegra_read_chipid();
0077
0078 write_enb_clr(periph_clk_to_bit(gate), gate);
0079 }
0080
0081 static int clk_periph_enable(struct clk_hw *hw)
0082 {
0083 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0084 unsigned long flags = 0;
0085
0086 spin_lock_irqsave(&periph_ref_lock, flags);
0087
0088 if (!gate->enable_refcnt[gate->clk_num]++)
0089 clk_periph_enable_locked(hw);
0090
0091 spin_unlock_irqrestore(&periph_ref_lock, flags);
0092
0093 return 0;
0094 }
0095
0096 static void clk_periph_disable(struct clk_hw *hw)
0097 {
0098 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0099 unsigned long flags = 0;
0100
0101 spin_lock_irqsave(&periph_ref_lock, flags);
0102
0103 WARN_ON(!gate->enable_refcnt[gate->clk_num]);
0104
0105 if (--gate->enable_refcnt[gate->clk_num] == 0)
0106 clk_periph_disable_locked(hw);
0107
0108 spin_unlock_irqrestore(&periph_ref_lock, flags);
0109 }
0110
0111 static void clk_periph_disable_unused(struct clk_hw *hw)
0112 {
0113 struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0114 unsigned long flags = 0;
0115
0116 spin_lock_irqsave(&periph_ref_lock, flags);
0117
0118
0119
0120
0121
0122
0123 if (!gate->enable_refcnt[gate->clk_num])
0124 clk_periph_disable_locked(hw);
0125
0126 spin_unlock_irqrestore(&periph_ref_lock, flags);
0127 }
0128
0129 const struct clk_ops tegra_clk_periph_gate_ops = {
0130 .is_enabled = clk_periph_is_enabled,
0131 .enable = clk_periph_enable,
0132 .disable = clk_periph_disable,
0133 .disable_unused = clk_periph_disable_unused,
0134 };
0135
0136 struct clk *tegra_clk_register_periph_gate(const char *name,
0137 const char *parent_name, u8 gate_flags, void __iomem *clk_base,
0138 unsigned long flags, int clk_num, int *enable_refcnt)
0139 {
0140 struct tegra_clk_periph_gate *gate;
0141 struct clk *clk;
0142 struct clk_init_data init;
0143 const struct tegra_clk_periph_regs *pregs;
0144
0145 pregs = get_reg_bank(clk_num);
0146 if (!pregs)
0147 return ERR_PTR(-EINVAL);
0148
0149 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
0150 if (!gate) {
0151 pr_err("%s: could not allocate periph gate clk\n", __func__);
0152 return ERR_PTR(-ENOMEM);
0153 }
0154
0155 init.name = name;
0156 init.flags = flags;
0157 init.parent_names = parent_name ? &parent_name : NULL;
0158 init.num_parents = parent_name ? 1 : 0;
0159 init.ops = &tegra_clk_periph_gate_ops;
0160
0161 gate->magic = TEGRA_CLK_PERIPH_GATE_MAGIC;
0162 gate->clk_base = clk_base;
0163 gate->clk_num = clk_num;
0164 gate->flags = gate_flags;
0165 gate->enable_refcnt = enable_refcnt;
0166 gate->regs = pregs;
0167
0168
0169 gate->hw.init = &init;
0170
0171 clk = clk_register(NULL, &gate->hw);
0172 if (IS_ERR(clk))
0173 kfree(gate);
0174
0175 return clk;
0176 }