1  // SPDX-License-Identifier: GPL-2.0
2  //
3  // Register map access API - MMIO support
4  //
5  // Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
6  
7  #include <linux/clk.h>
8  #include <linux/err.h>
9  #include <linux/io.h>
10  #include <linux/module.h>
11  #include <linux/regmap.h>
12  #include <linux/slab.h>
13  #include <linux/swab.h>
14  
15  #include "internal.h"
16  
17  struct regmap_mmio_context {
18  	void __iomem *regs;
19  	unsigned int val_bytes;
20  	bool big_endian;
21  
22  	bool attached_clk;
23  	struct clk *clk;
24  
25  	void (*reg_write)(struct regmap_mmio_context *ctx,
26  			  unsigned int reg, unsigned int val);
27  	unsigned int (*reg_read)(struct regmap_mmio_context *ctx,
28  			         unsigned int reg);
29  };
30  
regmap_mmio_regbits_check(size_t reg_bits)31  static int regmap_mmio_regbits_check(size_t reg_bits)
32  {
33  	switch (reg_bits) {
34  	case 8:
35  	case 16:
36  	case 32:
37  		return 0;
38  	default:
39  		return -EINVAL;
40  	}
41  }
42  
regmap_mmio_get_min_stride(size_t val_bits)43  static int regmap_mmio_get_min_stride(size_t val_bits)
44  {
45  	int min_stride;
46  
47  	switch (val_bits) {
48  	case 8:
49  		/* The core treats 0 as 1 */
50  		min_stride = 0;
51  		break;
52  	case 16:
53  		min_stride = 2;
54  		break;
55  	case 32:
56  		min_stride = 4;
57  		break;
58  	default:
59  		return -EINVAL;
60  	}
61  
62  	return min_stride;
63  }
64  
regmap_mmio_write8(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)65  static void regmap_mmio_write8(struct regmap_mmio_context *ctx,
66  				unsigned int reg,
67  				unsigned int val)
68  {
69  	writeb(val, ctx->regs + reg);
70  }
71  
regmap_mmio_write8_relaxed(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)72  static void regmap_mmio_write8_relaxed(struct regmap_mmio_context *ctx,
73  				unsigned int reg,
74  				unsigned int val)
75  {
76  	writeb_relaxed(val, ctx->regs + reg);
77  }
78  
regmap_mmio_iowrite8(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)79  static void regmap_mmio_iowrite8(struct regmap_mmio_context *ctx,
80  				 unsigned int reg, unsigned int val)
81  {
82  	iowrite8(val, ctx->regs + reg);
83  }
84  
regmap_mmio_write16le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)85  static void regmap_mmio_write16le(struct regmap_mmio_context *ctx,
86  				  unsigned int reg,
87  				  unsigned int val)
88  {
89  	writew(val, ctx->regs + reg);
90  }
91  
regmap_mmio_write16le_relaxed(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)92  static void regmap_mmio_write16le_relaxed(struct regmap_mmio_context *ctx,
93  				  unsigned int reg,
94  				  unsigned int val)
95  {
96  	writew_relaxed(val, ctx->regs + reg);
97  }
98  
regmap_mmio_iowrite16le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)99  static void regmap_mmio_iowrite16le(struct regmap_mmio_context *ctx,
100  				    unsigned int reg, unsigned int val)
101  {
102  	iowrite16(val, ctx->regs + reg);
103  }
104  
regmap_mmio_write16be(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)105  static void regmap_mmio_write16be(struct regmap_mmio_context *ctx,
106  				  unsigned int reg,
107  				  unsigned int val)
108  {
109  	writew(swab16(val), ctx->regs + reg);
110  }
111  
regmap_mmio_iowrite16be(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)112  static void regmap_mmio_iowrite16be(struct regmap_mmio_context *ctx,
113  				    unsigned int reg, unsigned int val)
114  {
115  	iowrite16be(val, ctx->regs + reg);
116  }
117  
regmap_mmio_write32le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)118  static void regmap_mmio_write32le(struct regmap_mmio_context *ctx,
119  				  unsigned int reg,
120  				  unsigned int val)
121  {
122  	writel(val, ctx->regs + reg);
123  }
124  
regmap_mmio_write32le_relaxed(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)125  static void regmap_mmio_write32le_relaxed(struct regmap_mmio_context *ctx,
126  				  unsigned int reg,
127  				  unsigned int val)
128  {
129  	writel_relaxed(val, ctx->regs + reg);
130  }
131  
regmap_mmio_iowrite32le(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)132  static void regmap_mmio_iowrite32le(struct regmap_mmio_context *ctx,
133  				    unsigned int reg, unsigned int val)
134  {
135  	iowrite32(val, ctx->regs + reg);
136  }
137  
regmap_mmio_write32be(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)138  static void regmap_mmio_write32be(struct regmap_mmio_context *ctx,
139  				  unsigned int reg,
140  				  unsigned int val)
141  {
142  	writel(swab32(val), ctx->regs + reg);
143  }
144  
regmap_mmio_iowrite32be(struct regmap_mmio_context * ctx,unsigned int reg,unsigned int val)145  static void regmap_mmio_iowrite32be(struct regmap_mmio_context *ctx,
146  				    unsigned int reg, unsigned int val)
147  {
148  	iowrite32be(val, ctx->regs + reg);
149  }
150  
regmap_mmio_write(void * context,unsigned int reg,unsigned int val)151  static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val)
152  {
153  	struct regmap_mmio_context *ctx = context;
154  	int ret;
155  
156  	if (!IS_ERR(ctx->clk)) {
157  		ret = clk_enable(ctx->clk);
158  		if (ret < 0)
159  			return ret;
160  	}
161  
162  	ctx->reg_write(ctx, reg, val);
163  
164  	if (!IS_ERR(ctx->clk))
165  		clk_disable(ctx->clk);
166  
167  	return 0;
168  }
169  
regmap_mmio_noinc_write(void * context,unsigned int reg,const void * val,size_t val_count)170  static int regmap_mmio_noinc_write(void *context, unsigned int reg,
171  				   const void *val, size_t val_count)
172  {
173  	struct regmap_mmio_context *ctx = context;
174  	int ret = 0;
175  	int i;
176  
177  	if (!IS_ERR(ctx->clk)) {
178  		ret = clk_enable(ctx->clk);
179  		if (ret < 0)
180  			return ret;
181  	}
182  
183  	/*
184  	 * There are no native, assembly-optimized write single register
185  	 * operations for big endian, so fall back to emulation if this
186  	 * is needed. (Single bytes are fine, they are not affected by
187  	 * endianness.)
188  	 */
189  	if (ctx->big_endian && (ctx->val_bytes > 1)) {
190  		switch (ctx->val_bytes) {
191  		case 2:
192  		{
193  			const u16 *valp = (const u16 *)val;
194  			for (i = 0; i < val_count; i++)
195  				writew(swab16(valp[i]), ctx->regs + reg);
196  			goto out_clk;
197  		}
198  		case 4:
199  		{
200  			const u32 *valp = (const u32 *)val;
201  			for (i = 0; i < val_count; i++)
202  				writel(swab32(valp[i]), ctx->regs + reg);
203  			goto out_clk;
204  		}
205  		default:
206  			ret = -EINVAL;
207  			goto out_clk;
208  		}
209  	}
210  
211  	switch (ctx->val_bytes) {
212  	case 1:
213  		writesb(ctx->regs + reg, (const u8 *)val, val_count);
214  		break;
215  	case 2:
216  		writesw(ctx->regs + reg, (const u16 *)val, val_count);
217  		break;
218  	case 4:
219  		writesl(ctx->regs + reg, (const u32 *)val, val_count);
220  		break;
221  	default:
222  		ret = -EINVAL;
223  		break;
224  	}
225  
226  out_clk:
227  	if (!IS_ERR(ctx->clk))
228  		clk_disable(ctx->clk);
229  
230  	return ret;
231  }
232  
regmap_mmio_read8(struct regmap_mmio_context * ctx,unsigned int reg)233  static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx,
234  				      unsigned int reg)
235  {
236  	return readb(ctx->regs + reg);
237  }
238  
regmap_mmio_read8_relaxed(struct regmap_mmio_context * ctx,unsigned int reg)239  static unsigned int regmap_mmio_read8_relaxed(struct regmap_mmio_context *ctx,
240  				      unsigned int reg)
241  {
242  	return readb_relaxed(ctx->regs + reg);
243  }
244  
regmap_mmio_ioread8(struct regmap_mmio_context * ctx,unsigned int reg)245  static unsigned int regmap_mmio_ioread8(struct regmap_mmio_context *ctx,
246  					unsigned int reg)
247  {
248  	return ioread8(ctx->regs + reg);
249  }
250  
regmap_mmio_read16le(struct regmap_mmio_context * ctx,unsigned int reg)251  static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx,
252  				         unsigned int reg)
253  {
254  	return readw(ctx->regs + reg);
255  }
256  
regmap_mmio_read16le_relaxed(struct regmap_mmio_context * ctx,unsigned int reg)257  static unsigned int regmap_mmio_read16le_relaxed(struct regmap_mmio_context *ctx,
258  						 unsigned int reg)
259  {
260  	return readw_relaxed(ctx->regs + reg);
261  }
262  
regmap_mmio_ioread16le(struct regmap_mmio_context * ctx,unsigned int reg)263  static unsigned int regmap_mmio_ioread16le(struct regmap_mmio_context *ctx,
264  					   unsigned int reg)
265  {
266  	return ioread16(ctx->regs + reg);
267  }
268  
regmap_mmio_read16be(struct regmap_mmio_context * ctx,unsigned int reg)269  static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx,
270  				         unsigned int reg)
271  {
272  	return swab16(readw(ctx->regs + reg));
273  }
274  
regmap_mmio_ioread16be(struct regmap_mmio_context * ctx,unsigned int reg)275  static unsigned int regmap_mmio_ioread16be(struct regmap_mmio_context *ctx,
276  					   unsigned int reg)
277  {
278  	return ioread16be(ctx->regs + reg);
279  }
280  
regmap_mmio_read32le(struct regmap_mmio_context * ctx,unsigned int reg)281  static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx,
282  				         unsigned int reg)
283  {
284  	return readl(ctx->regs + reg);
285  }
286  
regmap_mmio_read32le_relaxed(struct regmap_mmio_context * ctx,unsigned int reg)287  static unsigned int regmap_mmio_read32le_relaxed(struct regmap_mmio_context *ctx,
288  						 unsigned int reg)
289  {
290  	return readl_relaxed(ctx->regs + reg);
291  }
292  
regmap_mmio_ioread32le(struct regmap_mmio_context * ctx,unsigned int reg)293  static unsigned int regmap_mmio_ioread32le(struct regmap_mmio_context *ctx,
294  					   unsigned int reg)
295  {
296  	return ioread32(ctx->regs + reg);
297  }
298  
regmap_mmio_read32be(struct regmap_mmio_context * ctx,unsigned int reg)299  static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx,
300  				         unsigned int reg)
301  {
302  	return swab32(readl(ctx->regs + reg));
303  }
304  
regmap_mmio_ioread32be(struct regmap_mmio_context * ctx,unsigned int reg)305  static unsigned int regmap_mmio_ioread32be(struct regmap_mmio_context *ctx,
306  					   unsigned int reg)
307  {
308  	return ioread32be(ctx->regs + reg);
309  }
310  
regmap_mmio_read(void * context,unsigned int reg,unsigned int * val)311  static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val)
312  {
313  	struct regmap_mmio_context *ctx = context;
314  	int ret;
315  
316  	if (!IS_ERR(ctx->clk)) {
317  		ret = clk_enable(ctx->clk);
318  		if (ret < 0)
319  			return ret;
320  	}
321  
322  	*val = ctx->reg_read(ctx, reg);
323  
324  	if (!IS_ERR(ctx->clk))
325  		clk_disable(ctx->clk);
326  
327  	return 0;
328  }
329  
regmap_mmio_noinc_read(void * context,unsigned int reg,void * val,size_t val_count)330  static int regmap_mmio_noinc_read(void *context, unsigned int reg,
331  				  void *val, size_t val_count)
332  {
333  	struct regmap_mmio_context *ctx = context;
334  	int ret = 0;
335  
336  	if (!IS_ERR(ctx->clk)) {
337  		ret = clk_enable(ctx->clk);
338  		if (ret < 0)
339  			return ret;
340  	}
341  
342  	switch (ctx->val_bytes) {
343  	case 1:
344  		readsb(ctx->regs + reg, (u8 *)val, val_count);
345  		break;
346  	case 2:
347  		readsw(ctx->regs + reg, (u16 *)val, val_count);
348  		break;
349  	case 4:
350  		readsl(ctx->regs + reg, (u32 *)val, val_count);
351  		break;
352  	default:
353  		ret = -EINVAL;
354  		goto out_clk;
355  	}
356  
357  	/*
358  	 * There are no native, assembly-optimized write single register
359  	 * operations for big endian, so fall back to emulation if this
360  	 * is needed. (Single bytes are fine, they are not affected by
361  	 * endianness.)
362  	 */
363  	if (ctx->big_endian && (ctx->val_bytes > 1)) {
364  		switch (ctx->val_bytes) {
365  		case 2:
366  			swab16_array(val, val_count);
367  			break;
368  		case 4:
369  			swab32_array(val, val_count);
370  			break;
371  		default:
372  			ret = -EINVAL;
373  			break;
374  		}
375  	}
376  
377  out_clk:
378  	if (!IS_ERR(ctx->clk))
379  		clk_disable(ctx->clk);
380  
381  	return ret;
382  }
383  
384  
regmap_mmio_free_context(void * context)385  static void regmap_mmio_free_context(void *context)
386  {
387  	struct regmap_mmio_context *ctx = context;
388  
389  	if (!IS_ERR(ctx->clk)) {
390  		clk_unprepare(ctx->clk);
391  		if (!ctx->attached_clk)
392  			clk_put(ctx->clk);
393  	}
394  	kfree(context);
395  }
396  
397  static const struct regmap_bus regmap_mmio = {
398  	.fast_io = true,
399  	.reg_write = regmap_mmio_write,
400  	.reg_read = regmap_mmio_read,
401  	.reg_noinc_write = regmap_mmio_noinc_write,
402  	.reg_noinc_read = regmap_mmio_noinc_read,
403  	.free_context = regmap_mmio_free_context,
404  	.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
405  };
406  
regmap_mmio_gen_context(struct device * dev,const char * clk_id,void __iomem * regs,const struct regmap_config * config)407  static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
408  					const char *clk_id,
409  					void __iomem *regs,
410  					const struct regmap_config *config)
411  {
412  	struct regmap_mmio_context *ctx;
413  	int min_stride;
414  	int ret;
415  
416  	ret = regmap_mmio_regbits_check(config->reg_bits);
417  	if (ret)
418  		return ERR_PTR(ret);
419  
420  	if (config->pad_bits)
421  		return ERR_PTR(-EINVAL);
422  
423  	min_stride = regmap_mmio_get_min_stride(config->val_bits);
424  	if (min_stride < 0)
425  		return ERR_PTR(min_stride);
426  
427  	if (config->reg_stride && config->reg_stride < min_stride)
428  		return ERR_PTR(-EINVAL);
429  
430  	if (config->use_relaxed_mmio && config->io_port)
431  		return ERR_PTR(-EINVAL);
432  
433  	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
434  	if (!ctx)
435  		return ERR_PTR(-ENOMEM);
436  
437  	ctx->regs = regs;
438  	ctx->val_bytes = config->val_bits / 8;
439  	ctx->clk = ERR_PTR(-ENODEV);
440  
441  	switch (regmap_get_val_endian(dev, &regmap_mmio, config)) {
442  	case REGMAP_ENDIAN_DEFAULT:
443  	case REGMAP_ENDIAN_LITTLE:
444  #ifdef __LITTLE_ENDIAN
445  	case REGMAP_ENDIAN_NATIVE:
446  #endif
447  		switch (config->val_bits) {
448  		case 8:
449  			if (config->io_port) {
450  				ctx->reg_read = regmap_mmio_ioread8;
451  				ctx->reg_write = regmap_mmio_iowrite8;
452  			} else if (config->use_relaxed_mmio) {
453  				ctx->reg_read = regmap_mmio_read8_relaxed;
454  				ctx->reg_write = regmap_mmio_write8_relaxed;
455  			} else {
456  				ctx->reg_read = regmap_mmio_read8;
457  				ctx->reg_write = regmap_mmio_write8;
458  			}
459  			break;
460  		case 16:
461  			if (config->io_port) {
462  				ctx->reg_read = regmap_mmio_ioread16le;
463  				ctx->reg_write = regmap_mmio_iowrite16le;
464  			} else if (config->use_relaxed_mmio) {
465  				ctx->reg_read = regmap_mmio_read16le_relaxed;
466  				ctx->reg_write = regmap_mmio_write16le_relaxed;
467  			} else {
468  				ctx->reg_read = regmap_mmio_read16le;
469  				ctx->reg_write = regmap_mmio_write16le;
470  			}
471  			break;
472  		case 32:
473  			if (config->io_port) {
474  				ctx->reg_read = regmap_mmio_ioread32le;
475  				ctx->reg_write = regmap_mmio_iowrite32le;
476  			} else if (config->use_relaxed_mmio) {
477  				ctx->reg_read = regmap_mmio_read32le_relaxed;
478  				ctx->reg_write = regmap_mmio_write32le_relaxed;
479  			} else {
480  				ctx->reg_read = regmap_mmio_read32le;
481  				ctx->reg_write = regmap_mmio_write32le;
482  			}
483  			break;
484  		default:
485  			ret = -EINVAL;
486  			goto err_free;
487  		}
488  		break;
489  	case REGMAP_ENDIAN_BIG:
490  #ifdef __BIG_ENDIAN
491  	case REGMAP_ENDIAN_NATIVE:
492  #endif
493  		ctx->big_endian = true;
494  		switch (config->val_bits) {
495  		case 8:
496  			if (config->io_port) {
497  				ctx->reg_read = regmap_mmio_ioread8;
498  				ctx->reg_write = regmap_mmio_iowrite8;
499  			} else {
500  				ctx->reg_read = regmap_mmio_read8;
501  				ctx->reg_write = regmap_mmio_write8;
502  			}
503  			break;
504  		case 16:
505  			if (config->io_port) {
506  				ctx->reg_read = regmap_mmio_ioread16be;
507  				ctx->reg_write = regmap_mmio_iowrite16be;
508  			} else {
509  				ctx->reg_read = regmap_mmio_read16be;
510  				ctx->reg_write = regmap_mmio_write16be;
511  			}
512  			break;
513  		case 32:
514  			if (config->io_port) {
515  				ctx->reg_read = regmap_mmio_ioread32be;
516  				ctx->reg_write = regmap_mmio_iowrite32be;
517  			} else {
518  				ctx->reg_read = regmap_mmio_read32be;
519  				ctx->reg_write = regmap_mmio_write32be;
520  			}
521  			break;
522  		default:
523  			ret = -EINVAL;
524  			goto err_free;
525  		}
526  		break;
527  	default:
528  		ret = -EINVAL;
529  		goto err_free;
530  	}
531  
532  	if (clk_id == NULL)
533  		return ctx;
534  
535  	ctx->clk = clk_get(dev, clk_id);
536  	if (IS_ERR(ctx->clk)) {
537  		ret = PTR_ERR(ctx->clk);
538  		goto err_free;
539  	}
540  
541  	ret = clk_prepare(ctx->clk);
542  	if (ret < 0) {
543  		clk_put(ctx->clk);
544  		goto err_free;
545  	}
546  
547  	return ctx;
548  
549  err_free:
550  	kfree(ctx);
551  
552  	return ERR_PTR(ret);
553  }
554  
__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)555  struct regmap *__regmap_init_mmio_clk(struct device *dev, const char *clk_id,
556  				      void __iomem *regs,
557  				      const struct regmap_config *config,
558  				      struct lock_class_key *lock_key,
559  				      const char *lock_name)
560  {
561  	struct regmap_mmio_context *ctx;
562  
563  	ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
564  	if (IS_ERR(ctx))
565  		return ERR_CAST(ctx);
566  
567  	return __regmap_init(dev, &regmap_mmio, ctx, config,
568  			     lock_key, lock_name);
569  }
570  EXPORT_SYMBOL_GPL(__regmap_init_mmio_clk);
571  
__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)572  struct regmap *__devm_regmap_init_mmio_clk(struct device *dev,
573  					   const char *clk_id,
574  					   void __iomem *regs,
575  					   const struct regmap_config *config,
576  					   struct lock_class_key *lock_key,
577  					   const char *lock_name)
578  {
579  	struct regmap_mmio_context *ctx;
580  
581  	ctx = regmap_mmio_gen_context(dev, clk_id, regs, config);
582  	if (IS_ERR(ctx))
583  		return ERR_CAST(ctx);
584  
585  	return __devm_regmap_init(dev, &regmap_mmio, ctx, config,
586  				  lock_key, lock_name);
587  }
588  EXPORT_SYMBOL_GPL(__devm_regmap_init_mmio_clk);
589  
regmap_mmio_attach_clk(struct regmap * map,struct clk * clk)590  int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk)
591  {
592  	struct regmap_mmio_context *ctx = map->bus_context;
593  
594  	ctx->clk = clk;
595  	ctx->attached_clk = true;
596  
597  	return clk_prepare(ctx->clk);
598  }
599  EXPORT_SYMBOL_GPL(regmap_mmio_attach_clk);
600  
regmap_mmio_detach_clk(struct regmap * map)601  void regmap_mmio_detach_clk(struct regmap *map)
602  {
603  	struct regmap_mmio_context *ctx = map->bus_context;
604  
605  	clk_unprepare(ctx->clk);
606  
607  	ctx->attached_clk = false;
608  	ctx->clk = NULL;
609  }
610  EXPORT_SYMBOL_GPL(regmap_mmio_detach_clk);
611  
612  MODULE_LICENSE("GPL v2");
613