1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2016 Maxime Ripard 4 * 5 * Maxime Ripard <maxime.ripard@free-electrons.com> 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/clk-provider.h> 10 #include <linux/device.h> 11 #include <linux/iopoll.h> 12 #include <linux/module.h> 13 #include <linux/slab.h> 14 15 #include "ccu_common.h" 16 #include "ccu_gate.h" 17 #include "ccu_reset.h" 18 19 struct sunxi_ccu { 20 const struct sunxi_ccu_desc *desc; 21 spinlock_t lock; 22 struct ccu_reset reset; 23 }; 24 25 void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) 26 { 27 void __iomem *addr; 28 u32 reg; 29 30 if (!lock) 31 return; 32 33 if (common->features & CCU_FEATURE_LOCK_REG) 34 addr = common->base + common->lock_reg; 35 else 36 addr = common->base + common->reg; 37 38 WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000)); 39 } 40 EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, SUNXI_CCU); 41 42 bool ccu_is_better_rate(struct ccu_common *common, 43 unsigned long target_rate, 44 unsigned long current_rate, 45 unsigned long best_rate) 46 { 47 unsigned long min_rate, max_rate; 48 49 clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate); 50 51 if (current_rate > max_rate) 52 return false; 53 54 if (current_rate < min_rate) 55 return false; 56 57 if (common->features & CCU_FEATURE_CLOSEST_RATE) 58 return abs(current_rate - target_rate) < abs(best_rate - target_rate); 59 60 return current_rate <= target_rate && current_rate > best_rate; 61 } 62 EXPORT_SYMBOL_NS_GPL(ccu_is_better_rate, SUNXI_CCU); 63 64 /* 65 * This clock notifier is called when the frequency of a PLL clock is 66 * changed. In common PLL designs, changes to the dividers take effect 67 * almost immediately, while changes to the multipliers (implemented 68 * as dividers in the feedback loop) take a few cycles to work into 69 * the feedback loop for the PLL to stablize. 70 * 71 * Sometimes when the PLL clock rate is changed, the decrease in the 72 * divider is too much for the decrease in the multiplier to catch up. 73 * The PLL clock rate will spike, and in some cases, might lock up 74 * completely. 75 * 76 * This notifier callback will gate and then ungate the clock, 77 * effectively resetting it, so it proceeds to work. Care must be 78 * taken to reparent consumers to other temporary clocks during the 79 * rate change, and that this notifier callback must be the first 80 * to be registered. 81 */ 82 static int ccu_pll_notifier_cb(struct notifier_block *nb, 83 unsigned long event, void *data) 84 { 85 struct ccu_pll_nb *pll = to_ccu_pll_nb(nb); 86 int ret = 0; 87 88 if (event != POST_RATE_CHANGE) 89 goto out; 90 91 ccu_gate_helper_disable(pll->common, pll->enable); 92 93 ret = ccu_gate_helper_enable(pll->common, pll->enable); 94 if (ret) 95 goto out; 96 97 ccu_helper_wait_for_lock(pll->common, pll->lock); 98 99 out: 100 return notifier_from_errno(ret); 101 } 102 103 int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb) 104 { 105 pll_nb->clk_nb.notifier_call = ccu_pll_notifier_cb; 106 107 return clk_notifier_register(pll_nb->common->hw.clk, 108 &pll_nb->clk_nb); 109 } 110 EXPORT_SYMBOL_NS_GPL(ccu_pll_notifier_register, SUNXI_CCU); 111 112 static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev, 113 struct device_node *node, void __iomem *reg, 114 const struct sunxi_ccu_desc *desc) 115 { 116 struct ccu_reset *reset; 117 int i, ret; 118 119 ccu->desc = desc; 120 121 spin_lock_init(&ccu->lock); 122 123 for (i = 0; i < desc->num_ccu_clks; i++) { 124 struct ccu_common *cclk = desc->ccu_clks[i]; 125 126 if (!cclk) 127 continue; 128 129 cclk->base = reg; 130 cclk->lock = &ccu->lock; 131 } 132 133 for (i = 0; i < desc->hw_clks->num ; i++) { 134 struct clk_hw *hw = desc->hw_clks->hws[i]; 135 const char *name; 136 137 if (!hw) 138 continue; 139 140 name = hw->init->name; 141 if (dev) 142 ret = clk_hw_register(dev, hw); 143 else 144 ret = of_clk_hw_register(node, hw); 145 if (ret) { 146 pr_err("Couldn't register clock %d - %s\n", i, name); 147 goto err_clk_unreg; 148 } 149 } 150 151 for (i = 0; i < desc->num_ccu_clks; i++) { 152 struct ccu_common *cclk = desc->ccu_clks[i]; 153 154 if (!cclk) 155 continue; 156 157 if (cclk->max_rate) 158 clk_hw_set_rate_range(&cclk->hw, cclk->min_rate, 159 cclk->max_rate); 160 else 161 WARN(cclk->min_rate, 162 "No max_rate, ignoring min_rate of clock %d - %s\n", 163 i, clk_hw_get_name(&cclk->hw)); 164 } 165 166 ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, 167 desc->hw_clks); 168 if (ret) 169 goto err_clk_unreg; 170 171 reset = &ccu->reset; 172 reset->rcdev.of_node = node; 173 reset->rcdev.ops = &ccu_reset_ops; 174 reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE; 175 reset->rcdev.nr_resets = desc->num_resets; 176 reset->base = reg; 177 reset->lock = &ccu->lock; 178 reset->reset_map = desc->resets; 179 180 ret = reset_controller_register(&reset->rcdev); 181 if (ret) 182 goto err_del_provider; 183 184 return 0; 185 186 err_del_provider: 187 of_clk_del_provider(node); 188 err_clk_unreg: 189 while (--i >= 0) { 190 struct clk_hw *hw = desc->hw_clks->hws[i]; 191 192 if (!hw) 193 continue; 194 clk_hw_unregister(hw); 195 } 196 return ret; 197 } 198 199 static void devm_sunxi_ccu_release(struct device *dev, void *res) 200 { 201 struct sunxi_ccu *ccu = res; 202 const struct sunxi_ccu_desc *desc = ccu->desc; 203 int i; 204 205 reset_controller_unregister(&ccu->reset.rcdev); 206 of_clk_del_provider(dev->of_node); 207 208 for (i = 0; i < desc->hw_clks->num; i++) { 209 struct clk_hw *hw = desc->hw_clks->hws[i]; 210 211 if (!hw) 212 continue; 213 clk_hw_unregister(hw); 214 } 215 } 216 217 int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, 218 const struct sunxi_ccu_desc *desc) 219 { 220 struct sunxi_ccu *ccu; 221 int ret; 222 223 ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL); 224 if (!ccu) 225 return -ENOMEM; 226 227 ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc); 228 if (ret) { 229 devres_free(ccu); 230 return ret; 231 } 232 233 devres_add(dev, ccu); 234 235 return 0; 236 } 237 EXPORT_SYMBOL_NS_GPL(devm_sunxi_ccu_probe, SUNXI_CCU); 238 239 void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, 240 const struct sunxi_ccu_desc *desc) 241 { 242 struct sunxi_ccu *ccu; 243 int ret; 244 245 ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); 246 if (!ccu) 247 return; 248 249 ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc); 250 if (ret) { 251 pr_err("%pOF: probing clocks failed: %d\n", node, ret); 252 kfree(ccu); 253 } 254 } 255 256 MODULE_DESCRIPTION("Common clock support for Allwinner SoCs"); 257 MODULE_LICENSE("GPL"); 258