xref: /openbmc/u-boot/include/regmap.h (revision 77c07e7e)
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 #ifndef __REGMAP_H
86f98b750SSimon Glass #define __REGMAP_H
96f98b750SSimon Glass 
106f98b750SSimon Glass /**
11a6d4b060SMario Six  * DOC: Overview
12a6d4b060SMario Six  *
13a6d4b060SMario Six  * Regmaps are an abstraction mechanism that allows device drivers to access
14a6d4b060SMario Six  * register maps irrespective of the underlying bus architecture. This entails
15a6d4b060SMario Six  * that for devices that support multiple busses (e.g. I2C and SPI for a GPIO
16a6d4b060SMario Six  * expander chip) only one driver has to be written. This driver will
17a6d4b060SMario Six  * instantiate a regmap with a backend depending on the bus the device is
18a6d4b060SMario Six  * attached to, and use the regmap API to access the register map through that
19a6d4b060SMario Six  * bus transparently.
20a6d4b060SMario Six  *
21a6d4b060SMario Six  * Read and write functions are supplied, which can read/write data of
22a6d4b060SMario Six  * arbitrary length from/to the regmap.
23a6d4b060SMario Six  *
24a6d4b060SMario Six  * The endianness of regmap accesses is selectable for each map through device
25a6d4b060SMario Six  * tree settings via the boolean "little-endian", "big-endian", and
26a6d4b060SMario Six  * "native-endian" properties.
27a6d4b060SMario Six  *
28a6d4b060SMario Six  * Furthermore, the register map described by a regmap can be split into
29a6d4b060SMario Six  * multiple disjoint areas called ranges. In this way, register maps with
30a6d4b060SMario Six  * "holes", i.e. areas of addressable memory that are not part of the register
31a6d4b060SMario Six  * map, can be accessed in a concise manner.
32a6d4b060SMario Six  *
33a6d4b060SMario Six  * Currently, only a bare "mem" backend for regmaps is supported, which
34a6d4b060SMario Six  * accesses the register map as regular IO-mapped memory.
35a6d4b060SMario Six  */
36a6d4b060SMario Six 
37a6d4b060SMario Six /**
3884ff8f62SMario Six  * enum regmap_size_t - Access sizes for regmap reads and writes
3984ff8f62SMario Six  *
4084ff8f62SMario Six  * @REGMAP_SIZE_8: 8-bit read/write access size
4184ff8f62SMario Six  * @REGMAP_SIZE_16: 16-bit read/write access size
4284ff8f62SMario Six  * @REGMAP_SIZE_32: 32-bit read/write access size
4384ff8f62SMario Six  * @REGMAP_SIZE_64: 64-bit read/write access size
4484ff8f62SMario Six  */
4584ff8f62SMario Six enum regmap_size_t {
4684ff8f62SMario Six 	REGMAP_SIZE_8 = 1,
4784ff8f62SMario Six 	REGMAP_SIZE_16 = 2,
4884ff8f62SMario Six 	REGMAP_SIZE_32 = 4,
4984ff8f62SMario Six 	REGMAP_SIZE_64 = 8,
5084ff8f62SMario Six };
5184ff8f62SMario Six 
5284ff8f62SMario Six /**
539b77fe3bSMario Six  * enum regmap_endianness_t - Endianness for regmap reads and writes
549b77fe3bSMario Six  *
559b77fe3bSMario Six  * @REGMAP_NATIVE_ENDIAN: Native endian read/write accesses
569b77fe3bSMario Six  * @REGMAP_LITTLE_ENDIAN: Little endian read/write accesses
579b77fe3bSMario Six  * @REGMAP_BIG_ENDIAN: Big endian read/write accesses
589b77fe3bSMario Six  */
599b77fe3bSMario Six enum regmap_endianness_t {
609b77fe3bSMario Six 	REGMAP_NATIVE_ENDIAN,
619b77fe3bSMario Six 	REGMAP_LITTLE_ENDIAN,
629b77fe3bSMario Six 	REGMAP_BIG_ENDIAN,
639b77fe3bSMario Six };
649b77fe3bSMario Six 
659b77fe3bSMario Six /**
666f98b750SSimon Glass  * struct regmap_range - a register map range
676f98b750SSimon Glass  *
686f98b750SSimon Glass  * @start:	Start address
696f98b750SSimon Glass  * @size:	Size in bytes
706f98b750SSimon Glass  */
716f98b750SSimon Glass struct regmap_range {
726f98b750SSimon Glass 	ulong start;
736f98b750SSimon Glass 	ulong size;
746f98b750SSimon Glass };
756f98b750SSimon Glass 
766f98b750SSimon Glass /**
776f98b750SSimon Glass  * struct regmap - a way of accessing hardware/bus registers
786f98b750SSimon Glass  *
796f98b750SSimon Glass  * @range_count:	Number of ranges available within the map
808c1de5e0SMasahiro Yamada  * @ranges:		Array of ranges
816f98b750SSimon Glass  */
826f98b750SSimon Glass struct regmap {
839b77fe3bSMario Six 	enum regmap_endianness_t endianness;
846f98b750SSimon Glass 	int range_count;
858c1de5e0SMasahiro Yamada 	struct regmap_range ranges[0];
866f98b750SSimon Glass };
876f98b750SSimon Glass 
886f98b750SSimon Glass /*
896f98b750SSimon Glass  * Interface to provide access to registers either through a direct memory
906f98b750SSimon Glass  * bus or through a peripheral bus like I2C, SPI.
916f98b750SSimon Glass  */
92604b6696SMario Six 
93604b6696SMario Six /**
94604b6696SMario Six  * regmap_write() - Write a 32-bit value to a regmap
95604b6696SMario Six  *
96604b6696SMario Six  * @map:	Regmap to write to
97604b6696SMario Six  * @offset:	Offset in the regmap to write to
98604b6696SMario Six  * @val:	Data to write to the regmap at the specified offset
99604b6696SMario Six  *
10084ff8f62SMario Six  * Note that this function will only write values of 32 bit width to the
10184ff8f62SMario Six  * regmap; if the size of data to be read is different, the regmap_raw_write
10284ff8f62SMario Six  * function can be used.
10384ff8f62SMario Six  *
104604b6696SMario Six  * Return: 0 if OK, -ve on error
105604b6696SMario Six  */
1066f98b750SSimon Glass int regmap_write(struct regmap *map, uint offset, uint val);
107604b6696SMario Six 
108604b6696SMario Six /**
109604b6696SMario Six  * regmap_read() - Read a 32-bit value from a regmap
110604b6696SMario Six  *
111604b6696SMario Six  * @map:	Regmap to read from
112604b6696SMario Six  * @offset:	Offset in the regmap to read from
113604b6696SMario Six  * @valp:	Pointer to the buffer to receive the data read from the regmap
114604b6696SMario Six  *		at the specified offset
115604b6696SMario Six  *
11684ff8f62SMario Six  * Note that this function will only read values of 32 bit width from the
11784ff8f62SMario Six  * regmap; if the size of data to be read is different, the regmap_raw_read
11884ff8f62SMario Six  * function can be used.
11984ff8f62SMario Six  *
120604b6696SMario Six  * Return: 0 if OK, -ve on error
121604b6696SMario Six  */
1226f98b750SSimon Glass int regmap_read(struct regmap *map, uint offset, uint *valp);
1236f98b750SSimon Glass 
12484ff8f62SMario Six /**
12584ff8f62SMario Six  * regmap_raw_write() - Write a value of specified length to a regmap
12684ff8f62SMario Six  *
12784ff8f62SMario Six  * @map:	Regmap to write to
12884ff8f62SMario Six  * @offset:	Offset in the regmap to write to
12984ff8f62SMario Six  * @val:	Value to write to the regmap at the specified offset
13084ff8f62SMario Six  * @val_len:	Length of the data to be written to the regmap
13184ff8f62SMario Six  *
13284ff8f62SMario Six  * Note that this function will, as opposed to regmap_write, write data of
13384ff8f62SMario Six  * arbitrary length to the regmap, and not just 32-bit values, and is thus a
13484ff8f62SMario Six  * generalized version of regmap_write.
13584ff8f62SMario Six  *
13684ff8f62SMario Six  * Return: 0 if OK, -ve on error
13784ff8f62SMario Six  */
13884ff8f62SMario Six int regmap_raw_write(struct regmap *map, uint offset, const void *val,
13984ff8f62SMario Six 		     size_t val_len);
14084ff8f62SMario Six 
14184ff8f62SMario Six /**
14284ff8f62SMario Six  * regmap_raw_read() - Read a value of specified length from a regmap
14384ff8f62SMario Six  *
14484ff8f62SMario Six  * @map:	Regmap to read from
14584ff8f62SMario Six  * @offset:	Offset in the regmap to read from
14684ff8f62SMario Six  * @valp:	Pointer to the buffer to receive the data read from the regmap
14784ff8f62SMario Six  *		at the specified offset
14884ff8f62SMario Six  * @val_len:	Length of the data to be read from the regmap
14984ff8f62SMario Six  *
15084ff8f62SMario Six  * Note that this function will, as opposed to regmap_read, read data of
15184ff8f62SMario Six  * arbitrary length from the regmap, and not just 32-bit values, and is thus a
15284ff8f62SMario Six  * generalized version of regmap_read.
15384ff8f62SMario Six  *
15484ff8f62SMario Six  * Return: 0 if OK, -ve on error
15584ff8f62SMario Six  */
15684ff8f62SMario Six int regmap_raw_read(struct regmap *map, uint offset, void *valp,
15784ff8f62SMario Six 		    size_t val_len);
15884ff8f62SMario Six 
159d5c7bd98SMario Six /**
160d5c7bd98SMario Six  * regmap_raw_write_range() - Write a value of specified length to a range of a
161d5c7bd98SMario Six  *			      regmap
162d5c7bd98SMario Six  *
163d5c7bd98SMario Six  * @map:	Regmap to write to
164d5c7bd98SMario Six  * @range_num:	Number of the range in the regmap to write to
165d5c7bd98SMario Six  * @offset:	Offset in the regmap to write to
166d5c7bd98SMario Six  * @val:	Value to write to the regmap at the specified offset
167d5c7bd98SMario Six  * @val_len:	Length of the data to be written to the regmap
168d5c7bd98SMario Six  *
169d5c7bd98SMario Six  * Return: 0 if OK, -ve on error
170d5c7bd98SMario Six  */
171d5c7bd98SMario Six int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset,
172d5c7bd98SMario Six 			   const void *val, size_t val_len);
173d5c7bd98SMario Six 
174d5c7bd98SMario Six /**
175d5c7bd98SMario Six  * regmap_raw_read_range() - Read a value of specified length from a range of a
176d5c7bd98SMario Six  *			     regmap
177d5c7bd98SMario Six  *
178d5c7bd98SMario Six  * @map:	Regmap to read from
179d5c7bd98SMario Six  * @range_num:	Number of the range in the regmap to write to
180d5c7bd98SMario Six  * @offset:	Offset in the regmap to read from
181d5c7bd98SMario Six  * @valp:	Pointer to the buffer to receive the data read from the regmap
182d5c7bd98SMario Six  *		at the specified offset
183d5c7bd98SMario Six  * @val_len:	Length of the data to be read from the regmap
184d5c7bd98SMario Six  *
185d5c7bd98SMario Six  * Return: 0 if OK, -ve on error
186d5c7bd98SMario Six  */
187d5c7bd98SMario Six int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset,
188d5c7bd98SMario Six 			  void *valp, size_t val_len);
189d5c7bd98SMario Six 
190e936397aSMario Six /**
191e936397aSMario Six  * regmap_range_set() - Set a value in a regmap range described by a struct
192e936397aSMario Six  * @map:    Regmap in which a value should be set
193e936397aSMario Six  * @range:  Range of the regmap in which a value should be set
194e936397aSMario Six  * @type:   Structure type that describes the memory layout of the regmap range
195e936397aSMario Six  * @member: Member of the describing structure that should be set in the regmap
196e936397aSMario Six  *          range
197e936397aSMario Six  * @val:    Value which should be written to the regmap range
198e936397aSMario Six  */
199e936397aSMario Six #define regmap_range_set(map, range, type, member, val) \
200e936397aSMario Six 	do { \
201e936397aSMario Six 		typeof(((type *)0)->member) __tmp = val; \
202e936397aSMario Six 		regmap_raw_write_range(map, range, offsetof(type, member), \
203e936397aSMario Six 				       &__tmp, sizeof(((type *)0)->member)); \
204e936397aSMario Six 	} while (0)
2056f98b750SSimon Glass 
206e936397aSMario Six /**
207e936397aSMario Six  * regmap_set() - Set a value in a regmap described by a struct
208e936397aSMario Six  * @map:    Regmap in which a value should be set
209e936397aSMario Six  * @type:   Structure type that describes the memory layout of the regmap
210e936397aSMario Six  * @member: Member of the describing structure that should be set in the regmap
211e936397aSMario Six  * @val:    Value which should be written to the regmap
212e936397aSMario Six  */
213e936397aSMario Six #define regmap_set(map, type, member, val) \
214e936397aSMario Six 	regmap_range_set(map, 0, type, member, val)
215e936397aSMario Six 
216e936397aSMario Six /**
217e936397aSMario Six  * regmap_range_get() - Get a value from a regmap range described by a struct
218e936397aSMario Six  * @map:    Regmap from which a value should be read
219e936397aSMario Six  * @range:  Range of the regmap from which a value should be read
220e936397aSMario Six  * @type:   Structure type that describes the memory layout of the regmap
221e936397aSMario Six  *          range
222e936397aSMario Six  * @member: Member of the describing structure that should be read in the
223e936397aSMario Six  *          regmap range
224e936397aSMario Six  * @valp:   Variable that receives the value read from the regmap range
225e936397aSMario Six  */
226e936397aSMario Six #define regmap_range_get(map, range, type, member, valp) \
227e936397aSMario Six 	regmap_raw_read_range(map, range, offsetof(type, member), \
228e936397aSMario Six 			      (void *)valp, sizeof(((type *)0)->member))
229e936397aSMario Six 
230e936397aSMario Six /**
231e936397aSMario Six  * regmap_get() - Get a value from a regmap described by a struct
232e936397aSMario Six  * @map:    Regmap from which a value should be read
233e936397aSMario Six  * @type:   Structure type that describes the memory layout of the regmap
234e936397aSMario Six  *          range
235e936397aSMario Six  * @member: Member of the describing structure that should be read in the
236e936397aSMario Six  *          regmap
237e936397aSMario Six  * @valp:   Variable that receives the value read from the regmap
238e936397aSMario Six  */
239e936397aSMario Six #define regmap_get(map, type, member, valp) \
240e936397aSMario Six 	regmap_range_get(map, 0, type, member, valp)
2416f98b750SSimon Glass 
2426f98b750SSimon Glass /**
243d13801efSNeil Armstrong  * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs
244d13801efSNeil Armstrong  *
245d13801efSNeil Armstrong  * @map:	Regmap to read from
246d13801efSNeil Armstrong  * @addr:	Offset to poll
247d13801efSNeil Armstrong  * @val:	Unsigned integer variable to read the value into
248d13801efSNeil Armstrong  * @cond:	Break condition (usually involving @val)
249d13801efSNeil Armstrong  * @sleep_us:	Maximum time to sleep between reads in us (0 tight-loops).
250d13801efSNeil Armstrong  * @timeout_ms:	Timeout in ms, 0 means never timeout
251*df9cf1ccSSimon Glass  * @test_add_time: Used for sandbox testing - amount of time to add after
252*df9cf1ccSSimon Glass  *		starting the loop (0 if not testing)
253d13801efSNeil Armstrong  *
254d13801efSNeil Armstrong  * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
255d13801efSNeil Armstrong  * error return value in case of a error read. In the two former cases,
256d13801efSNeil Armstrong  * the last read value at @addr is stored in @val. Must not be called
257d13801efSNeil Armstrong  * from atomic context if sleep_us or timeout_us are used.
258d13801efSNeil Armstrong  *
259d13801efSNeil Armstrong  * This is modelled after the regmap_read_poll_timeout macros in linux but
260d13801efSNeil Armstrong  * with millisecond timeout.
261*df9cf1ccSSimon Glass  *
262*df9cf1ccSSimon Glass  * The _test version is for sandbox testing only. Do not use this in normal
263*df9cf1ccSSimon Glass  * code as it advances the timer.
264d13801efSNeil Armstrong  */
265*df9cf1ccSSimon Glass #define regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \
266*df9cf1ccSSimon Glass 				      timeout_ms, test_add_time) \
267d13801efSNeil Armstrong ({ \
268d13801efSNeil Armstrong 	unsigned long __start = get_timer(0); \
269d13801efSNeil Armstrong 	int __ret; \
270d13801efSNeil Armstrong 	for (;;) { \
271d13801efSNeil Armstrong 		__ret = regmap_read((map), (addr), &(val)); \
272d13801efSNeil Armstrong 		if (__ret) \
273d13801efSNeil Armstrong 			break; \
274d13801efSNeil Armstrong 		if (cond) \
275d13801efSNeil Armstrong 			break; \
276*df9cf1ccSSimon Glass 		if (IS_ENABLED(CONFIG_SANDBOX) && test_add_time) \
277*df9cf1ccSSimon Glass 			sandbox_timer_add_offset(test_add_time); \
278d13801efSNeil Armstrong 		if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \
279d13801efSNeil Armstrong 			__ret = regmap_read((map), (addr), &(val)); \
280d13801efSNeil Armstrong 			break; \
281d13801efSNeil Armstrong 		} \
282d13801efSNeil Armstrong 		if ((sleep_us)) \
283d13801efSNeil Armstrong 			udelay((sleep_us)); \
284d13801efSNeil Armstrong 	} \
285d13801efSNeil Armstrong 	__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
286d13801efSNeil Armstrong })
287d13801efSNeil Armstrong 
288*df9cf1ccSSimon Glass #define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_ms) \
289*df9cf1ccSSimon Glass 	regmap_read_poll_timeout_test(map, addr, val, cond, sleep_us, \
290*df9cf1ccSSimon Glass 				      timeout_ms, 0) \
291*df9cf1ccSSimon Glass 
292d13801efSNeil Armstrong /**
293285cbcf9SNeil Armstrong  * regmap_update_bits() - Perform a read/modify/write using a mask
294285cbcf9SNeil Armstrong  *
295285cbcf9SNeil Armstrong  * @map:	The map returned by regmap_init_mem*()
296285cbcf9SNeil Armstrong  * @offset:	Offset of the memory
297285cbcf9SNeil Armstrong  * @mask:	Mask to apply to the read value
298285cbcf9SNeil Armstrong  * @val:	Value to apply to the value to write
299604b6696SMario Six  * Return: 0 if OK, -ve on error
300285cbcf9SNeil Armstrong  */
301285cbcf9SNeil Armstrong int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val);
302285cbcf9SNeil Armstrong 
303285cbcf9SNeil Armstrong /**
3046f98b750SSimon Glass  * regmap_init_mem() - Set up a new register map that uses memory access
3056f98b750SSimon Glass  *
306d3581236SMasahiro Yamada  * @node:	Device node that uses this map
3076f98b750SSimon Glass  * @mapp:	Returns allocated map
308604b6696SMario Six  * Return: 0 if OK, -ve on error
309604b6696SMario Six  *
310604b6696SMario Six  * Use regmap_uninit() to free it.
3116f98b750SSimon Glass  */
312d3581236SMasahiro Yamada int regmap_init_mem(ofnode node, struct regmap **mapp);
3136f98b750SSimon Glass 
3141e6ca1a6SSimon Glass /**
315604b6696SMario Six  * regmap_init_mem_platdata() - Set up a new memory register map for
316604b6696SMario Six  *				of-platdata
317604b6696SMario Six  *
318604b6696SMario Six  * @dev:	Device that uses this map
319604b6696SMario Six  * @reg:	List of address, size pairs
320604b6696SMario Six  * @count:	Number of pairs (e.g. 1 if the regmap has a single entry)
321604b6696SMario Six  * @mapp:	Returns allocated map
322604b6696SMario Six  * Return: 0 if OK, -ve on error
3231e6ca1a6SSimon Glass  *
3241e6ca1a6SSimon Glass  * This creates a new regmap with a list of regions passed in, rather than
3251e6ca1a6SSimon Glass  * using the device tree. It only supports 32-bit machines.
3261e6ca1a6SSimon Glass  *
3271e6ca1a6SSimon Glass  * Use regmap_uninit() to free it.
3281e6ca1a6SSimon Glass  *
3291e6ca1a6SSimon Glass  */
330c20ee0edSSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
3313b2a29e0SSimon Glass 			     struct regmap **mapp);
3323b2a29e0SSimon Glass 
3336f98b750SSimon Glass /**
3346f98b750SSimon Glass  * regmap_get_range() - Obtain the base memory address of a regmap range
3356f98b750SSimon Glass  *
3366f98b750SSimon Glass  * @map:	Regmap to query
3376f98b750SSimon Glass  * @range_num:	Range to look up
338604b6696SMario Six  * Return: Pointer to the range in question if OK, NULL on error
3396f98b750SSimon Glass  */
3406f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num);
3416f98b750SSimon Glass 
3426f98b750SSimon Glass /**
3436f98b750SSimon Glass  * regmap_uninit() - free a previously inited regmap
344604b6696SMario Six  *
345604b6696SMario Six  * @map:	Regmap to free
346604b6696SMario Six  * Return: 0 if OK, -ve on error
3476f98b750SSimon Glass  */
3486f98b750SSimon Glass int regmap_uninit(struct regmap *map);
3496f98b750SSimon Glass 
3506f98b750SSimon Glass #endif
351