18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Register map access API - MMIO support 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/clk.h> 88c2ecf20Sopenharmony_ci#include <linux/err.h> 98c2ecf20Sopenharmony_ci#include <linux/io.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/regmap.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "internal.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistruct regmap_mmio_context { 178c2ecf20Sopenharmony_ci void __iomem *regs; 188c2ecf20Sopenharmony_ci unsigned val_bytes; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci bool attached_clk; 218c2ecf20Sopenharmony_ci struct clk *clk; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci void (*reg_write)(struct regmap_mmio_context *ctx, 248c2ecf20Sopenharmony_ci unsigned int reg, unsigned int val); 258c2ecf20Sopenharmony_ci unsigned int (*reg_read)(struct regmap_mmio_context *ctx, 268c2ecf20Sopenharmony_ci unsigned int reg); 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic int regmap_mmio_regbits_check(size_t reg_bits) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci switch (reg_bits) { 328c2ecf20Sopenharmony_ci case 8: 338c2ecf20Sopenharmony_ci case 16: 348c2ecf20Sopenharmony_ci case 32: 358c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 368c2ecf20Sopenharmony_ci case 64: 378c2ecf20Sopenharmony_ci#endif 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci default: 408c2ecf20Sopenharmony_ci return -EINVAL; 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic int regmap_mmio_get_min_stride(size_t val_bits) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci int min_stride; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci switch (val_bits) { 498c2ecf20Sopenharmony_ci case 8: 508c2ecf20Sopenharmony_ci /* The core treats 0 as 1 */ 518c2ecf20Sopenharmony_ci min_stride = 0; 528c2ecf20Sopenharmony_ci return 0; 538c2ecf20Sopenharmony_ci case 16: 548c2ecf20Sopenharmony_ci min_stride = 2; 558c2ecf20Sopenharmony_ci break; 568c2ecf20Sopenharmony_ci case 32: 578c2ecf20Sopenharmony_ci min_stride = 4; 588c2ecf20Sopenharmony_ci break; 598c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 608c2ecf20Sopenharmony_ci case 64: 618c2ecf20Sopenharmony_ci min_stride = 8; 628c2ecf20Sopenharmony_ci break; 638c2ecf20Sopenharmony_ci#endif 648c2ecf20Sopenharmony_ci default: 658c2ecf20Sopenharmony_ci return -EINVAL; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return min_stride; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic void regmap_mmio_write8(struct regmap_mmio_context *ctx, 728c2ecf20Sopenharmony_ci unsigned int reg, 738c2ecf20Sopenharmony_ci unsigned int val) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci writeb(val, ctx->regs + reg); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic void regmap_mmio_write16le(struct regmap_mmio_context *ctx, 798c2ecf20Sopenharmony_ci unsigned int reg, 808c2ecf20Sopenharmony_ci unsigned int val) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci writew(val, ctx->regs + reg); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic void regmap_mmio_write16be(struct regmap_mmio_context *ctx, 868c2ecf20Sopenharmony_ci unsigned int reg, 878c2ecf20Sopenharmony_ci unsigned int val) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci iowrite16be(val, ctx->regs + reg); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic void regmap_mmio_write32le(struct regmap_mmio_context *ctx, 938c2ecf20Sopenharmony_ci unsigned int reg, 948c2ecf20Sopenharmony_ci unsigned int val) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci writel(val, ctx->regs + reg); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void regmap_mmio_write32be(struct regmap_mmio_context *ctx, 1008c2ecf20Sopenharmony_ci unsigned int reg, 1018c2ecf20Sopenharmony_ci unsigned int val) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci iowrite32be(val, ctx->regs + reg); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 1078c2ecf20Sopenharmony_cistatic void regmap_mmio_write64le(struct regmap_mmio_context *ctx, 1088c2ecf20Sopenharmony_ci unsigned int reg, 1098c2ecf20Sopenharmony_ci unsigned int val) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci writeq(val, ctx->regs + reg); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci#endif 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx = context; 1188c2ecf20Sopenharmony_ci int ret; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci if (!IS_ERR(ctx->clk)) { 1218c2ecf20Sopenharmony_ci ret = clk_enable(ctx->clk); 1228c2ecf20Sopenharmony_ci if (ret < 0) 1238c2ecf20Sopenharmony_ci return ret; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci ctx->reg_write(ctx, reg, val); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (!IS_ERR(ctx->clk)) 1298c2ecf20Sopenharmony_ci clk_disable(ctx->clk); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return 0; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, 1358c2ecf20Sopenharmony_ci unsigned int reg) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci return readb(ctx->regs + reg); 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, 1418c2ecf20Sopenharmony_ci unsigned int reg) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci return readw(ctx->regs + reg); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, 1478c2ecf20Sopenharmony_ci unsigned int reg) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci return ioread16be(ctx->regs + reg); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, 1538c2ecf20Sopenharmony_ci unsigned int reg) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci return readl(ctx->regs + reg); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, 1598c2ecf20Sopenharmony_ci unsigned int reg) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci return ioread32be(ctx->regs + reg); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 1658c2ecf20Sopenharmony_cistatic unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, 1668c2ecf20Sopenharmony_ci unsigned int reg) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci return readq(ctx->regs + reg); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci#endif 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx = context; 1758c2ecf20Sopenharmony_ci int ret; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci if (!IS_ERR(ctx->clk)) { 1788c2ecf20Sopenharmony_ci ret = clk_enable(ctx->clk); 1798c2ecf20Sopenharmony_ci if (ret < 0) 1808c2ecf20Sopenharmony_ci return ret; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci *val = ctx->reg_read(ctx, reg); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (!IS_ERR(ctx->clk)) 1868c2ecf20Sopenharmony_ci clk_disable(ctx->clk); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic void regmap_mmio_free_context(void *context) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx = context; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (!IS_ERR(ctx->clk)) { 1968c2ecf20Sopenharmony_ci clk_unprepare(ctx->clk); 1978c2ecf20Sopenharmony_ci if (!ctx->attached_clk) 1988c2ecf20Sopenharmony_ci clk_put(ctx->clk); 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci kfree(context); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic const struct regmap_bus regmap_mmio = { 2048c2ecf20Sopenharmony_ci .fast_io = true, 2058c2ecf20Sopenharmony_ci .reg_write = regmap_mmio_write, 2068c2ecf20Sopenharmony_ci .reg_read = regmap_mmio_read, 2078c2ecf20Sopenharmony_ci .free_context = regmap_mmio_free_context, 2088c2ecf20Sopenharmony_ci .val_format_endian_default = REGMAP_ENDIAN_LITTLE, 2098c2ecf20Sopenharmony_ci}; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, 2128c2ecf20Sopenharmony_ci const char *clk_id, 2138c2ecf20Sopenharmony_ci void __iomem *regs, 2148c2ecf20Sopenharmony_ci const struct regmap_config *config) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx; 2178c2ecf20Sopenharmony_ci int min_stride; 2188c2ecf20Sopenharmony_ci int ret; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci ret = regmap_mmio_regbits_check(config->reg_bits); 2218c2ecf20Sopenharmony_ci if (ret) 2228c2ecf20Sopenharmony_ci return ERR_PTR(ret); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci if (config->pad_bits) 2258c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci min_stride = regmap_mmio_get_min_stride(config->val_bits); 2288c2ecf20Sopenharmony_ci if (min_stride < 0) 2298c2ecf20Sopenharmony_ci return ERR_PTR(min_stride); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (config->reg_stride < min_stride) 2328c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 2358c2ecf20Sopenharmony_ci if (!ctx) 2368c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci ctx->regs = regs; 2398c2ecf20Sopenharmony_ci ctx->val_bytes = config->val_bits / 8; 2408c2ecf20Sopenharmony_ci ctx->clk = ERR_PTR(-ENODEV); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci switch (regmap_get_val_endian(dev, ®map_mmio, config)) { 2438c2ecf20Sopenharmony_ci case REGMAP_ENDIAN_DEFAULT: 2448c2ecf20Sopenharmony_ci case REGMAP_ENDIAN_LITTLE: 2458c2ecf20Sopenharmony_ci#ifdef __LITTLE_ENDIAN 2468c2ecf20Sopenharmony_ci case REGMAP_ENDIAN_NATIVE: 2478c2ecf20Sopenharmony_ci#endif 2488c2ecf20Sopenharmony_ci switch (config->val_bits) { 2498c2ecf20Sopenharmony_ci case 8: 2508c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read8; 2518c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write8; 2528c2ecf20Sopenharmony_ci break; 2538c2ecf20Sopenharmony_ci case 16: 2548c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read16le; 2558c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write16le; 2568c2ecf20Sopenharmony_ci break; 2578c2ecf20Sopenharmony_ci case 32: 2588c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read32le; 2598c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write32le; 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 2628c2ecf20Sopenharmony_ci case 64: 2638c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read64le; 2648c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write64le; 2658c2ecf20Sopenharmony_ci break; 2668c2ecf20Sopenharmony_ci#endif 2678c2ecf20Sopenharmony_ci default: 2688c2ecf20Sopenharmony_ci ret = -EINVAL; 2698c2ecf20Sopenharmony_ci goto err_free; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci break; 2728c2ecf20Sopenharmony_ci case REGMAP_ENDIAN_BIG: 2738c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN 2748c2ecf20Sopenharmony_ci case REGMAP_ENDIAN_NATIVE: 2758c2ecf20Sopenharmony_ci#endif 2768c2ecf20Sopenharmony_ci switch (config->val_bits) { 2778c2ecf20Sopenharmony_ci case 8: 2788c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read8; 2798c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write8; 2808c2ecf20Sopenharmony_ci break; 2818c2ecf20Sopenharmony_ci case 16: 2828c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read16be; 2838c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write16be; 2848c2ecf20Sopenharmony_ci break; 2858c2ecf20Sopenharmony_ci case 32: 2868c2ecf20Sopenharmony_ci ctx->reg_read = regmap_mmio_read32be; 2878c2ecf20Sopenharmony_ci ctx->reg_write = regmap_mmio_write32be; 2888c2ecf20Sopenharmony_ci break; 2898c2ecf20Sopenharmony_ci default: 2908c2ecf20Sopenharmony_ci ret = -EINVAL; 2918c2ecf20Sopenharmony_ci goto err_free; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci break; 2948c2ecf20Sopenharmony_ci default: 2958c2ecf20Sopenharmony_ci ret = -EINVAL; 2968c2ecf20Sopenharmony_ci goto err_free; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (clk_id == NULL) 3008c2ecf20Sopenharmony_ci return ctx; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci ctx->clk = clk_get(dev, clk_id); 3038c2ecf20Sopenharmony_ci if (IS_ERR(ctx->clk)) { 3048c2ecf20Sopenharmony_ci ret = PTR_ERR(ctx->clk); 3058c2ecf20Sopenharmony_ci goto err_free; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci ret = clk_prepare(ctx->clk); 3098c2ecf20Sopenharmony_ci if (ret < 0) { 3108c2ecf20Sopenharmony_ci clk_put(ctx->clk); 3118c2ecf20Sopenharmony_ci goto err_free; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci return ctx; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cierr_free: 3178c2ecf20Sopenharmony_ci kfree(ctx); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci return ERR_PTR(ret); 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistruct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id, 3238c2ecf20Sopenharmony_ci void __iomem *regs, 3248c2ecf20Sopenharmony_ci const struct regmap_config *config, 3258c2ecf20Sopenharmony_ci struct lock_class_key *lock_key, 3268c2ecf20Sopenharmony_ci const char *lock_name) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); 3318c2ecf20Sopenharmony_ci if (IS_ERR(ctx)) 3328c2ecf20Sopenharmony_ci return ERR_CAST(ctx); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci return __regmap_init(dev, ®map_mmio, ctx, config, 3358c2ecf20Sopenharmony_ci lock_key, lock_name); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__regmap_init_mmio_clk); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistruct regmap *__devm_regmap_init_mmio_clk(struct device *dev, 3408c2ecf20Sopenharmony_ci const char *clk_id, 3418c2ecf20Sopenharmony_ci void __iomem *regs, 3428c2ecf20Sopenharmony_ci const struct regmap_config *config, 3438c2ecf20Sopenharmony_ci struct lock_class_key *lock_key, 3448c2ecf20Sopenharmony_ci const char *lock_name) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); 3498c2ecf20Sopenharmony_ci if (IS_ERR(ctx)) 3508c2ecf20Sopenharmony_ci return ERR_CAST(ctx); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return __devm_regmap_init(dev, ®map_mmio, ctx, config, 3538c2ecf20Sopenharmony_ci lock_key, lock_name); 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ciint regmap_mmio_attach_clk(struct regmap *map, struct clk *clk) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx = map->bus_context; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci ctx->clk = clk; 3628c2ecf20Sopenharmony_ci ctx->attached_clk = true; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return clk_prepare(ctx->clk); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regmap_mmio_attach_clk); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_civoid regmap_mmio_detach_clk(struct regmap *map) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct regmap_mmio_context *ctx = map->bus_context; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci clk_unprepare(ctx->clk); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci ctx->attached_clk = false; 3758c2ecf20Sopenharmony_ci ctx->clk = NULL; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(regmap_mmio_detach_clk); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 380