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