0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/bitops.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/io.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/slab.h>
0014 #include <linux/spinlock.h>
0015
0016 #include "berlin2-div.h"
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 #define PLL_SELECT_MASK 0x7
0052 #define DIV_SELECT_MASK 0x7
0053
0054 struct berlin2_div {
0055 struct clk_hw hw;
0056 void __iomem *base;
0057 struct berlin2_div_map map;
0058 spinlock_t *lock;
0059 };
0060
0061 #define to_berlin2_div(hw) container_of(hw, struct berlin2_div, hw)
0062
0063 static u8 clk_div[] = { 1, 2, 4, 6, 8, 12, 1, 1 };
0064
0065 static int berlin2_div_is_enabled(struct clk_hw *hw)
0066 {
0067 struct berlin2_div *div = to_berlin2_div(hw);
0068 struct berlin2_div_map *map = &div->map;
0069 u32 reg;
0070
0071 if (div->lock)
0072 spin_lock(div->lock);
0073
0074 reg = readl_relaxed(div->base + map->gate_offs);
0075 reg >>= map->gate_shift;
0076
0077 if (div->lock)
0078 spin_unlock(div->lock);
0079
0080 return (reg & 0x1);
0081 }
0082
0083 static int berlin2_div_enable(struct clk_hw *hw)
0084 {
0085 struct berlin2_div *div = to_berlin2_div(hw);
0086 struct berlin2_div_map *map = &div->map;
0087 u32 reg;
0088
0089 if (div->lock)
0090 spin_lock(div->lock);
0091
0092 reg = readl_relaxed(div->base + map->gate_offs);
0093 reg |= BIT(map->gate_shift);
0094 writel_relaxed(reg, div->base + map->gate_offs);
0095
0096 if (div->lock)
0097 spin_unlock(div->lock);
0098
0099 return 0;
0100 }
0101
0102 static void berlin2_div_disable(struct clk_hw *hw)
0103 {
0104 struct berlin2_div *div = to_berlin2_div(hw);
0105 struct berlin2_div_map *map = &div->map;
0106 u32 reg;
0107
0108 if (div->lock)
0109 spin_lock(div->lock);
0110
0111 reg = readl_relaxed(div->base + map->gate_offs);
0112 reg &= ~BIT(map->gate_shift);
0113 writel_relaxed(reg, div->base + map->gate_offs);
0114
0115 if (div->lock)
0116 spin_unlock(div->lock);
0117 }
0118
0119 static int berlin2_div_set_parent(struct clk_hw *hw, u8 index)
0120 {
0121 struct berlin2_div *div = to_berlin2_div(hw);
0122 struct berlin2_div_map *map = &div->map;
0123 u32 reg;
0124
0125 if (div->lock)
0126 spin_lock(div->lock);
0127
0128
0129 reg = readl_relaxed(div->base + map->pll_switch_offs);
0130 if (index == 0)
0131 reg &= ~BIT(map->pll_switch_shift);
0132 else
0133 reg |= BIT(map->pll_switch_shift);
0134 writel_relaxed(reg, div->base + map->pll_switch_offs);
0135
0136
0137 if (index > 0) {
0138 reg = readl_relaxed(div->base + map->pll_select_offs);
0139 reg &= ~(PLL_SELECT_MASK << map->pll_select_shift);
0140 reg |= (index - 1) << map->pll_select_shift;
0141 writel_relaxed(reg, div->base + map->pll_select_offs);
0142 }
0143
0144 if (div->lock)
0145 spin_unlock(div->lock);
0146
0147 return 0;
0148 }
0149
0150 static u8 berlin2_div_get_parent(struct clk_hw *hw)
0151 {
0152 struct berlin2_div *div = to_berlin2_div(hw);
0153 struct berlin2_div_map *map = &div->map;
0154 u32 reg;
0155 u8 index = 0;
0156
0157 if (div->lock)
0158 spin_lock(div->lock);
0159
0160
0161 reg = readl_relaxed(div->base + map->pll_switch_offs);
0162 reg &= BIT(map->pll_switch_shift);
0163 if (reg) {
0164 reg = readl_relaxed(div->base + map->pll_select_offs);
0165 reg >>= map->pll_select_shift;
0166 reg &= PLL_SELECT_MASK;
0167 index = 1 + reg;
0168 }
0169
0170 if (div->lock)
0171 spin_unlock(div->lock);
0172
0173 return index;
0174 }
0175
0176 static unsigned long berlin2_div_recalc_rate(struct clk_hw *hw,
0177 unsigned long parent_rate)
0178 {
0179 struct berlin2_div *div = to_berlin2_div(hw);
0180 struct berlin2_div_map *map = &div->map;
0181 u32 divsw, div3sw, divider = 1;
0182
0183 if (div->lock)
0184 spin_lock(div->lock);
0185
0186 divsw = readl_relaxed(div->base + map->div_switch_offs) &
0187 (1 << map->div_switch_shift);
0188 div3sw = readl_relaxed(div->base + map->div3_switch_offs) &
0189 (1 << map->div3_switch_shift);
0190
0191
0192 if (div3sw != 0) {
0193 divider = 3;
0194
0195 } else if (divsw == 0) {
0196 divider = 1;
0197
0198 } else {
0199 u32 reg;
0200 reg = readl_relaxed(div->base + map->div_select_offs);
0201 reg >>= map->div_select_shift;
0202 reg &= DIV_SELECT_MASK;
0203 divider = clk_div[reg];
0204 }
0205
0206 if (div->lock)
0207 spin_unlock(div->lock);
0208
0209 return parent_rate / divider;
0210 }
0211
0212 static const struct clk_ops berlin2_div_rate_ops = {
0213 .recalc_rate = berlin2_div_recalc_rate,
0214 };
0215
0216 static const struct clk_ops berlin2_div_gate_ops = {
0217 .is_enabled = berlin2_div_is_enabled,
0218 .enable = berlin2_div_enable,
0219 .disable = berlin2_div_disable,
0220 };
0221
0222 static const struct clk_ops berlin2_div_mux_ops = {
0223 .set_parent = berlin2_div_set_parent,
0224 .get_parent = berlin2_div_get_parent,
0225 };
0226
0227 struct clk_hw * __init
0228 berlin2_div_register(const struct berlin2_div_map *map,
0229 void __iomem *base, const char *name, u8 div_flags,
0230 const char **parent_names, int num_parents,
0231 unsigned long flags, spinlock_t *lock)
0232 {
0233 const struct clk_ops *mux_ops = &berlin2_div_mux_ops;
0234 const struct clk_ops *rate_ops = &berlin2_div_rate_ops;
0235 const struct clk_ops *gate_ops = &berlin2_div_gate_ops;
0236 struct berlin2_div *div;
0237
0238 div = kzalloc(sizeof(*div), GFP_KERNEL);
0239 if (!div)
0240 return ERR_PTR(-ENOMEM);
0241
0242
0243 memcpy(&div->map, map, sizeof(*map));
0244 div->base = base;
0245 div->lock = lock;
0246
0247 if ((div_flags & BERLIN2_DIV_HAS_GATE) == 0)
0248 gate_ops = NULL;
0249 if ((div_flags & BERLIN2_DIV_HAS_MUX) == 0)
0250 mux_ops = NULL;
0251
0252 return clk_hw_register_composite(NULL, name, parent_names, num_parents,
0253 &div->hw, mux_ops, &div->hw, rate_ops,
0254 &div->hw, gate_ops, flags);
0255 }