Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / core / regmap.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #define LOG_CATEGORY    LOGC_DM
8
9 #include <common.h>
10 #include <dm.h>
11 #include <errno.h>
12 #include <log.h>
13 #include <asm/global_data.h>
14 #include <linux/libfdt.h>
15 #include <malloc.h>
16 #include <mapmem.h>
17 #include <regmap.h>
18 #include <asm/io.h>
19 #include <dm/of_addr.h>
20 #include <dm/devres.h>
21 #include <linux/ioport.h>
22 #include <linux/compat.h>
23 #include <linux/err.h>
24 #include <linux/bitops.h>
25
26 /*
27  * Internal representation of a regmap field. Instead of storing the MSB and
28  * LSB, store the shift and mask. This makes the code a bit cleaner and faster
29  * because the shift and mask don't have to be calculated every time.
30  */
31 struct regmap_field {
32         struct regmap *regmap;
33         unsigned int mask;
34         /* lsb */
35         unsigned int shift;
36         unsigned int reg;
37 };
38
39 DECLARE_GLOBAL_DATA_PTR;
40
41 /**
42  * do_range_check() - Control whether range checks are done
43  *
44  * Returns: true to do range checks, false to skip
45  *
46  * This is used to reduce code size on SPL where range checks are known not to
47  * be needed
48  *
49  * Add this to the top of the file to enable them: #define LOG_DEBUG
50  */
51 static inline bool do_range_check(void)
52 {
53         return _LOG_DEBUG || !IS_ENABLED(CONFIG_SPL);
54
55 }
56
57 /**
58  * regmap_alloc() - Allocate a regmap with a given number of ranges.
59  *
60  * @count: Number of ranges to be allocated for the regmap.
61  *
62  * The default regmap width is set to REGMAP_SIZE_32. Callers can override it
63  * if they need.
64  *
65  * Return: A pointer to the newly allocated regmap, or NULL on error.
66  */
67 static struct regmap *regmap_alloc(int count)
68 {
69         struct regmap *map;
70         size_t size = sizeof(*map) + sizeof(map->ranges[0]) * count;
71
72         map = calloc(1, size);
73         if (!map)
74                 return NULL;
75         map->range_count = count;
76         map->width = REGMAP_SIZE_32;
77
78         return map;
79 }
80
81 #if CONFIG_IS_ENABLED(OF_PLATDATA)
82 int regmap_init_mem_plat(struct udevice *dev, void *reg, int size, int count,
83                          struct regmap **mapp)
84 {
85         struct regmap_range *range;
86         struct regmap *map;
87
88         map = regmap_alloc(count);
89         if (!map)
90                 return -ENOMEM;
91
92         if (size == sizeof(fdt32_t)) {
93                 fdt32_t *ptr = (fdt32_t *)reg;
94
95                 for (range = map->ranges; count > 0;
96                      ptr += 2, range++, count--) {
97                         range->start = *ptr;
98                         range->size = ptr[1];
99                 }
100         } else if (size == sizeof(fdt64_t)) {
101                 fdt64_t *ptr = (fdt64_t *)reg;
102
103                 for (range = map->ranges; count > 0;
104                      ptr += 2, range++, count--) {
105                         range->start = *ptr;
106                         range->size = ptr[1];
107                 }
108         } else {
109                 return -EINVAL;
110         }
111
112         *mapp = map;
113
114         return 0;
115 }
116 #else
117 /**
118  * init_range() - Initialize a single range of a regmap
119  * @node:     Device node that will use the map in question
120  * @range:    Pointer to a regmap_range structure that will be initialized
121  * @addr_len: The length of the addr parts of the reg property
122  * @size_len: The length of the size parts of the reg property
123  * @index:    The index of the range to initialize
124  *
125  * This function will read the necessary 'reg' information from the device tree
126  * (the 'addr' part, and the 'length' part), and initialize the range in
127  * quesion.
128  *
129  * Return: 0 if OK, -ve on error
130  */
131 static int init_range(ofnode node, struct regmap_range *range, int addr_len,
132                       int size_len, int index)
133 {
134         fdt_size_t sz;
135         struct resource r;
136
137         if (of_live_active()) {
138                 int ret;
139
140                 ret = of_address_to_resource(ofnode_to_np(node),
141                                              index, &r);
142                 if (ret) {
143                         debug("%s: Could not read resource of range %d (ret = %d)\n",
144                               ofnode_get_name(node), index, ret);
145                         return ret;
146                 }
147
148                 range->start = r.start;
149                 range->size = r.end - r.start + 1;
150         } else {
151                 int offset = ofnode_to_offset(node);
152
153                 range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset,
154                                                           "reg", index,
155                                                           addr_len, size_len,
156                                                           &sz, true);
157                 if (range->start == FDT_ADDR_T_NONE) {
158                         debug("%s: Could not read start of range %d\n",
159                               ofnode_get_name(node), index);
160                         return -EINVAL;
161                 }
162
163                 range->size = sz;
164         }
165
166         return 0;
167 }
168
169 int regmap_init_mem_index(ofnode node, struct regmap **mapp, int index)
170 {
171         struct regmap *map;
172         int addr_len, size_len;
173         int ret;
174
175         addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
176         if (addr_len < 0) {
177                 debug("%s: Error while reading the addr length (ret = %d)\n",
178                       ofnode_get_name(node), addr_len);
179                 return addr_len;
180         }
181
182         size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
183         if (size_len < 0) {
184                 debug("%s: Error while reading the size length: (ret = %d)\n",
185                       ofnode_get_name(node), size_len);
186                 return size_len;
187         }
188
189         map = regmap_alloc(1);
190         if (!map)
191                 return -ENOMEM;
192
193         ret = init_range(node, map->ranges, addr_len, size_len, index);
194         if (ret)
195                 goto err;
196
197         if (ofnode_read_bool(node, "little-endian"))
198                 map->endianness = REGMAP_LITTLE_ENDIAN;
199         else if (ofnode_read_bool(node, "big-endian"))
200                 map->endianness = REGMAP_BIG_ENDIAN;
201         else if (ofnode_read_bool(node, "native-endian"))
202                 map->endianness = REGMAP_NATIVE_ENDIAN;
203         else /* Default: native endianness */
204                 map->endianness = REGMAP_NATIVE_ENDIAN;
205
206         *mapp = map;
207
208         return 0;
209 err:
210         regmap_uninit(map);
211
212         return ret;
213 }
214
215 int regmap_init_mem_range(ofnode node, ulong r_start, ulong r_size,
216                           struct regmap **mapp)
217 {
218         struct regmap *map;
219         struct regmap_range *range;
220
221         map = regmap_alloc(1);
222         if (!map)
223                 return -ENOMEM;
224
225         range = &map->ranges[0];
226         range->start = r_start;
227         range->size = r_size;
228
229         if (ofnode_read_bool(node, "little-endian"))
230                 map->endianness = REGMAP_LITTLE_ENDIAN;
231         else if (ofnode_read_bool(node, "big-endian"))
232                 map->endianness = REGMAP_BIG_ENDIAN;
233         else if (ofnode_read_bool(node, "native-endian"))
234                 map->endianness = REGMAP_NATIVE_ENDIAN;
235         else /* Default: native endianness */
236                 map->endianness = REGMAP_NATIVE_ENDIAN;
237
238         *mapp = map;
239         return 0;
240 }
241
242 int regmap_init_mem(ofnode node, struct regmap **mapp)
243 {
244         struct regmap_range *range;
245         struct regmap *map;
246         int count;
247         int addr_len, size_len, both_len;
248         int len;
249         int index;
250         int ret;
251
252         addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
253         if (addr_len < 0) {
254                 debug("%s: Error while reading the addr length (ret = %d)\n",
255                       ofnode_get_name(node), addr_len);
256                 return addr_len;
257         }
258
259         size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
260         if (size_len < 0) {
261                 debug("%s: Error while reading the size length: (ret = %d)\n",
262                       ofnode_get_name(node), size_len);
263                 return size_len;
264         }
265
266         both_len = addr_len + size_len;
267         if (!both_len) {
268                 debug("%s: Both addr and size length are zero\n",
269                       ofnode_get_name(node));
270                 return -EINVAL;
271         }
272
273         len = ofnode_read_size(node, "reg");
274         if (len < 0) {
275                 debug("%s: Error while reading reg size (ret = %d)\n",
276                       ofnode_get_name(node), len);
277                 return len;
278         }
279         len /= sizeof(fdt32_t);
280         count = len / both_len;
281         if (!count) {
282                 debug("%s: Not enough data in reg property\n",
283                       ofnode_get_name(node));
284                 return -EINVAL;
285         }
286
287         map = regmap_alloc(count);
288         if (!map)
289                 return -ENOMEM;
290
291         for (range = map->ranges, index = 0; count > 0;
292              count--, range++, index++) {
293                 ret = init_range(node, range, addr_len, size_len, index);
294                 if (ret)
295                         goto err;
296         }
297
298         if (ofnode_read_bool(node, "little-endian"))
299                 map->endianness = REGMAP_LITTLE_ENDIAN;
300         else if (ofnode_read_bool(node, "big-endian"))
301                 map->endianness = REGMAP_BIG_ENDIAN;
302         else if (ofnode_read_bool(node, "native-endian"))
303                 map->endianness = REGMAP_NATIVE_ENDIAN;
304         else /* Default: native endianness */
305                 map->endianness = REGMAP_NATIVE_ENDIAN;
306
307         *mapp = map;
308
309         return 0;
310 err:
311         regmap_uninit(map);
312
313         return ret;
314 }
315
316 static void devm_regmap_release(struct udevice *dev, void *res)
317 {
318         regmap_uninit(*(struct regmap **)res);
319 }
320
321 struct regmap *devm_regmap_init(struct udevice *dev,
322                                 const struct regmap_bus *bus,
323                                 void *bus_context,
324                                 const struct regmap_config *config)
325 {
326         int rc;
327         struct regmap **mapp, *map;
328
329         /* this looks like a leak, but devres takes care of it */
330         mapp = devres_alloc(devm_regmap_release, sizeof(struct regmap *),
331                             __GFP_ZERO);
332         if (unlikely(!mapp))
333                 return ERR_PTR(-ENOMEM);
334
335         if (config && config->r_size != 0)
336                 rc = regmap_init_mem_range(dev_ofnode(dev), config->r_start,
337                                            config->r_size, mapp);
338         else
339                 rc = regmap_init_mem(dev_ofnode(dev), mapp);
340         if (rc)
341                 return ERR_PTR(rc);
342
343         map = *mapp;
344         if (config) {
345                 map->width = config->width;
346                 map->reg_offset_shift = config->reg_offset_shift;
347         }
348
349         devres_add(dev, mapp);
350         return *mapp;
351 }
352 #endif
353
354 void *regmap_get_range(struct regmap *map, unsigned int range_num)
355 {
356         struct regmap_range *range;
357
358         if (range_num >= map->range_count)
359                 return NULL;
360         range = &map->ranges[range_num];
361
362         return map_sysmem(range->start, range->size);
363 }
364
365 int regmap_uninit(struct regmap *map)
366 {
367         free(map);
368
369         return 0;
370 }
371
372 static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
373 {
374         return readb(addr);
375 }
376
377 static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
378 {
379         switch (endianness) {
380         case REGMAP_LITTLE_ENDIAN:
381                 return in_le16(addr);
382         case REGMAP_BIG_ENDIAN:
383                 return in_be16(addr);
384         case REGMAP_NATIVE_ENDIAN:
385                 return readw(addr);
386         }
387
388         return readw(addr);
389 }
390
391 static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
392 {
393         switch (endianness) {
394         case REGMAP_LITTLE_ENDIAN:
395                 return in_le32(addr);
396         case REGMAP_BIG_ENDIAN:
397                 return in_be32(addr);
398         case REGMAP_NATIVE_ENDIAN:
399                 return readl(addr);
400         }
401
402         return readl(addr);
403 }
404
405 #if defined(in_le64) && defined(in_be64) && defined(readq)
406 static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
407 {
408         switch (endianness) {
409         case REGMAP_LITTLE_ENDIAN:
410                 return in_le64(addr);
411         case REGMAP_BIG_ENDIAN:
412                 return in_be64(addr);
413         case REGMAP_NATIVE_ENDIAN:
414                 return readq(addr);
415         }
416
417         return readq(addr);
418 }
419 #endif
420
421 int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
422                           void *valp, size_t val_len)
423 {
424         struct regmap_range *range;
425         void *ptr;
426
427         if (do_range_check() && range_num >= map->range_count) {
428                 debug("%s: range index %d larger than range count\n",
429                       __func__, range_num);
430                 return -ERANGE;
431         }
432         range = &map->ranges[range_num];
433
434         offset <<= map->reg_offset_shift;
435         if (do_range_check() &&
436             (offset + val_len > range->size || offset + val_len < offset)) {
437                 debug("%s: offset/size combination invalid\n", __func__);
438                 return -ERANGE;
439         }
440
441         ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
442
443         switch (val_len) {
444         case REGMAP_SIZE_8:
445                 *((u8 *)valp) = __read_8(ptr, map->endianness);
446                 break;
447         case REGMAP_SIZE_16:
448                 *((u16 *)valp) = __read_16(ptr, map->endianness);
449                 break;
450         case REGMAP_SIZE_32:
451                 *((u32 *)valp) = __read_32(ptr, map->endianness);
452                 break;
453 #if defined(in_le64) && defined(in_be64) && defined(readq)
454         case REGMAP_SIZE_64:
455                 *((u64 *)valp) = __read_64(ptr, map->endianness);
456                 break;
457 #endif
458         default:
459                 debug("%s: regmap size %zu unknown\n", __func__, val_len);
460                 return -EINVAL;
461         }
462
463         return 0;
464 }
465
466 int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len)
467 {
468         return regmap_raw_read_range(map, 0, offset, valp, val_len);
469 }
470
471 int regmap_read(struct regmap *map, uint offset, uint *valp)
472 {
473         union {
474                 u8 v8;
475                 u16 v16;
476                 u32 v32;
477                 u64 v64;
478         } u;
479         int res;
480
481         res = regmap_raw_read(map, offset, &u, map->width);
482         if (res)
483                 return res;
484
485         switch (map->width) {
486         case REGMAP_SIZE_8:
487                 *valp = u.v8;
488                 break;
489         case REGMAP_SIZE_16:
490                 *valp = u.v16;
491                 break;
492         case REGMAP_SIZE_32:
493                 *valp = u.v32;
494                 break;
495         case REGMAP_SIZE_64:
496                 *valp = u.v64;
497                 break;
498         default:
499                 unreachable();
500         }
501
502         return 0;
503 }
504
505 static inline void __write_8(u8 *addr, const u8 *val,
506                              enum regmap_endianness_t endianness)
507 {
508         writeb(*val, addr);
509 }
510
511 static inline void __write_16(u16 *addr, const u16 *val,
512                               enum regmap_endianness_t endianness)
513 {
514         switch (endianness) {
515         case REGMAP_NATIVE_ENDIAN:
516                 writew(*val, addr);
517                 break;
518         case REGMAP_LITTLE_ENDIAN:
519                 out_le16(addr, *val);
520                 break;
521         case REGMAP_BIG_ENDIAN:
522                 out_be16(addr, *val);
523                 break;
524         }
525 }
526
527 static inline void __write_32(u32 *addr, const u32 *val,
528                               enum regmap_endianness_t endianness)
529 {
530         switch (endianness) {
531         case REGMAP_NATIVE_ENDIAN:
532                 writel(*val, addr);
533                 break;
534         case REGMAP_LITTLE_ENDIAN:
535                 out_le32(addr, *val);
536                 break;
537         case REGMAP_BIG_ENDIAN:
538                 out_be32(addr, *val);
539                 break;
540         }
541 }
542
543 #if defined(out_le64) && defined(out_be64) && defined(writeq)
544 static inline void __write_64(u64 *addr, const u64 *val,
545                               enum regmap_endianness_t endianness)
546 {
547         switch (endianness) {
548         case REGMAP_NATIVE_ENDIAN:
549                 writeq(*val, addr);
550                 break;
551         case REGMAP_LITTLE_ENDIAN:
552                 out_le64(addr, *val);
553                 break;
554         case REGMAP_BIG_ENDIAN:
555                 out_be64(addr, *val);
556                 break;
557         }
558 }
559 #endif
560
561 int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
562                            const void *val, size_t val_len)
563 {
564         struct regmap_range *range;
565         void *ptr;
566
567         if (range_num >= map->range_count) {
568                 debug("%s: range index %d larger than range count\n",
569                       __func__, range_num);
570                 return -ERANGE;
571         }
572         range = &map->ranges[range_num];
573
574         offset <<= map->reg_offset_shift;
575         if (offset + val_len > range->size || offset + val_len < offset) {
576                 debug("%s: offset/size combination invalid\n", __func__);
577                 return -ERANGE;
578         }
579
580         ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
581
582         switch (val_len) {
583         case REGMAP_SIZE_8:
584                 __write_8(ptr, val, map->endianness);
585                 break;
586         case REGMAP_SIZE_16:
587                 __write_16(ptr, val, map->endianness);
588                 break;
589         case REGMAP_SIZE_32:
590                 __write_32(ptr, val, map->endianness);
591                 break;
592 #if defined(out_le64) && defined(out_be64) && defined(writeq)
593         case REGMAP_SIZE_64:
594                 __write_64(ptr, val, map->endianness);
595                 break;
596 #endif
597         default:
598                 debug("%s: regmap size %zu unknown\n", __func__, val_len);
599                 return -EINVAL;
600         }
601
602         return 0;
603 }
604
605 int regmap_raw_write(struct regmap *map, uint offset, const void *val,
606                      size_t val_len)
607 {
608         return regmap_raw_write_range(map, 0, offset, val, val_len);
609 }
610
611 int regmap_write(struct regmap *map, uint offset, uint val)
612 {
613         union {
614                 u8 v8;
615                 u16 v16;
616                 u32 v32;
617                 u64 v64;
618         } u;
619
620         switch (map->width) {
621         case REGMAP_SIZE_8:
622                 u.v8 = val;
623                 break;
624         case REGMAP_SIZE_16:
625                 u.v16 = val;
626                 break;
627         case REGMAP_SIZE_32:
628                 u.v32 = val;
629                 break;
630         case REGMAP_SIZE_64:
631                 u.v64 = val;
632                 break;
633         default:
634                 debug("%s: regmap size %zu unknown\n", __func__,
635                       (size_t)map->width);
636                 return -EINVAL;
637         }
638
639         return regmap_raw_write(map, offset, &u, map->width);
640 }
641
642 int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
643 {
644         uint reg;
645         int ret;
646
647         ret = regmap_read(map, offset, &reg);
648         if (ret)
649                 return ret;
650
651         reg &= ~mask;
652
653         return regmap_write(map, offset, reg | (val & mask));
654 }
655
656 int regmap_field_read(struct regmap_field *field, unsigned int *val)
657 {
658         int ret;
659         unsigned int reg_val;
660
661         ret = regmap_read(field->regmap, field->reg, &reg_val);
662         if (ret != 0)
663                 return ret;
664
665         reg_val &= field->mask;
666         reg_val >>= field->shift;
667         *val = reg_val;
668
669         return ret;
670 }
671
672 int regmap_field_write(struct regmap_field *field, unsigned int val)
673 {
674         return regmap_update_bits(field->regmap, field->reg, field->mask,
675                                   val << field->shift);
676 }
677
678 static void regmap_field_init(struct regmap_field *rm_field,
679                               struct regmap *regmap,
680                               struct reg_field reg_field)
681 {
682         rm_field->regmap = regmap;
683         rm_field->reg = reg_field.reg;
684         rm_field->shift = reg_field.lsb;
685         rm_field->mask = GENMASK(reg_field.msb, reg_field.lsb);
686 }
687
688 struct regmap_field *devm_regmap_field_alloc(struct udevice *dev,
689                                              struct regmap *regmap,
690                                              struct reg_field reg_field)
691 {
692         struct regmap_field *rm_field = devm_kzalloc(dev, sizeof(*rm_field),
693                                                      GFP_KERNEL);
694         if (!rm_field)
695                 return ERR_PTR(-ENOMEM);
696
697         regmap_field_init(rm_field, regmap, reg_field);
698
699         return rm_field;
700 }
701
702 void devm_regmap_field_free(struct udevice *dev, struct regmap_field *field)
703 {
704         devm_kfree(dev, field);
705 }
706
707 struct regmap_field *regmap_field_alloc(struct regmap *regmap,
708                                         struct reg_field reg_field)
709 {
710         struct regmap_field *rm_field = kzalloc(sizeof(*rm_field), GFP_KERNEL);
711
712         if (!rm_field)
713                 return ERR_PTR(-ENOMEM);
714
715         regmap_field_init(rm_field, regmap, reg_field);
716
717         return rm_field;
718 }
719
720 void regmap_field_free(struct regmap_field *field)
721 {
722         kfree(field);
723 }