xref: /openbmc/u-boot/drivers/core/regmap.c (revision 1d6edcbf)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
26f98b750SSimon Glass /*
36f98b750SSimon Glass  * Copyright (c) 2015 Google, Inc
46f98b750SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
56f98b750SSimon Glass  */
66f98b750SSimon Glass 
76f98b750SSimon Glass #include <common.h>
86f98b750SSimon Glass #include <dm.h>
96f98b750SSimon Glass #include <errno.h>
10b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
116f98b750SSimon Glass #include <malloc.h>
126f98b750SSimon Glass #include <mapmem.h>
136f98b750SSimon Glass #include <regmap.h>
143bfb8cb4SPaul Burton #include <asm/io.h>
1523d63267SSimon Glass #include <dm/of_addr.h>
1623d63267SSimon Glass #include <linux/ioport.h>
173bfb8cb4SPaul Burton 
186f98b750SSimon Glass DECLARE_GLOBAL_DATA_PTR;
196f98b750SSimon Glass 
209b076095SMario Six /**
219b076095SMario Six  * regmap_alloc() - Allocate a regmap with a given number of ranges.
229b076095SMario Six  *
239b076095SMario Six  * @count: Number of ranges to be allocated for the regmap.
249b076095SMario Six  * Return: A pointer to the newly allocated regmap, or NULL on error.
259b076095SMario Six  */
regmap_alloc(int count)268c1de5e0SMasahiro Yamada static struct regmap *regmap_alloc(int count)
27a951431eSSimon Glass {
28a951431eSSimon Glass 	struct regmap *map;
29a951431eSSimon Glass 
308c1de5e0SMasahiro Yamada 	map = malloc(sizeof(*map) + sizeof(map->ranges[0]) * count);
31a951431eSSimon Glass 	if (!map)
32a951431eSSimon Glass 		return NULL;
33a951431eSSimon Glass 	map->range_count = count;
34a951431eSSimon Glass 
35a951431eSSimon Glass 	return map;
36a951431eSSimon Glass }
37a951431eSSimon Glass 
383b2a29e0SSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA)
regmap_init_mem_platdata(struct udevice * dev,fdt_val_t * reg,int count,struct regmap ** mapp)39c20ee0edSSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
403b2a29e0SSimon Glass 			     struct regmap **mapp)
413b2a29e0SSimon Glass {
421e6ca1a6SSimon Glass 	struct regmap_range *range;
431e6ca1a6SSimon Glass 	struct regmap *map;
441e6ca1a6SSimon Glass 
458c1de5e0SMasahiro Yamada 	map = regmap_alloc(count);
461e6ca1a6SSimon Glass 	if (!map)
471e6ca1a6SSimon Glass 		return -ENOMEM;
481e6ca1a6SSimon Glass 
498c1de5e0SMasahiro Yamada 	for (range = map->ranges; count > 0; reg += 2, range++, count--) {
501e6ca1a6SSimon Glass 		range->start = *reg;
511e6ca1a6SSimon Glass 		range->size = reg[1];
521e6ca1a6SSimon Glass 	}
531e6ca1a6SSimon Glass 
541e6ca1a6SSimon Glass 	*mapp = map;
551e6ca1a6SSimon Glass 
563b2a29e0SSimon Glass 	return 0;
573b2a29e0SSimon Glass }
583b2a29e0SSimon Glass #else
597f0e3669SMario Six /**
607f0e3669SMario Six  * init_range() - Initialize a single range of a regmap
617f0e3669SMario Six  * @node:     Device node that will use the map in question
627f0e3669SMario Six  * @range:    Pointer to a regmap_range structure that will be initialized
637f0e3669SMario Six  * @addr_len: The length of the addr parts of the reg property
647f0e3669SMario Six  * @size_len: The length of the size parts of the reg property
657f0e3669SMario Six  * @index:    The index of the range to initialize
667f0e3669SMario Six  *
677f0e3669SMario Six  * This function will read the necessary 'reg' information from the device tree
687f0e3669SMario Six  * (the 'addr' part, and the 'length' part), and initialize the range in
697f0e3669SMario Six  * quesion.
707f0e3669SMario Six  *
717f0e3669SMario Six  * Return: 0 if OK, -ve on error
727f0e3669SMario Six  */
init_range(ofnode node,struct regmap_range * range,int addr_len,int size_len,int index)737f0e3669SMario Six static int init_range(ofnode node, struct regmap_range *range, int addr_len,
747f0e3669SMario Six 		      int size_len, int index)
757f0e3669SMario Six {
767f0e3669SMario Six 	fdt_size_t sz;
777f0e3669SMario Six 	struct resource r;
787f0e3669SMario Six 
797f0e3669SMario Six 	if (of_live_active()) {
807f0e3669SMario Six 		int ret;
817f0e3669SMario Six 
827f0e3669SMario Six 		ret = of_address_to_resource(ofnode_to_np(node),
837f0e3669SMario Six 					     index, &r);
847f0e3669SMario Six 		if (ret) {
857f0e3669SMario Six 			debug("%s: Could not read resource of range %d (ret = %d)\n",
867f0e3669SMario Six 			      ofnode_get_name(node), index, ret);
877f0e3669SMario Six 			return ret;
887f0e3669SMario Six 		}
897f0e3669SMario Six 
907f0e3669SMario Six 		range->start = r.start;
917f0e3669SMario Six 		range->size = r.end - r.start + 1;
927f0e3669SMario Six 	} else {
937f0e3669SMario Six 		int offset = ofnode_to_offset(node);
947f0e3669SMario Six 
957f0e3669SMario Six 		range->start = fdtdec_get_addr_size_fixed(gd->fdt_blob, offset,
967f0e3669SMario Six 							  "reg", index,
977f0e3669SMario Six 							  addr_len, size_len,
987f0e3669SMario Six 							  &sz, true);
997f0e3669SMario Six 		if (range->start == FDT_ADDR_T_NONE) {
1007f0e3669SMario Six 			debug("%s: Could not read start of range %d\n",
1017f0e3669SMario Six 			      ofnode_get_name(node), index);
1027f0e3669SMario Six 			return -EINVAL;
1037f0e3669SMario Six 		}
1047f0e3669SMario Six 
1057f0e3669SMario Six 		range->size = sz;
1067f0e3669SMario Six 	}
1077f0e3669SMario Six 
1087f0e3669SMario Six 	return 0;
1097f0e3669SMario Six }
1107f0e3669SMario Six 
regmap_init_mem(ofnode node,struct regmap ** mapp)111d3581236SMasahiro Yamada int regmap_init_mem(ofnode node, struct regmap **mapp)
1126f98b750SSimon Glass {
1136f98b750SSimon Glass 	struct regmap_range *range;
1146f98b750SSimon Glass 	struct regmap *map;
1156f98b750SSimon Glass 	int count;
1166f98b750SSimon Glass 	int addr_len, size_len, both_len;
1176f98b750SSimon Glass 	int len;
1181804044fSJean-Jacques Hiblot 	int index;
1196f98b750SSimon Glass 
120d3581236SMasahiro Yamada 	addr_len = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
121b6f58bfdSMario Six 	if (addr_len < 0) {
122b6f58bfdSMario Six 		debug("%s: Error while reading the addr length (ret = %d)\n",
123b6f58bfdSMario Six 		      ofnode_get_name(node), addr_len);
124b6f58bfdSMario Six 		return addr_len;
125b6f58bfdSMario Six 	}
126b6f58bfdSMario Six 
127d3581236SMasahiro Yamada 	size_len = ofnode_read_simple_size_cells(ofnode_get_parent(node));
128b6f58bfdSMario Six 	if (size_len < 0) {
129b6f58bfdSMario Six 		debug("%s: Error while reading the size length: (ret = %d)\n",
130b6f58bfdSMario Six 		      ofnode_get_name(node), size_len);
131b6f58bfdSMario Six 		return size_len;
132b6f58bfdSMario Six 	}
133b6f58bfdSMario Six 
1346f98b750SSimon Glass 	both_len = addr_len + size_len;
135b6f58bfdSMario Six 	if (!both_len) {
136b6f58bfdSMario Six 		debug("%s: Both addr and size length are zero\n",
137b6f58bfdSMario Six 		      ofnode_get_name(node));
138b6f58bfdSMario Six 		return -EINVAL;
139b6f58bfdSMario Six 	}
1406f98b750SSimon Glass 
141d3581236SMasahiro Yamada 	len = ofnode_read_size(node, "reg");
1422448f607SMario Six 	if (len < 0) {
1432448f607SMario Six 		debug("%s: Error while reading reg size (ret = %d)\n",
1442448f607SMario Six 		      ofnode_get_name(node), len);
14523d63267SSimon Glass 		return len;
1462448f607SMario Six 	}
14723d63267SSimon Glass 	len /= sizeof(fdt32_t);
1486f98b750SSimon Glass 	count = len / both_len;
1492448f607SMario Six 	if (!count) {
1502448f607SMario Six 		debug("%s: Not enough data in reg property\n",
1512448f607SMario Six 		      ofnode_get_name(node));
1526f98b750SSimon Glass 		return -EINVAL;
1532448f607SMario Six 	}
1546f98b750SSimon Glass 
1558c1de5e0SMasahiro Yamada 	map = regmap_alloc(count);
1566f98b750SSimon Glass 	if (!map)
1576f98b750SSimon Glass 		return -ENOMEM;
1586f98b750SSimon Glass 
1598c1de5e0SMasahiro Yamada 	for (range = map->ranges, index = 0; count > 0;
16023d63267SSimon Glass 	     count--, range++, index++) {
1617f0e3669SMario Six 		int ret = init_range(node, range, addr_len, size_len, index);
1627f0e3669SMario Six 
1637f0e3669SMario Six 		if (ret)
1647f0e3669SMario Six 			return ret;
16523d63267SSimon Glass 	}
1666f98b750SSimon Glass 
167*9b77fe3bSMario Six 	if (ofnode_read_bool(node, "little-endian"))
168*9b77fe3bSMario Six 		map->endianness = REGMAP_LITTLE_ENDIAN;
169*9b77fe3bSMario Six 	else if (ofnode_read_bool(node, "big-endian"))
170*9b77fe3bSMario Six 		map->endianness = REGMAP_BIG_ENDIAN;
171*9b77fe3bSMario Six 	else if (ofnode_read_bool(node, "native-endian"))
172*9b77fe3bSMario Six 		map->endianness = REGMAP_NATIVE_ENDIAN;
173*9b77fe3bSMario Six 	else /* Default: native endianness */
174*9b77fe3bSMario Six 		map->endianness = REGMAP_NATIVE_ENDIAN;
175*9b77fe3bSMario Six 
1766f98b750SSimon Glass 	*mapp = map;
1776f98b750SSimon Glass 
1786f98b750SSimon Glass 	return 0;
1796f98b750SSimon Glass }
1803b2a29e0SSimon Glass #endif
1816f98b750SSimon Glass 
regmap_get_range(struct regmap * map,unsigned int range_num)1826f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num)
1836f98b750SSimon Glass {
1846f98b750SSimon Glass 	struct regmap_range *range;
1856f98b750SSimon Glass 
1866f98b750SSimon Glass 	if (range_num >= map->range_count)
1876f98b750SSimon Glass 		return NULL;
1888c1de5e0SMasahiro Yamada 	range = &map->ranges[range_num];
1896f98b750SSimon Glass 
1906f98b750SSimon Glass 	return map_sysmem(range->start, range->size);
1916f98b750SSimon Glass }
1926f98b750SSimon Glass 
regmap_uninit(struct regmap * map)1936f98b750SSimon Glass int regmap_uninit(struct regmap *map)
1946f98b750SSimon Glass {
1956f98b750SSimon Glass 	free(map);
1966f98b750SSimon Glass 
1976f98b750SSimon Glass 	return 0;
1986f98b750SSimon Glass }
1993bfb8cb4SPaul Burton 
__read_8(u8 * addr,enum regmap_endianness_t endianness)200*9b77fe3bSMario Six static inline u8 __read_8(u8 *addr, enum regmap_endianness_t endianness)
201*9b77fe3bSMario Six {
202*9b77fe3bSMario Six 	return readb(addr);
203*9b77fe3bSMario Six }
204*9b77fe3bSMario Six 
__read_16(u16 * addr,enum regmap_endianness_t endianness)205*9b77fe3bSMario Six static inline u16 __read_16(u16 *addr, enum regmap_endianness_t endianness)
206*9b77fe3bSMario Six {
207*9b77fe3bSMario Six 	switch (endianness) {
208*9b77fe3bSMario Six 	case REGMAP_LITTLE_ENDIAN:
209*9b77fe3bSMario Six 		return in_le16(addr);
210*9b77fe3bSMario Six 	case REGMAP_BIG_ENDIAN:
211*9b77fe3bSMario Six 		return in_be16(addr);
212*9b77fe3bSMario Six 	case REGMAP_NATIVE_ENDIAN:
213*9b77fe3bSMario Six 		return readw(addr);
214*9b77fe3bSMario Six 	}
215*9b77fe3bSMario Six 
216*9b77fe3bSMario Six 	return readw(addr);
217*9b77fe3bSMario Six }
218*9b77fe3bSMario Six 
__read_32(u32 * addr,enum regmap_endianness_t endianness)219*9b77fe3bSMario Six static inline u32 __read_32(u32 *addr, enum regmap_endianness_t endianness)
220*9b77fe3bSMario Six {
221*9b77fe3bSMario Six 	switch (endianness) {
222*9b77fe3bSMario Six 	case REGMAP_LITTLE_ENDIAN:
223*9b77fe3bSMario Six 		return in_le32(addr);
224*9b77fe3bSMario Six 	case REGMAP_BIG_ENDIAN:
225*9b77fe3bSMario Six 		return in_be32(addr);
226*9b77fe3bSMario Six 	case REGMAP_NATIVE_ENDIAN:
227*9b77fe3bSMario Six 		return readl(addr);
228*9b77fe3bSMario Six 	}
229*9b77fe3bSMario Six 
230*9b77fe3bSMario Six 	return readl(addr);
231*9b77fe3bSMario Six }
232*9b77fe3bSMario Six 
233*9b77fe3bSMario Six #if defined(in_le64) && defined(in_be64) && defined(readq)
__read_64(u64 * addr,enum regmap_endianness_t endianness)234*9b77fe3bSMario Six static inline u64 __read_64(u64 *addr, enum regmap_endianness_t endianness)
235*9b77fe3bSMario Six {
236*9b77fe3bSMario Six 	switch (endianness) {
237*9b77fe3bSMario Six 	case REGMAP_LITTLE_ENDIAN:
238*9b77fe3bSMario Six 		return in_le64(addr);
239*9b77fe3bSMario Six 	case REGMAP_BIG_ENDIAN:
240*9b77fe3bSMario Six 		return in_be64(addr);
241*9b77fe3bSMario Six 	case REGMAP_NATIVE_ENDIAN:
242*9b77fe3bSMario Six 		return readq(addr);
243*9b77fe3bSMario Six 	}
244*9b77fe3bSMario Six 
245*9b77fe3bSMario Six 	return readq(addr);
246*9b77fe3bSMario Six }
247*9b77fe3bSMario Six #endif
248*9b77fe3bSMario Six 
regmap_raw_read_range(struct regmap * map,uint range_num,uint offset,void * valp,size_t val_len)249d5c7bd98SMario Six int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
250d5c7bd98SMario Six 			  void *valp, size_t val_len)
25184ff8f62SMario Six {
252d5c7bd98SMario Six 	struct regmap_range *range;
25384ff8f62SMario Six 	void *ptr;
25484ff8f62SMario Six 
255d5c7bd98SMario Six 	if (range_num >= map->range_count) {
256d5c7bd98SMario Six 		debug("%s: range index %d larger than range count\n",
257d5c7bd98SMario Six 		      __func__, range_num);
258d5c7bd98SMario Six 		return -ERANGE;
259d5c7bd98SMario Six 	}
260d5c7bd98SMario Six 	range = &map->ranges[range_num];
261d5c7bd98SMario Six 
262d5c7bd98SMario Six 	ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
263d5c7bd98SMario Six 
264d5c7bd98SMario Six 	if (offset + val_len > range->size) {
265d5c7bd98SMario Six 		debug("%s: offset/size combination invalid\n", __func__);
266d5c7bd98SMario Six 		return -ERANGE;
267d5c7bd98SMario Six 	}
26884ff8f62SMario Six 
26984ff8f62SMario Six 	switch (val_len) {
27084ff8f62SMario Six 	case REGMAP_SIZE_8:
271*9b77fe3bSMario Six 		*((u8 *)valp) = __read_8(ptr, map->endianness);
27284ff8f62SMario Six 		break;
27384ff8f62SMario Six 	case REGMAP_SIZE_16:
274*9b77fe3bSMario Six 		*((u16 *)valp) = __read_16(ptr, map->endianness);
27584ff8f62SMario Six 		break;
27684ff8f62SMario Six 	case REGMAP_SIZE_32:
277*9b77fe3bSMario Six 		*((u32 *)valp) = __read_32(ptr, map->endianness);
27884ff8f62SMario Six 		break;
279*9b77fe3bSMario Six #if defined(in_le64) && defined(in_be64) && defined(readq)
28084ff8f62SMario Six 	case REGMAP_SIZE_64:
281*9b77fe3bSMario Six 		*((u64 *)valp) = __read_64(ptr, map->endianness);
28284ff8f62SMario Six 		break;
28384ff8f62SMario Six #endif
28484ff8f62SMario Six 	default:
28584ff8f62SMario Six 		debug("%s: regmap size %zu unknown\n", __func__, val_len);
28684ff8f62SMario Six 		return -EINVAL;
28784ff8f62SMario Six 	}
288d5c7bd98SMario Six 
28984ff8f62SMario Six 	return 0;
29084ff8f62SMario Six }
29184ff8f62SMario Six 
regmap_raw_read(struct regmap * map,uint offset,void * valp,size_t val_len)292d5c7bd98SMario Six int regmap_raw_read(struct regmap *map, uint offset, void *valp, size_t val_len)
293d5c7bd98SMario Six {
294d5c7bd98SMario Six 	return regmap_raw_read_range(map, 0, offset, valp, val_len);
295d5c7bd98SMario Six }
296d5c7bd98SMario Six 
regmap_read(struct regmap * map,uint offset,uint * valp)2973bfb8cb4SPaul Burton int regmap_read(struct regmap *map, uint offset, uint *valp)
2983bfb8cb4SPaul Burton {
29984ff8f62SMario Six 	return regmap_raw_read(map, offset, valp, REGMAP_SIZE_32);
30084ff8f62SMario Six }
3013bfb8cb4SPaul Burton 
__write_8(u8 * addr,const u8 * val,enum regmap_endianness_t endianness)302*9b77fe3bSMario Six static inline void __write_8(u8 *addr, const u8 *val,
303*9b77fe3bSMario Six 			     enum regmap_endianness_t endianness)
304*9b77fe3bSMario Six {
305*9b77fe3bSMario Six 	writeb(*val, addr);
306*9b77fe3bSMario Six }
307*9b77fe3bSMario Six 
__write_16(u16 * addr,const u16 * val,enum regmap_endianness_t endianness)308*9b77fe3bSMario Six static inline void __write_16(u16 *addr, const u16 *val,
309*9b77fe3bSMario Six 			      enum regmap_endianness_t endianness)
310*9b77fe3bSMario Six {
311*9b77fe3bSMario Six 	switch (endianness) {
312*9b77fe3bSMario Six 	case REGMAP_NATIVE_ENDIAN:
313*9b77fe3bSMario Six 		writew(*val, addr);
314*9b77fe3bSMario Six 		break;
315*9b77fe3bSMario Six 	case REGMAP_LITTLE_ENDIAN:
316*9b77fe3bSMario Six 		out_le16(addr, *val);
317*9b77fe3bSMario Six 		break;
318*9b77fe3bSMario Six 	case REGMAP_BIG_ENDIAN:
319*9b77fe3bSMario Six 		out_be16(addr, *val);
320*9b77fe3bSMario Six 		break;
321*9b77fe3bSMario Six 	}
322*9b77fe3bSMario Six }
323*9b77fe3bSMario Six 
__write_32(u32 * addr,const u32 * val,enum regmap_endianness_t endianness)324*9b77fe3bSMario Six static inline void __write_32(u32 *addr, const u32 *val,
325*9b77fe3bSMario Six 			      enum regmap_endianness_t endianness)
326*9b77fe3bSMario Six {
327*9b77fe3bSMario Six 	switch (endianness) {
328*9b77fe3bSMario Six 	case REGMAP_NATIVE_ENDIAN:
329*9b77fe3bSMario Six 		writel(*val, addr);
330*9b77fe3bSMario Six 		break;
331*9b77fe3bSMario Six 	case REGMAP_LITTLE_ENDIAN:
332*9b77fe3bSMario Six 		out_le32(addr, *val);
333*9b77fe3bSMario Six 		break;
334*9b77fe3bSMario Six 	case REGMAP_BIG_ENDIAN:
335*9b77fe3bSMario Six 		out_be32(addr, *val);
336*9b77fe3bSMario Six 		break;
337*9b77fe3bSMario Six 	}
338*9b77fe3bSMario Six }
339*9b77fe3bSMario Six 
340*9b77fe3bSMario Six #if defined(out_le64) && defined(out_be64) && defined(writeq)
__write_64(u64 * addr,const u64 * val,enum regmap_endianness_t endianness)341*9b77fe3bSMario Six static inline void __write_64(u64 *addr, const u64 *val,
342*9b77fe3bSMario Six 			      enum regmap_endianness_t endianness)
343*9b77fe3bSMario Six {
344*9b77fe3bSMario Six 	switch (endianness) {
345*9b77fe3bSMario Six 	case REGMAP_NATIVE_ENDIAN:
346*9b77fe3bSMario Six 		writeq(*val, addr);
347*9b77fe3bSMario Six 		break;
348*9b77fe3bSMario Six 	case REGMAP_LITTLE_ENDIAN:
349*9b77fe3bSMario Six 		out_le64(addr, *val);
350*9b77fe3bSMario Six 		break;
351*9b77fe3bSMario Six 	case REGMAP_BIG_ENDIAN:
352*9b77fe3bSMario Six 		out_be64(addr, *val);
353*9b77fe3bSMario Six 		break;
354*9b77fe3bSMario Six 	}
355*9b77fe3bSMario Six }
356*9b77fe3bSMario Six #endif
357*9b77fe3bSMario Six 
regmap_raw_write_range(struct regmap * map,uint range_num,uint offset,const void * val,size_t val_len)358d5c7bd98SMario Six int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
359d5c7bd98SMario Six 			   const void *val, size_t val_len)
36084ff8f62SMario Six {
361d5c7bd98SMario Six 	struct regmap_range *range;
36284ff8f62SMario Six 	void *ptr;
36384ff8f62SMario Six 
364d5c7bd98SMario Six 	if (range_num >= map->range_count) {
365d5c7bd98SMario Six 		debug("%s: range index %d larger than range count\n",
366d5c7bd98SMario Six 		      __func__, range_num);
367d5c7bd98SMario Six 		return -ERANGE;
368d5c7bd98SMario Six 	}
369d5c7bd98SMario Six 	range = &map->ranges[range_num];
370d5c7bd98SMario Six 
371d5c7bd98SMario Six 	ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE);
372d5c7bd98SMario Six 
373d5c7bd98SMario Six 	if (offset + val_len > range->size) {
374d5c7bd98SMario Six 		debug("%s: offset/size combination invalid\n", __func__);
375d5c7bd98SMario Six 		return -ERANGE;
376d5c7bd98SMario Six 	}
37784ff8f62SMario Six 
37884ff8f62SMario Six 	switch (val_len) {
37984ff8f62SMario Six 	case REGMAP_SIZE_8:
380*9b77fe3bSMario Six 		__write_8(ptr, val, map->endianness);
38184ff8f62SMario Six 		break;
38284ff8f62SMario Six 	case REGMAP_SIZE_16:
383*9b77fe3bSMario Six 		__write_16(ptr, val, map->endianness);
38484ff8f62SMario Six 		break;
38584ff8f62SMario Six 	case REGMAP_SIZE_32:
386*9b77fe3bSMario Six 		__write_32(ptr, val, map->endianness);
38784ff8f62SMario Six 		break;
388*9b77fe3bSMario Six #if defined(out_le64) && defined(out_be64) && defined(writeq)
38984ff8f62SMario Six 	case REGMAP_SIZE_64:
390*9b77fe3bSMario Six 		__write_64(ptr, val, map->endianness);
39184ff8f62SMario Six 		break;
39284ff8f62SMario Six #endif
39384ff8f62SMario Six 	default:
39484ff8f62SMario Six 		debug("%s: regmap size %zu unknown\n", __func__, val_len);
39584ff8f62SMario Six 		return -EINVAL;
39684ff8f62SMario Six 	}
3973bfb8cb4SPaul Burton 
3983bfb8cb4SPaul Burton 	return 0;
3993bfb8cb4SPaul Burton }
4003bfb8cb4SPaul Burton 
regmap_raw_write(struct regmap * map,uint offset,const void * val,size_t val_len)401d5c7bd98SMario Six int regmap_raw_write(struct regmap *map, uint offset, const void *val,
402d5c7bd98SMario Six 		     size_t val_len)
403d5c7bd98SMario Six {
404d5c7bd98SMario Six 	return regmap_raw_write_range(map, 0, offset, val, val_len);
405d5c7bd98SMario Six }
406d5c7bd98SMario Six 
regmap_write(struct regmap * map,uint offset,uint val)4073bfb8cb4SPaul Burton int regmap_write(struct regmap *map, uint offset, uint val)
4083bfb8cb4SPaul Burton {
40984ff8f62SMario Six 	return regmap_raw_write(map, offset, &val, REGMAP_SIZE_32);
4103bfb8cb4SPaul Burton }
411285cbcf9SNeil Armstrong 
regmap_update_bits(struct regmap * map,uint offset,uint mask,uint val)412285cbcf9SNeil Armstrong int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val)
413285cbcf9SNeil Armstrong {
414285cbcf9SNeil Armstrong 	uint reg;
415285cbcf9SNeil Armstrong 	int ret;
416285cbcf9SNeil Armstrong 
417285cbcf9SNeil Armstrong 	ret = regmap_read(map, offset, &reg);
418285cbcf9SNeil Armstrong 	if (ret)
419285cbcf9SNeil Armstrong 		return ret;
420285cbcf9SNeil Armstrong 
421285cbcf9SNeil Armstrong 	reg &= ~mask;
422285cbcf9SNeil Armstrong 
423285cbcf9SNeil Armstrong 	return regmap_write(map, offset, reg | val);
424285cbcf9SNeil Armstrong }
425