1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021 Linaro Ltd. 4 * Copyright (C) 2021 Dávid Virág <virag.david003@gmail.com> 5 * Author: Sam Protsenko <semen.protsenko@linaro.org> 6 * Author: Dávid Virág <virag.david003@gmail.com> 7 * 8 * This file contains shared functions used by some arm64 Exynos SoCs, 9 * such as Exynos7885 or Exynos850 to register and init CMUs. 10 */ 11 #include <linux/clk.h> 12 #include <linux/of_address.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/slab.h> 17 18 #include "clk-exynos-arm64.h" 19 20 /* PLL register bits */ 21 #define PLL_CON1_MANUAL BIT(1) 22 23 /* Gate register bits */ 24 #define GATE_MANUAL BIT(20) 25 #define GATE_ENABLE_HWACG BIT(28) 26 27 /* PLL_CONx_PLL register offsets range */ 28 #define PLL_CON_OFF_START 0x100 29 #define PLL_CON_OFF_END 0x600 30 31 /* Gate register offsets range */ 32 #define GATE_OFF_START 0x2000 33 #define GATE_OFF_END 0x2fff 34 35 struct exynos_arm64_cmu_data { 36 struct samsung_clk_reg_dump *clk_save; 37 unsigned int nr_clk_save; 38 const struct samsung_clk_reg_dump *clk_suspend; 39 unsigned int nr_clk_suspend; 40 41 struct clk *clk; 42 struct clk **pclks; 43 int nr_pclks; 44 45 struct samsung_clk_provider *ctx; 46 }; 47 48 /* Check if the register offset is a GATE register */ 49 static bool is_gate_reg(unsigned long off) 50 { 51 return off >= GATE_OFF_START && off <= GATE_OFF_END; 52 } 53 54 /* Check if the register offset is a PLL_CONx register */ 55 static bool is_pll_conx_reg(unsigned long off) 56 { 57 return off >= PLL_CON_OFF_START && off <= PLL_CON_OFF_END; 58 } 59 60 /* Check if the register offset is a PLL_CON1 register */ 61 static bool is_pll_con1_reg(unsigned long off) 62 { 63 return is_pll_conx_reg(off) && (off & 0xf) == 0x4 && !(off & 0x10); 64 } 65 66 /** 67 * exynos_arm64_init_clocks - Set clocks initial configuration 68 * @np: CMU device tree node with "reg" property (CMU addr) 69 * @cmu: CMU data 70 * 71 * Set manual control mode for all gate and PLL clocks. 72 */ 73 static void __init exynos_arm64_init_clocks(struct device_node *np, 74 const struct samsung_cmu_info *cmu) 75 { 76 const unsigned long *reg_offs = cmu->clk_regs; 77 size_t reg_offs_len = cmu->nr_clk_regs; 78 void __iomem *reg_base; 79 size_t i; 80 81 reg_base = of_iomap(np, 0); 82 if (!reg_base) 83 panic("%s: failed to map registers\n", __func__); 84 85 for (i = 0; i < reg_offs_len; ++i) { 86 void __iomem *reg = reg_base + reg_offs[i]; 87 u32 val; 88 89 if (cmu->manual_plls && is_pll_con1_reg(reg_offs[i])) { 90 writel(PLL_CON1_MANUAL, reg); 91 } else if (is_gate_reg(reg_offs[i])) { 92 val = readl(reg); 93 val |= GATE_MANUAL; 94 val &= ~GATE_ENABLE_HWACG; 95 writel(val, reg); 96 } 97 } 98 99 iounmap(reg_base); 100 } 101 102 /** 103 * exynos_arm64_enable_bus_clk - Enable parent clock of specified CMU 104 * 105 * @dev: Device object; may be NULL if this function is not being 106 * called from platform driver probe function 107 * @np: CMU device tree node 108 * @cmu: CMU data 109 * 110 * Keep CMU parent clock running (needed for CMU registers access). 111 * 112 * Return: 0 on success or a negative error code on failure. 113 */ 114 static int __init exynos_arm64_enable_bus_clk(struct device *dev, 115 struct device_node *np, const struct samsung_cmu_info *cmu) 116 { 117 struct clk *parent_clk; 118 119 if (!cmu->clk_name) 120 return 0; 121 122 if (dev) { 123 struct exynos_arm64_cmu_data *data; 124 125 parent_clk = clk_get(dev, cmu->clk_name); 126 data = dev_get_drvdata(dev); 127 if (data) 128 data->clk = parent_clk; 129 } else { 130 parent_clk = of_clk_get_by_name(np, cmu->clk_name); 131 } 132 133 if (IS_ERR(parent_clk)) 134 return PTR_ERR(parent_clk); 135 136 return clk_prepare_enable(parent_clk); 137 } 138 139 static int __init exynos_arm64_cmu_prepare_pm(struct device *dev, 140 const struct samsung_cmu_info *cmu) 141 { 142 struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev); 143 int i; 144 145 data->clk_save = samsung_clk_alloc_reg_dump(cmu->clk_regs, 146 cmu->nr_clk_regs); 147 if (!data->clk_save) 148 return -ENOMEM; 149 150 data->nr_clk_save = cmu->nr_clk_regs; 151 data->clk_suspend = cmu->suspend_regs; 152 data->nr_clk_suspend = cmu->nr_suspend_regs; 153 data->nr_pclks = of_clk_get_parent_count(dev->of_node); 154 if (!data->nr_pclks) 155 return 0; 156 157 data->pclks = devm_kcalloc(dev, sizeof(struct clk *), data->nr_pclks, 158 GFP_KERNEL); 159 if (!data->pclks) { 160 kfree(data->clk_save); 161 return -ENOMEM; 162 } 163 164 for (i = 0; i < data->nr_pclks; i++) { 165 struct clk *clk = of_clk_get(dev->of_node, i); 166 167 if (IS_ERR(clk)) { 168 kfree(data->clk_save); 169 while (--i >= 0) 170 clk_put(data->pclks[i]); 171 return PTR_ERR(clk); 172 } 173 data->pclks[i] = clk; 174 } 175 176 return 0; 177 } 178 179 /** 180 * exynos_arm64_register_cmu - Register specified Exynos CMU domain 181 * @dev: Device object; may be NULL if this function is not being 182 * called from platform driver probe function 183 * @np: CMU device tree node 184 * @cmu: CMU data 185 * 186 * Register specified CMU domain, which includes next steps: 187 * 188 * 1. Enable parent clock of @cmu CMU 189 * 2. Set initial registers configuration for @cmu CMU clocks 190 * 3. Register @cmu CMU clocks using Samsung clock framework API 191 */ 192 void __init exynos_arm64_register_cmu(struct device *dev, 193 struct device_node *np, const struct samsung_cmu_info *cmu) 194 { 195 int err; 196 197 /* 198 * Try to boot even if the parent clock enablement fails, as it might be 199 * already enabled by bootloader. 200 */ 201 err = exynos_arm64_enable_bus_clk(dev, np, cmu); 202 if (err) 203 pr_err("%s: could not enable bus clock %s; err = %d\n", 204 __func__, cmu->clk_name, err); 205 206 exynos_arm64_init_clocks(np, cmu); 207 samsung_cmu_register_one(np, cmu); 208 } 209 210 /** 211 * exynos_arm64_register_cmu_pm - Register Exynos CMU domain with PM support 212 * 213 * @pdev: Platform device object 214 * @set_manual: If true, set gate clocks to manual mode 215 * 216 * It's a version of exynos_arm64_register_cmu() with PM support. Should be 217 * called from probe function of platform driver. 218 * 219 * Return: 0 on success, or negative error code on error. 220 */ 221 int __init exynos_arm64_register_cmu_pm(struct platform_device *pdev, 222 bool set_manual) 223 { 224 const struct samsung_cmu_info *cmu; 225 struct device *dev = &pdev->dev; 226 struct device_node *np = dev->of_node; 227 struct exynos_arm64_cmu_data *data; 228 void __iomem *reg_base; 229 int ret; 230 231 cmu = of_device_get_match_data(dev); 232 233 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 234 if (!data) 235 return -ENOMEM; 236 237 platform_set_drvdata(pdev, data); 238 239 ret = exynos_arm64_cmu_prepare_pm(dev, cmu); 240 if (ret) 241 return ret; 242 243 /* 244 * Try to boot even if the parent clock enablement fails, as it might be 245 * already enabled by bootloader. 246 */ 247 ret = exynos_arm64_enable_bus_clk(dev, NULL, cmu); 248 if (ret) 249 dev_err(dev, "%s: could not enable bus clock %s; err = %d\n", 250 __func__, cmu->clk_name, ret); 251 252 if (set_manual) 253 exynos_arm64_init_clocks(np, cmu); 254 255 reg_base = devm_platform_ioremap_resource(pdev, 0); 256 if (IS_ERR(reg_base)) 257 return PTR_ERR(reg_base); 258 259 data->ctx = samsung_clk_init(dev, reg_base, cmu->nr_clk_ids); 260 261 /* 262 * Enable runtime PM here to allow the clock core using runtime PM 263 * for the registered clocks. Additionally, we increase the runtime 264 * PM usage count before registering the clocks, to prevent the 265 * clock core from runtime suspending the device. 266 */ 267 pm_runtime_get_noresume(dev); 268 pm_runtime_set_active(dev); 269 pm_runtime_enable(dev); 270 271 samsung_cmu_register_clocks(data->ctx, cmu); 272 samsung_clk_of_add_provider(dev->of_node, data->ctx); 273 pm_runtime_put_sync(dev); 274 275 return 0; 276 } 277 278 int exynos_arm64_cmu_suspend(struct device *dev) 279 { 280 struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev); 281 int i; 282 283 samsung_clk_save(data->ctx->reg_base, data->clk_save, 284 data->nr_clk_save); 285 286 for (i = 0; i < data->nr_pclks; i++) 287 clk_prepare_enable(data->pclks[i]); 288 289 /* For suspend some registers have to be set to certain values */ 290 samsung_clk_restore(data->ctx->reg_base, data->clk_suspend, 291 data->nr_clk_suspend); 292 293 for (i = 0; i < data->nr_pclks; i++) 294 clk_disable_unprepare(data->pclks[i]); 295 296 clk_disable_unprepare(data->clk); 297 298 return 0; 299 } 300 301 int exynos_arm64_cmu_resume(struct device *dev) 302 { 303 struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev); 304 int i; 305 306 clk_prepare_enable(data->clk); 307 308 for (i = 0; i < data->nr_pclks; i++) 309 clk_prepare_enable(data->pclks[i]); 310 311 samsung_clk_restore(data->ctx->reg_base, data->clk_save, 312 data->nr_clk_save); 313 314 for (i = 0; i < data->nr_pclks; i++) 315 clk_disable_unprepare(data->pclks[i]); 316 317 return 0; 318 } 319