xref: /rk3399_rockchip-uboot/include/regmap.h (revision 7ad3d56782ea430c5b03fc7e28428e5ee332b3e6)
16f98b750SSimon Glass /*
26f98b750SSimon Glass  * Copyright (c) 2015 Google, Inc
36f98b750SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
46f98b750SSimon Glass  *
56f98b750SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
66f98b750SSimon Glass  */
76f98b750SSimon Glass 
86f98b750SSimon Glass #ifndef __REGMAP_H
96f98b750SSimon Glass #define __REGMAP_H
106f98b750SSimon Glass 
116f98b750SSimon Glass /**
126f98b750SSimon Glass  * struct regmap_range - a register map range
136f98b750SSimon Glass  *
146f98b750SSimon Glass  * @start:	Start address
156f98b750SSimon Glass  * @size:	Size in bytes
166f98b750SSimon Glass  */
176f98b750SSimon Glass struct regmap_range {
186f98b750SSimon Glass 	ulong start;
196f98b750SSimon Glass 	ulong size;
206f98b750SSimon Glass };
216f98b750SSimon Glass 
226f98b750SSimon Glass /**
236f98b750SSimon Glass  * struct regmap - a way of accessing hardware/bus registers
246f98b750SSimon Glass  *
256f98b750SSimon Glass  * @base:	Base address of register map
266f98b750SSimon Glass  * @range_count: Number of ranges available within the map
276f98b750SSimon Glass  * @range:	Pointer to the list of ranges, allocated if @range_count > 1
286f98b750SSimon Glass  * @base_range:	If @range_count is <= 1, @range points here
296f98b750SSimon Glass  */
306f98b750SSimon Glass struct regmap {
316f98b750SSimon Glass 	phys_addr_t base;
326f98b750SSimon Glass 	int range_count;
336f98b750SSimon Glass 	struct regmap_range *range, base_range;
346f98b750SSimon Glass };
356f98b750SSimon Glass 
366f98b750SSimon Glass /*
376f98b750SSimon Glass  * Interface to provide access to registers either through a direct memory
386f98b750SSimon Glass  * bus or through a peripheral bus like I2C, SPI.
396f98b750SSimon Glass  */
406f98b750SSimon Glass int regmap_write(struct regmap *map, uint offset, uint val);
416f98b750SSimon Glass int regmap_read(struct regmap *map, uint offset, uint *valp);
426f98b750SSimon Glass 
436f98b750SSimon Glass #define regmap_write32(map, ptr, member, val) \
446f98b750SSimon Glass 	regmap_write(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), val)
456f98b750SSimon Glass 
466f98b750SSimon Glass #define regmap_read32(map, ptr, member, valp) \
476f98b750SSimon Glass 	regmap_read(map, (uint32_t *)(ptr)->member - (uint32_t *)(ptr), valp)
486f98b750SSimon Glass 
496f98b750SSimon Glass /**
50cd4cabecSNeil Armstrong  * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs
51cd4cabecSNeil Armstrong  *
52cd4cabecSNeil Armstrong  * @map:	Regmap to read from
53cd4cabecSNeil Armstrong  * @addr:	Offset to poll
54cd4cabecSNeil Armstrong  * @val:	Unsigned integer variable to read the value into
55cd4cabecSNeil Armstrong  * @cond:	Break condition (usually involving @val)
56cd4cabecSNeil Armstrong  * @sleep_us:	Maximum time to sleep between reads in us (0 tight-loops).
57cd4cabecSNeil Armstrong  * @timeout_ms:	Timeout in ms, 0 means never timeout
58cd4cabecSNeil Armstrong  *
59cd4cabecSNeil Armstrong  * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read
60cd4cabecSNeil Armstrong  * error return value in case of a error read. In the two former cases,
61cd4cabecSNeil Armstrong  * the last read value at @addr is stored in @val. Must not be called
62cd4cabecSNeil Armstrong  * from atomic context if sleep_us or timeout_us are used.
63cd4cabecSNeil Armstrong  *
64cd4cabecSNeil Armstrong  * This is modelled after the regmap_read_poll_timeout macros in linux but
65cd4cabecSNeil Armstrong  * with millisecond timeout.
66cd4cabecSNeil Armstrong  */
67cd4cabecSNeil Armstrong #define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_ms) \
68cd4cabecSNeil Armstrong ({ \
69cd4cabecSNeil Armstrong 	unsigned long __start = get_timer(0); \
70cd4cabecSNeil Armstrong 	int __ret; \
71cd4cabecSNeil Armstrong 	for (;;) { \
72cd4cabecSNeil Armstrong 		__ret = regmap_read((map), (addr), &(val)); \
73cd4cabecSNeil Armstrong 		if (__ret) \
74cd4cabecSNeil Armstrong 			break; \
75cd4cabecSNeil Armstrong 		if (cond) \
76cd4cabecSNeil Armstrong 			break; \
77cd4cabecSNeil Armstrong 		if ((timeout_ms) && get_timer(__start) > (timeout_ms)) { \
78cd4cabecSNeil Armstrong 			__ret = regmap_read((map), (addr), &(val)); \
79cd4cabecSNeil Armstrong 			break; \
80cd4cabecSNeil Armstrong 		} \
81cd4cabecSNeil Armstrong 		if ((sleep_us)) \
82cd4cabecSNeil Armstrong 			udelay((sleep_us)); \
83cd4cabecSNeil Armstrong 	} \
84cd4cabecSNeil Armstrong 	__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
85cd4cabecSNeil Armstrong })
86cd4cabecSNeil Armstrong 
87cd4cabecSNeil Armstrong /**
88*7ad3d567SNeil Armstrong  * regmap_update_bits() - Perform a read/modify/write using a mask
89*7ad3d567SNeil Armstrong  *
90*7ad3d567SNeil Armstrong  * @map:	The map returned by regmap_init_mem*()
91*7ad3d567SNeil Armstrong  * @offset:	Offset of the memory
92*7ad3d567SNeil Armstrong  * @mask:	Mask to apply to the read value
93*7ad3d567SNeil Armstrong  * @val:	Value to apply to the value to write
94*7ad3d567SNeil Armstrong  */
95*7ad3d567SNeil Armstrong int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val);
96*7ad3d567SNeil Armstrong 
97*7ad3d567SNeil Armstrong /**
986f98b750SSimon Glass  * regmap_init_mem() - Set up a new register map that uses memory access
996f98b750SSimon Glass  *
1006f98b750SSimon Glass  * Use regmap_uninit() to free it.
1016f98b750SSimon Glass  *
1026f98b750SSimon Glass  * @dev:	Device that uses this map
1036f98b750SSimon Glass  * @mapp:	Returns allocated map
1046f98b750SSimon Glass  */
1056f98b750SSimon Glass int regmap_init_mem(struct udevice *dev, struct regmap **mapp);
1066f98b750SSimon Glass 
1071e6ca1a6SSimon Glass /**
1081e6ca1a6SSimon Glass  * regmap_init_mem_platdata() - Set up a new memory register map for of-platdata
1091e6ca1a6SSimon Glass  *
1101e6ca1a6SSimon Glass  * This creates a new regmap with a list of regions passed in, rather than
1111e6ca1a6SSimon Glass  * using the device tree. It only supports 32-bit machines.
1121e6ca1a6SSimon Glass  *
1131e6ca1a6SSimon Glass  * Use regmap_uninit() to free it.
1141e6ca1a6SSimon Glass  *
1151e6ca1a6SSimon Glass  * @dev:	Device that uses this map
1161e6ca1a6SSimon Glass  * @reg:	List of address, size pairs
1171e6ca1a6SSimon Glass  * @count:	Number of pairs (e.g. 1 if the regmap has a single entry)
1181e6ca1a6SSimon Glass  * @mapp:	Returns allocated map
1191e6ca1a6SSimon Glass  */
120a28bfcc3SSimon Glass int regmap_init_mem_platdata(struct udevice *dev, fdt_val_t *reg, int count,
1213b2a29e0SSimon Glass 			     struct regmap **mapp);
1223b2a29e0SSimon Glass 
1236f98b750SSimon Glass /**
1246f98b750SSimon Glass  * regmap_get_range() - Obtain the base memory address of a regmap range
1256f98b750SSimon Glass  *
1266f98b750SSimon Glass  * @map:	Regmap to query
1276f98b750SSimon Glass  * @range_num:	Range to look up
1286f98b750SSimon Glass  */
1296f98b750SSimon Glass void *regmap_get_range(struct regmap *map, unsigned int range_num);
1306f98b750SSimon Glass 
1316f98b750SSimon Glass /**
1326f98b750SSimon Glass  * regmap_uninit() - free a previously inited regmap
1336f98b750SSimon Glass  */
1346f98b750SSimon Glass int regmap_uninit(struct regmap *map);
1356f98b750SSimon Glass 
1366f98b750SSimon Glass #endif
137