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