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 struct ccu_common *common = hw_to_ccu_common(hw); 136 const char *name; 137 138 if (!hw) 139 continue; 140 141 name = hw->init->name; 142 if (dev) 143 ret = clk_hw_register(dev, hw); 144 else 145 ret = of_clk_hw_register(node, hw); 146 if (ret) { 147 pr_err("Couldn't register clock %d - %s\n", i, name); 148 goto err_clk_unreg; 149 } 150 151 if (common->max_rate) 152 clk_hw_set_rate_range(hw, common->min_rate, 153 common->max_rate); 154 else 155 WARN(common->min_rate, 156 "No max_rate, ignoring min_rate of clock %d - %s\n", 157 i, name); 158 } 159 160 ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, 161 desc->hw_clks); 162 if (ret) 163 goto err_clk_unreg; 164 165 reset = &ccu->reset; 166 reset->rcdev.of_node = node; 167 reset->rcdev.ops = &ccu_reset_ops; 168 reset->rcdev.owner = dev ? dev->driver->owner : THIS_MODULE; 169 reset->rcdev.nr_resets = desc->num_resets; 170 reset->base = reg; 171 reset->lock = &ccu->lock; 172 reset->reset_map = desc->resets; 173 174 ret = reset_controller_register(&reset->rcdev); 175 if (ret) 176 goto err_del_provider; 177 178 return 0; 179 180 err_del_provider: 181 of_clk_del_provider(node); 182 err_clk_unreg: 183 while (--i >= 0) { 184 struct clk_hw *hw = desc->hw_clks->hws[i]; 185 186 if (!hw) 187 continue; 188 clk_hw_unregister(hw); 189 } 190 return ret; 191 } 192 193 static void devm_sunxi_ccu_release(struct device *dev, void *res) 194 { 195 struct sunxi_ccu *ccu = res; 196 const struct sunxi_ccu_desc *desc = ccu->desc; 197 int i; 198 199 reset_controller_unregister(&ccu->reset.rcdev); 200 of_clk_del_provider(dev->of_node); 201 202 for (i = 0; i < desc->hw_clks->num; i++) { 203 struct clk_hw *hw = desc->hw_clks->hws[i]; 204 205 if (!hw) 206 continue; 207 clk_hw_unregister(hw); 208 } 209 } 210 211 int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg, 212 const struct sunxi_ccu_desc *desc) 213 { 214 struct sunxi_ccu *ccu; 215 int ret; 216 217 ccu = devres_alloc(devm_sunxi_ccu_release, sizeof(*ccu), GFP_KERNEL); 218 if (!ccu) 219 return -ENOMEM; 220 221 ret = sunxi_ccu_probe(ccu, dev, dev->of_node, reg, desc); 222 if (ret) { 223 devres_free(ccu); 224 return ret; 225 } 226 227 devres_add(dev, ccu); 228 229 return 0; 230 } 231 EXPORT_SYMBOL_NS_GPL(devm_sunxi_ccu_probe, SUNXI_CCU); 232 233 void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg, 234 const struct sunxi_ccu_desc *desc) 235 { 236 struct sunxi_ccu *ccu; 237 int ret; 238 239 ccu = kzalloc(sizeof(*ccu), GFP_KERNEL); 240 if (!ccu) 241 return; 242 243 ret = sunxi_ccu_probe(ccu, NULL, node, reg, desc); 244 if (ret) { 245 pr_err("%pOF: probing clocks failed: %d\n", node, ret); 246 kfree(ccu); 247 } 248 } 249 250 MODULE_DESCRIPTION("Common clock support for Allwinner SoCs"); 251 MODULE_LICENSE("GPL"); 252