xref: /OK3568_Linux_fs/kernel/drivers/base/regmap/regmap-mmio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Register map access API - MMIO support
4*4882a593Smuzhiyun //
5*4882a593Smuzhiyun // Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/clk.h>
8*4882a593Smuzhiyun #include <linux/err.h>
9*4882a593Smuzhiyun #include <linux/io.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/regmap.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include "internal.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun struct regmap_mmio_context {
17*4882a593Smuzhiyun 	void __iomem *regs;
18*4882a593Smuzhiyun 	unsigned val_bytes;
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	bool attached_clk;
21*4882a593Smuzhiyun 	struct clk *clk;
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun 	void (*reg_write)(struct regmap_mmio_context *ctx,
24*4882a593Smuzhiyun 			  unsigned int reg, unsigned int val);
25*4882a593Smuzhiyun 	unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
26*4882a593Smuzhiyun 			         unsigned int reg);
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
regmap_mmio_regbits_check(size_t reg_bits)29*4882a593Smuzhiyun static int regmap_mmio_regbits_check(size_t reg_bits)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	switch (reg_bits) {
32*4882a593Smuzhiyun 	case 8:
33*4882a593Smuzhiyun 	case 16:
34*4882a593Smuzhiyun 	case 32:
35*4882a593Smuzhiyun #ifdef CONFIG_64BIT
36*4882a593Smuzhiyun 	case 64:
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun 		return 0;
39*4882a593Smuzhiyun 	default:
40*4882a593Smuzhiyun 		return -EINVAL;
41*4882a593Smuzhiyun 	}
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun 
regmap_mmio_get_min_stride(size_t val_bits)44*4882a593Smuzhiyun static int regmap_mmio_get_min_stride(size_t val_bits)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun 	int min_stride;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	switch (val_bits) {
49*4882a593Smuzhiyun 	case 8:
50*4882a593Smuzhiyun 		/* The core treats 0 as 1 */
51*4882a593Smuzhiyun 		min_stride = 0;
52*4882a593Smuzhiyun 		return 0;
53*4882a593Smuzhiyun 	case 16:
54*4882a593Smuzhiyun 		min_stride = 2;
55*4882a593Smuzhiyun 		break;
56*4882a593Smuzhiyun 	case 32:
57*4882a593Smuzhiyun 		min_stride = 4;
58*4882a593Smuzhiyun 		break;
59*4882a593Smuzhiyun #ifdef CONFIG_64BIT
60*4882a593Smuzhiyun 	case 64:
61*4882a593Smuzhiyun 		min_stride = 8;
62*4882a593Smuzhiyun 		break;
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun 	default:
65*4882a593Smuzhiyun 		return -EINVAL;
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return min_stride;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
regmap_mmio_write8(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)71*4882a593Smuzhiyun static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
72*4882a593Smuzhiyun 				unsigned int reg,
73*4882a593Smuzhiyun 				unsigned int val)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	writeb(val, ctx->regs + reg);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
regmap_mmio_write16le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)78*4882a593Smuzhiyun static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
79*4882a593Smuzhiyun 				  unsigned int reg,
80*4882a593Smuzhiyun 				  unsigned int val)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	writew(val, ctx->regs + reg);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
regmap_mmio_write16be(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)85*4882a593Smuzhiyun static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
86*4882a593Smuzhiyun 				  unsigned int reg,
87*4882a593Smuzhiyun 				  unsigned int val)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	iowrite16be(val, ctx->regs + reg);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
regmap_mmio_write32le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)92*4882a593Smuzhiyun static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
93*4882a593Smuzhiyun 				  unsigned int reg,
94*4882a593Smuzhiyun 				  unsigned int val)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	writel(val, ctx->regs + reg);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
regmap_mmio_write32be(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)99*4882a593Smuzhiyun static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
100*4882a593Smuzhiyun 				  unsigned int reg,
101*4882a593Smuzhiyun 				  unsigned int val)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	iowrite32be(val, ctx->regs + reg);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun #ifdef CONFIG_64BIT
regmap_mmio_write64le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)107*4882a593Smuzhiyun static void regmap_mmio_write64le(struct regmap_mmio_context *ctx,
108*4882a593Smuzhiyun 				  unsigned int reg,
109*4882a593Smuzhiyun 				  unsigned int val)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	writeq(val, ctx->regs + reg);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun #endif
114*4882a593Smuzhiyun 
regmap_mmio_write(void * context,unsigned int reg,unsigned int val)115*4882a593Smuzhiyun static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx = context;
118*4882a593Smuzhiyun 	int ret;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	if (!IS_ERR(ctx->clk)) {
121*4882a593Smuzhiyun 		ret = clk_enable(ctx->clk);
122*4882a593Smuzhiyun 		if (ret < 0)
123*4882a593Smuzhiyun 			return ret;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	ctx->reg_write(ctx, reg, val);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	if (!IS_ERR(ctx->clk))
129*4882a593Smuzhiyun 		clk_disable(ctx->clk);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
regmap_mmio_read8(struct regmap_mmio_context * ctx,unsigned int reg)134*4882a593Smuzhiyun static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
135*4882a593Smuzhiyun 				      unsigned int reg)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	return readb(ctx->regs + reg);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
regmap_mmio_read16le(struct regmap_mmio_context * ctx,unsigned int reg)140*4882a593Smuzhiyun static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
141*4882a593Smuzhiyun 				         unsigned int reg)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	return readw(ctx->regs + reg);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
regmap_mmio_read16be(struct regmap_mmio_context * ctx,unsigned int reg)146*4882a593Smuzhiyun static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
147*4882a593Smuzhiyun 				         unsigned int reg)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	return ioread16be(ctx->regs + reg);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
regmap_mmio_read32le(struct regmap_mmio_context * ctx,unsigned int reg)152*4882a593Smuzhiyun static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
153*4882a593Smuzhiyun 				         unsigned int reg)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	return readl(ctx->regs + reg);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
regmap_mmio_read32be(struct regmap_mmio_context * ctx,unsigned int reg)158*4882a593Smuzhiyun static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
159*4882a593Smuzhiyun 				         unsigned int reg)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	return ioread32be(ctx->regs + reg);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun #ifdef CONFIG_64BIT
regmap_mmio_read64le(struct regmap_mmio_context * ctx,unsigned int reg)165*4882a593Smuzhiyun static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx,
166*4882a593Smuzhiyun 				         unsigned int reg)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun 	return readq(ctx->regs + reg);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun #endif
171*4882a593Smuzhiyun 
regmap_mmio_read(void * context,unsigned int reg,unsigned int * val)172*4882a593Smuzhiyun static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx = context;
175*4882a593Smuzhiyun 	int ret;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if (!IS_ERR(ctx->clk)) {
178*4882a593Smuzhiyun 		ret = clk_enable(ctx->clk);
179*4882a593Smuzhiyun 		if (ret < 0)
180*4882a593Smuzhiyun 			return ret;
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	*val = ctx->reg_read(ctx, reg);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	if (!IS_ERR(ctx->clk))
186*4882a593Smuzhiyun 		clk_disable(ctx->clk);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
regmap_mmio_free_context(void * context)191*4882a593Smuzhiyun static void regmap_mmio_free_context(void *context)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx = context;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	if (!IS_ERR(ctx->clk)) {
196*4882a593Smuzhiyun 		clk_unprepare(ctx->clk);
197*4882a593Smuzhiyun 		if (!ctx->attached_clk)
198*4882a593Smuzhiyun 			clk_put(ctx->clk);
199*4882a593Smuzhiyun 	}
200*4882a593Smuzhiyun 	kfree(context);
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun static const struct regmap_bus regmap_mmio = {
204*4882a593Smuzhiyun 	.fast_io = true,
205*4882a593Smuzhiyun 	.reg_write = regmap_mmio_write,
206*4882a593Smuzhiyun 	.reg_read = regmap_mmio_read,
207*4882a593Smuzhiyun 	.free_context = regmap_mmio_free_context,
208*4882a593Smuzhiyun 	.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
209*4882a593Smuzhiyun };
210*4882a593Smuzhiyun 
regmap_mmio_gen_context(struct device * dev,const char * clk_id,void __iomem * regs,const struct regmap_config * config)211*4882a593Smuzhiyun static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
212*4882a593Smuzhiyun 					const char *clk_id,
213*4882a593Smuzhiyun 					void __iomem *regs,
214*4882a593Smuzhiyun 					const struct regmap_config *config)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx;
217*4882a593Smuzhiyun 	int min_stride;
218*4882a593Smuzhiyun 	int ret;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	ret = regmap_mmio_regbits_check(config->reg_bits);
221*4882a593Smuzhiyun 	if (ret)
222*4882a593Smuzhiyun 		return ERR_PTR(ret);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	if (config->pad_bits)
225*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	min_stride = regmap_mmio_get_min_stride(config->val_bits);
228*4882a593Smuzhiyun 	if (min_stride < 0)
229*4882a593Smuzhiyun 		return ERR_PTR(min_stride);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	if (config->reg_stride < min_stride)
232*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
235*4882a593Smuzhiyun 	if (!ctx)
236*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	ctx->regs = regs;
239*4882a593Smuzhiyun 	ctx->val_bytes = config->val_bits / 8;
240*4882a593Smuzhiyun 	ctx->clk = ERR_PTR(-ENODEV);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	switch (regmap_get_val_endian(dev, &regmap_mmio, config)) {
243*4882a593Smuzhiyun 	case REGMAP_ENDIAN_DEFAULT:
244*4882a593Smuzhiyun 	case REGMAP_ENDIAN_LITTLE:
245*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN
246*4882a593Smuzhiyun 	case REGMAP_ENDIAN_NATIVE:
247*4882a593Smuzhiyun #endif
248*4882a593Smuzhiyun 		switch (config->val_bits) {
249*4882a593Smuzhiyun 		case 8:
250*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read8;
251*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write8;
252*4882a593Smuzhiyun 			break;
253*4882a593Smuzhiyun 		case 16:
254*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read16le;
255*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write16le;
256*4882a593Smuzhiyun 			break;
257*4882a593Smuzhiyun 		case 32:
258*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read32le;
259*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write32le;
260*4882a593Smuzhiyun 			break;
261*4882a593Smuzhiyun #ifdef CONFIG_64BIT
262*4882a593Smuzhiyun 		case 64:
263*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read64le;
264*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write64le;
265*4882a593Smuzhiyun 			break;
266*4882a593Smuzhiyun #endif
267*4882a593Smuzhiyun 		default:
268*4882a593Smuzhiyun 			ret = -EINVAL;
269*4882a593Smuzhiyun 			goto err_free;
270*4882a593Smuzhiyun 		}
271*4882a593Smuzhiyun 		break;
272*4882a593Smuzhiyun 	case REGMAP_ENDIAN_BIG:
273*4882a593Smuzhiyun #ifdef __BIG_ENDIAN
274*4882a593Smuzhiyun 	case REGMAP_ENDIAN_NATIVE:
275*4882a593Smuzhiyun #endif
276*4882a593Smuzhiyun 		switch (config->val_bits) {
277*4882a593Smuzhiyun 		case 8:
278*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read8;
279*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write8;
280*4882a593Smuzhiyun 			break;
281*4882a593Smuzhiyun 		case 16:
282*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read16be;
283*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write16be;
284*4882a593Smuzhiyun 			break;
285*4882a593Smuzhiyun 		case 32:
286*4882a593Smuzhiyun 			ctx->reg_read = regmap_mmio_read32be;
287*4882a593Smuzhiyun 			ctx->reg_write = regmap_mmio_write32be;
288*4882a593Smuzhiyun 			break;
289*4882a593Smuzhiyun 		default:
290*4882a593Smuzhiyun 			ret = -EINVAL;
291*4882a593Smuzhiyun 			goto err_free;
292*4882a593Smuzhiyun 		}
293*4882a593Smuzhiyun 		break;
294*4882a593Smuzhiyun 	default:
295*4882a593Smuzhiyun 		ret = -EINVAL;
296*4882a593Smuzhiyun 		goto err_free;
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	if (clk_id == NULL)
300*4882a593Smuzhiyun 		return ctx;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	ctx->clk = clk_get(dev, clk_id);
303*4882a593Smuzhiyun 	if (IS_ERR(ctx->clk)) {
304*4882a593Smuzhiyun 		ret = PTR_ERR(ctx->clk);
305*4882a593Smuzhiyun 		goto err_free;
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	ret = clk_prepare(ctx->clk);
309*4882a593Smuzhiyun 	if (ret < 0) {
310*4882a593Smuzhiyun 		clk_put(ctx->clk);
311*4882a593Smuzhiyun 		goto err_free;
312*4882a593Smuzhiyun 	}
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	return ctx;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun err_free:
317*4882a593Smuzhiyun 	kfree(ctx);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	return ERR_PTR(ret);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
__regmap_init_mmio_clk(struct device * dev,const char * clk_id,void __iomem * regs,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)322*4882a593Smuzhiyun struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
323*4882a593Smuzhiyun 				      void __iomem *regs,
324*4882a593Smuzhiyun 				      const struct regmap_config *config,
325*4882a593Smuzhiyun 				      struct lock_class_key *lock_key,
326*4882a593Smuzhiyun 				      const char *lock_name)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
331*4882a593Smuzhiyun 	if (IS_ERR(ctx))
332*4882a593Smuzhiyun 		return ERR_CAST(ctx);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	return __regmap_init(dev, &regmap_mmio, ctx, config,
335*4882a593Smuzhiyun 			     lock_key, lock_name);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk);
338*4882a593Smuzhiyun 
__devm_regmap_init_mmio_clk(struct device * dev,const char * clk_id,void __iomem * regs,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)339*4882a593Smuzhiyun struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
340*4882a593Smuzhiyun 					   const char *clk_id,
341*4882a593Smuzhiyun 					   void __iomem *regs,
342*4882a593Smuzhiyun 					   const struct regmap_config *config,
343*4882a593Smuzhiyun 					   struct lock_class_key *lock_key,
344*4882a593Smuzhiyun 					   const char *lock_name)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
349*4882a593Smuzhiyun 	if (IS_ERR(ctx))
350*4882a593Smuzhiyun 		return ERR_CAST(ctx);
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	return __devm_regmap_init(dev, &regmap_mmio, ctx, config,
353*4882a593Smuzhiyun 				  lock_key, lock_name);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
356*4882a593Smuzhiyun 
regmap_mmio_attach_clk(struct regmap * map,struct clk * clk)357*4882a593Smuzhiyun int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx = map->bus_context;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	ctx->clk = clk;
362*4882a593Smuzhiyun 	ctx->attached_clk = true;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	return clk_prepare(ctx->clk);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk);
367*4882a593Smuzhiyun 
regmap_mmio_detach_clk(struct regmap * map)368*4882a593Smuzhiyun void regmap_mmio_detach_clk(struct regmap *map)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	struct regmap_mmio_context *ctx = map->bus_context;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	clk_unprepare(ctx->clk);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	ctx->attached_clk = false;
375*4882a593Smuzhiyun 	ctx->clk = NULL;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
380