1b83a313bSMark Brown /* 2b83a313bSMark Brown * Register map access API 3b83a313bSMark Brown * 4b83a313bSMark Brown * Copyright 2011 Wolfson Microelectronics plc 5b83a313bSMark Brown * 6b83a313bSMark Brown * Author: Mark Brown <[email protected]> 7b83a313bSMark Brown * 8b83a313bSMark Brown * This program is free software; you can redistribute it and/or modify 9b83a313bSMark Brown * it under the terms of the GNU General Public License version 2 as 10b83a313bSMark Brown * published by the Free Software Foundation. 11b83a313bSMark Brown */ 12b83a313bSMark Brown 13b83a313bSMark Brown #include <linux/slab.h> 14b83a313bSMark Brown #include <linux/module.h> 15b83a313bSMark Brown #include <linux/mutex.h> 16b83a313bSMark Brown #include <linux/err.h> 17b83a313bSMark Brown 18fb2736bbSMark Brown #define CREATE_TRACE_POINTS 19fb2736bbSMark Brown #include <trace/events/regmap.h> 20fb2736bbSMark Brown 2193de9124SMark Brown #include "internal.h" 22b83a313bSMark Brown 238de2f081SMark Brown bool regmap_writeable(struct regmap *map, unsigned int reg) 248de2f081SMark Brown { 258de2f081SMark Brown if (map->max_register && reg > map->max_register) 268de2f081SMark Brown return false; 278de2f081SMark Brown 288de2f081SMark Brown if (map->writeable_reg) 298de2f081SMark Brown return map->writeable_reg(map->dev, reg); 308de2f081SMark Brown 318de2f081SMark Brown return true; 328de2f081SMark Brown } 338de2f081SMark Brown 348de2f081SMark Brown bool regmap_readable(struct regmap *map, unsigned int reg) 358de2f081SMark Brown { 368de2f081SMark Brown if (map->max_register && reg > map->max_register) 378de2f081SMark Brown return false; 388de2f081SMark Brown 398de2f081SMark Brown if (map->readable_reg) 408de2f081SMark Brown return map->readable_reg(map->dev, reg); 418de2f081SMark Brown 428de2f081SMark Brown return true; 438de2f081SMark Brown } 448de2f081SMark Brown 458de2f081SMark Brown bool regmap_volatile(struct regmap *map, unsigned int reg) 468de2f081SMark Brown { 478de2f081SMark Brown if (map->max_register && reg > map->max_register) 488de2f081SMark Brown return false; 498de2f081SMark Brown 508de2f081SMark Brown if (map->volatile_reg) 518de2f081SMark Brown return map->volatile_reg(map->dev, reg); 528de2f081SMark Brown 538de2f081SMark Brown return true; 548de2f081SMark Brown } 558de2f081SMark Brown 568de2f081SMark Brown bool regmap_precious(struct regmap *map, unsigned int reg) 578de2f081SMark Brown { 588de2f081SMark Brown if (map->max_register && reg > map->max_register) 598de2f081SMark Brown return false; 608de2f081SMark Brown 618de2f081SMark Brown if (map->precious_reg) 628de2f081SMark Brown return map->precious_reg(map->dev, reg); 638de2f081SMark Brown 648de2f081SMark Brown return false; 658de2f081SMark Brown } 668de2f081SMark Brown 6782cd9965SLars-Peter Clausen static bool regmap_volatile_range(struct regmap *map, unsigned int reg, 6882cd9965SLars-Peter Clausen unsigned int num) 6982cd9965SLars-Peter Clausen { 7082cd9965SLars-Peter Clausen unsigned int i; 7182cd9965SLars-Peter Clausen 7282cd9965SLars-Peter Clausen for (i = 0; i < num; i++) 7382cd9965SLars-Peter Clausen if (!regmap_volatile(map, reg + i)) 7482cd9965SLars-Peter Clausen return false; 7582cd9965SLars-Peter Clausen 7682cd9965SLars-Peter Clausen return true; 7782cd9965SLars-Peter Clausen } 7882cd9965SLars-Peter Clausen 79b83a313bSMark Brown static void regmap_format_4_12_write(struct regmap *map, 80b83a313bSMark Brown unsigned int reg, unsigned int val) 81b83a313bSMark Brown { 82b83a313bSMark Brown __be16 *out = map->work_buf; 83b83a313bSMark Brown *out = cpu_to_be16((reg << 12) | val); 84b83a313bSMark Brown } 85b83a313bSMark Brown 86b83a313bSMark Brown static void regmap_format_7_9_write(struct regmap *map, 87b83a313bSMark Brown unsigned int reg, unsigned int val) 88b83a313bSMark Brown { 89b83a313bSMark Brown __be16 *out = map->work_buf; 90b83a313bSMark Brown *out = cpu_to_be16((reg << 9) | val); 91b83a313bSMark Brown } 92b83a313bSMark Brown 937e5ec63eSLars-Peter Clausen static void regmap_format_10_14_write(struct regmap *map, 947e5ec63eSLars-Peter Clausen unsigned int reg, unsigned int val) 957e5ec63eSLars-Peter Clausen { 967e5ec63eSLars-Peter Clausen u8 *out = map->work_buf; 977e5ec63eSLars-Peter Clausen 987e5ec63eSLars-Peter Clausen out[2] = val; 997e5ec63eSLars-Peter Clausen out[1] = (val >> 8) | (reg << 6); 1007e5ec63eSLars-Peter Clausen out[0] = reg >> 2; 1017e5ec63eSLars-Peter Clausen } 1027e5ec63eSLars-Peter Clausen 103b83a313bSMark Brown static void regmap_format_8(void *buf, unsigned int val) 104b83a313bSMark Brown { 105b83a313bSMark Brown u8 *b = buf; 106b83a313bSMark Brown 107b83a313bSMark Brown b[0] = val; 108b83a313bSMark Brown } 109b83a313bSMark Brown 110b83a313bSMark Brown static void regmap_format_16(void *buf, unsigned int val) 111b83a313bSMark Brown { 112b83a313bSMark Brown __be16 *b = buf; 113b83a313bSMark Brown 114b83a313bSMark Brown b[0] = cpu_to_be16(val); 115b83a313bSMark Brown } 116b83a313bSMark Brown 117b83a313bSMark Brown static unsigned int regmap_parse_8(void *buf) 118b83a313bSMark Brown { 119b83a313bSMark Brown u8 *b = buf; 120b83a313bSMark Brown 121b83a313bSMark Brown return b[0]; 122b83a313bSMark Brown } 123b83a313bSMark Brown 124b83a313bSMark Brown static unsigned int regmap_parse_16(void *buf) 125b83a313bSMark Brown { 126b83a313bSMark Brown __be16 *b = buf; 127b83a313bSMark Brown 128b83a313bSMark Brown b[0] = be16_to_cpu(b[0]); 129b83a313bSMark Brown 130b83a313bSMark Brown return b[0]; 131b83a313bSMark Brown } 132b83a313bSMark Brown 133b83a313bSMark Brown /** 134b83a313bSMark Brown * regmap_init(): Initialise register map 135b83a313bSMark Brown * 136b83a313bSMark Brown * @dev: Device that will be interacted with 137b83a313bSMark Brown * @bus: Bus-specific callbacks to use with device 138b83a313bSMark Brown * @config: Configuration for register map 139b83a313bSMark Brown * 140b83a313bSMark Brown * The return value will be an ERR_PTR() on error or a valid pointer to 141b83a313bSMark Brown * a struct regmap. This function should generally not be called 142b83a313bSMark Brown * directly, it should be called by bus-specific init functions. 143b83a313bSMark Brown */ 144b83a313bSMark Brown struct regmap *regmap_init(struct device *dev, 145b83a313bSMark Brown const struct regmap_bus *bus, 146b83a313bSMark Brown const struct regmap_config *config) 147b83a313bSMark Brown { 148b83a313bSMark Brown struct regmap *map; 149b83a313bSMark Brown int ret = -EINVAL; 150b83a313bSMark Brown 151b83a313bSMark Brown if (!bus || !config) 152abbb18fbSLars-Peter Clausen goto err; 153b83a313bSMark Brown 154b83a313bSMark Brown map = kzalloc(sizeof(*map), GFP_KERNEL); 155b83a313bSMark Brown if (map == NULL) { 156b83a313bSMark Brown ret = -ENOMEM; 157b83a313bSMark Brown goto err; 158b83a313bSMark Brown } 159b83a313bSMark Brown 160b83a313bSMark Brown mutex_init(&map->lock); 161b83a313bSMark Brown map->format.buf_size = (config->reg_bits + config->val_bits) / 8; 162b83a313bSMark Brown map->format.reg_bytes = config->reg_bits / 8; 163b83a313bSMark Brown map->format.val_bytes = config->val_bits / 8; 164b83a313bSMark Brown map->dev = dev; 165b83a313bSMark Brown map->bus = bus; 1662e2ae66dSMark Brown map->max_register = config->max_register; 1672e2ae66dSMark Brown map->writeable_reg = config->writeable_reg; 1682e2ae66dSMark Brown map->readable_reg = config->readable_reg; 1692e2ae66dSMark Brown map->volatile_reg = config->volatile_reg; 1702efe1642SMark Brown map->precious_reg = config->precious_reg; 1715d1729e7SDimitris Papastamos map->cache_type = config->cache_type; 172b83a313bSMark Brown 1736f306441SLars-Peter Clausen if (config->read_flag_mask || config->write_flag_mask) { 1746f306441SLars-Peter Clausen map->read_flag_mask = config->read_flag_mask; 1756f306441SLars-Peter Clausen map->write_flag_mask = config->write_flag_mask; 1766f306441SLars-Peter Clausen } else { 1776f306441SLars-Peter Clausen map->read_flag_mask = bus->read_flag_mask; 1786f306441SLars-Peter Clausen } 1796f306441SLars-Peter Clausen 180b83a313bSMark Brown switch (config->reg_bits) { 181b83a313bSMark Brown case 4: 182b83a313bSMark Brown switch (config->val_bits) { 183b83a313bSMark Brown case 12: 184b83a313bSMark Brown map->format.format_write = regmap_format_4_12_write; 185b83a313bSMark Brown break; 186b83a313bSMark Brown default: 187b83a313bSMark Brown goto err_map; 188b83a313bSMark Brown } 189b83a313bSMark Brown break; 190b83a313bSMark Brown 191b83a313bSMark Brown case 7: 192b83a313bSMark Brown switch (config->val_bits) { 193b83a313bSMark Brown case 9: 194b83a313bSMark Brown map->format.format_write = regmap_format_7_9_write; 195b83a313bSMark Brown break; 196b83a313bSMark Brown default: 197b83a313bSMark Brown goto err_map; 198b83a313bSMark Brown } 199b83a313bSMark Brown break; 200b83a313bSMark Brown 2017e5ec63eSLars-Peter Clausen case 10: 2027e5ec63eSLars-Peter Clausen switch (config->val_bits) { 2037e5ec63eSLars-Peter Clausen case 14: 2047e5ec63eSLars-Peter Clausen map->format.format_write = regmap_format_10_14_write; 2057e5ec63eSLars-Peter Clausen break; 2067e5ec63eSLars-Peter Clausen default: 2077e5ec63eSLars-Peter Clausen goto err_map; 2087e5ec63eSLars-Peter Clausen } 2097e5ec63eSLars-Peter Clausen break; 2107e5ec63eSLars-Peter Clausen 211b83a313bSMark Brown case 8: 212b83a313bSMark Brown map->format.format_reg = regmap_format_8; 213b83a313bSMark Brown break; 214b83a313bSMark Brown 215b83a313bSMark Brown case 16: 216b83a313bSMark Brown map->format.format_reg = regmap_format_16; 217b83a313bSMark Brown break; 218b83a313bSMark Brown 219b83a313bSMark Brown default: 220b83a313bSMark Brown goto err_map; 221b83a313bSMark Brown } 222b83a313bSMark Brown 223b83a313bSMark Brown switch (config->val_bits) { 224b83a313bSMark Brown case 8: 225b83a313bSMark Brown map->format.format_val = regmap_format_8; 226b83a313bSMark Brown map->format.parse_val = regmap_parse_8; 227b83a313bSMark Brown break; 228b83a313bSMark Brown case 16: 229b83a313bSMark Brown map->format.format_val = regmap_format_16; 230b83a313bSMark Brown map->format.parse_val = regmap_parse_16; 231b83a313bSMark Brown break; 232b83a313bSMark Brown } 233b83a313bSMark Brown 234b83a313bSMark Brown if (!map->format.format_write && 235b83a313bSMark Brown !(map->format.format_reg && map->format.format_val)) 236b83a313bSMark Brown goto err_map; 237b83a313bSMark Brown 238b83a313bSMark Brown map->work_buf = kmalloc(map->format.buf_size, GFP_KERNEL); 239b83a313bSMark Brown if (map->work_buf == NULL) { 240b83a313bSMark Brown ret = -ENOMEM; 2415204f5e3SMark Brown goto err_map; 242b83a313bSMark Brown } 243b83a313bSMark Brown 244*052d2cd1SMark Brown regmap_debugfs_init(map); 245*052d2cd1SMark Brown 246e5e3b8abSLars-Peter Clausen ret = regcache_init(map, config); 2475d1729e7SDimitris Papastamos if (ret < 0) 24858072cbfSLars-Peter Clausen goto err_free_workbuf; 2495d1729e7SDimitris Papastamos 250b83a313bSMark Brown return map; 251b83a313bSMark Brown 25258072cbfSLars-Peter Clausen err_free_workbuf: 25358072cbfSLars-Peter Clausen kfree(map->work_buf); 254b83a313bSMark Brown err_map: 255b83a313bSMark Brown kfree(map); 256b83a313bSMark Brown err: 257b83a313bSMark Brown return ERR_PTR(ret); 258b83a313bSMark Brown } 259b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_init); 260b83a313bSMark Brown 261b83a313bSMark Brown /** 262b83a313bSMark Brown * regmap_exit(): Free a previously allocated register map 263b83a313bSMark Brown */ 264b83a313bSMark Brown void regmap_exit(struct regmap *map) 265b83a313bSMark Brown { 2665d1729e7SDimitris Papastamos regcache_exit(map); 26731244e39SMark Brown regmap_debugfs_exit(map); 268b83a313bSMark Brown kfree(map->work_buf); 269b83a313bSMark Brown kfree(map); 270b83a313bSMark Brown } 271b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_exit); 272b83a313bSMark Brown 273b83a313bSMark Brown static int _regmap_raw_write(struct regmap *map, unsigned int reg, 274b83a313bSMark Brown const void *val, size_t val_len) 275b83a313bSMark Brown { 2766f306441SLars-Peter Clausen u8 *u8 = map->work_buf; 277b83a313bSMark Brown void *buf; 278b83a313bSMark Brown int ret = -ENOTSUPP; 279b83a313bSMark Brown size_t len; 28073304781SMark Brown int i; 28173304781SMark Brown 28273304781SMark Brown /* Check for unwritable registers before we start */ 28373304781SMark Brown if (map->writeable_reg) 28473304781SMark Brown for (i = 0; i < val_len / map->format.val_bytes; i++) 28573304781SMark Brown if (!map->writeable_reg(map->dev, reg + i)) 28673304781SMark Brown return -EINVAL; 287b83a313bSMark Brown 288b83a313bSMark Brown map->format.format_reg(map->work_buf, reg); 289b83a313bSMark Brown 2906f306441SLars-Peter Clausen u8[0] |= map->write_flag_mask; 2916f306441SLars-Peter Clausen 292fb2736bbSMark Brown trace_regmap_hw_write_start(map->dev, reg, 293fb2736bbSMark Brown val_len / map->format.val_bytes); 294fb2736bbSMark Brown 2952547e201SMark Brown /* If we're doing a single register write we can probably just 2962547e201SMark Brown * send the work_buf directly, otherwise try to do a gather 2972547e201SMark Brown * write. 2982547e201SMark Brown */ 2992547e201SMark Brown if (val == map->work_buf + map->format.reg_bytes) 3002547e201SMark Brown ret = map->bus->write(map->dev, map->work_buf, 3012547e201SMark Brown map->format.reg_bytes + val_len); 3022547e201SMark Brown else if (map->bus->gather_write) 303b83a313bSMark Brown ret = map->bus->gather_write(map->dev, map->work_buf, 304b83a313bSMark Brown map->format.reg_bytes, 305b83a313bSMark Brown val, val_len); 306b83a313bSMark Brown 3072547e201SMark Brown /* If that didn't work fall back on linearising by hand. */ 308b83a313bSMark Brown if (ret == -ENOTSUPP) { 309b83a313bSMark Brown len = map->format.reg_bytes + val_len; 310b83a313bSMark Brown buf = kmalloc(len, GFP_KERNEL); 311b83a313bSMark Brown if (!buf) 312b83a313bSMark Brown return -ENOMEM; 313b83a313bSMark Brown 314b83a313bSMark Brown memcpy(buf, map->work_buf, map->format.reg_bytes); 315b83a313bSMark Brown memcpy(buf + map->format.reg_bytes, val, val_len); 316b83a313bSMark Brown ret = map->bus->write(map->dev, buf, len); 317b83a313bSMark Brown 318b83a313bSMark Brown kfree(buf); 319b83a313bSMark Brown } 320b83a313bSMark Brown 321fb2736bbSMark Brown trace_regmap_hw_write_done(map->dev, reg, 322fb2736bbSMark Brown val_len / map->format.val_bytes); 323fb2736bbSMark Brown 324b83a313bSMark Brown return ret; 325b83a313bSMark Brown } 326b83a313bSMark Brown 3274d2dc095SDimitris Papastamos int _regmap_write(struct regmap *map, unsigned int reg, 328b83a313bSMark Brown unsigned int val) 329b83a313bSMark Brown { 330fb2736bbSMark Brown int ret; 331b83a313bSMark Brown BUG_ON(!map->format.format_write && !map->format.format_val); 332b83a313bSMark Brown 3335d1729e7SDimitris Papastamos if (!map->cache_bypass) { 3345d1729e7SDimitris Papastamos ret = regcache_write(map, reg, val); 3355d1729e7SDimitris Papastamos if (ret != 0) 3365d1729e7SDimitris Papastamos return ret; 3378ae0d7e8SMark Brown if (map->cache_only) { 3388ae0d7e8SMark Brown map->cache_dirty = true; 3395d1729e7SDimitris Papastamos return 0; 3405d1729e7SDimitris Papastamos } 3418ae0d7e8SMark Brown } 3425d1729e7SDimitris Papastamos 343fb2736bbSMark Brown trace_regmap_reg_write(map->dev, reg, val); 344fb2736bbSMark Brown 345b83a313bSMark Brown if (map->format.format_write) { 346b83a313bSMark Brown map->format.format_write(map, reg, val); 347b83a313bSMark Brown 348fb2736bbSMark Brown trace_regmap_hw_write_start(map->dev, reg, 1); 349fb2736bbSMark Brown 350fb2736bbSMark Brown ret = map->bus->write(map->dev, map->work_buf, 351b83a313bSMark Brown map->format.buf_size); 352fb2736bbSMark Brown 353fb2736bbSMark Brown trace_regmap_hw_write_done(map->dev, reg, 1); 354fb2736bbSMark Brown 355fb2736bbSMark Brown return ret; 356b83a313bSMark Brown } else { 357b83a313bSMark Brown map->format.format_val(map->work_buf + map->format.reg_bytes, 358b83a313bSMark Brown val); 359b83a313bSMark Brown return _regmap_raw_write(map, reg, 360b83a313bSMark Brown map->work_buf + map->format.reg_bytes, 361b83a313bSMark Brown map->format.val_bytes); 362b83a313bSMark Brown } 363b83a313bSMark Brown } 364b83a313bSMark Brown 365b83a313bSMark Brown /** 366b83a313bSMark Brown * regmap_write(): Write a value to a single register 367b83a313bSMark Brown * 368b83a313bSMark Brown * @map: Register map to write to 369b83a313bSMark Brown * @reg: Register to write to 370b83a313bSMark Brown * @val: Value to be written 371b83a313bSMark Brown * 372b83a313bSMark Brown * A value of zero will be returned on success, a negative errno will 373b83a313bSMark Brown * be returned in error cases. 374b83a313bSMark Brown */ 375b83a313bSMark Brown int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) 376b83a313bSMark Brown { 377b83a313bSMark Brown int ret; 378b83a313bSMark Brown 379b83a313bSMark Brown mutex_lock(&map->lock); 380b83a313bSMark Brown 381b83a313bSMark Brown ret = _regmap_write(map, reg, val); 382b83a313bSMark Brown 383b83a313bSMark Brown mutex_unlock(&map->lock); 384b83a313bSMark Brown 385b83a313bSMark Brown return ret; 386b83a313bSMark Brown } 387b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_write); 388b83a313bSMark Brown 389b83a313bSMark Brown /** 390b83a313bSMark Brown * regmap_raw_write(): Write raw values to one or more registers 391b83a313bSMark Brown * 392b83a313bSMark Brown * @map: Register map to write to 393b83a313bSMark Brown * @reg: Initial register to write to 394b83a313bSMark Brown * @val: Block of data to be written, laid out for direct transmission to the 395b83a313bSMark Brown * device 396b83a313bSMark Brown * @val_len: Length of data pointed to by val. 397b83a313bSMark Brown * 398b83a313bSMark Brown * This function is intended to be used for things like firmware 399b83a313bSMark Brown * download where a large block of data needs to be transferred to the 400b83a313bSMark Brown * device. No formatting will be done on the data provided. 401b83a313bSMark Brown * 402b83a313bSMark Brown * A value of zero will be returned on success, a negative errno will 403b83a313bSMark Brown * be returned in error cases. 404b83a313bSMark Brown */ 405b83a313bSMark Brown int regmap_raw_write(struct regmap *map, unsigned int reg, 406b83a313bSMark Brown const void *val, size_t val_len) 407b83a313bSMark Brown { 408c48a9d74SLars-Peter Clausen size_t val_count = val_len / map->format.val_bytes; 409b83a313bSMark Brown int ret; 410b83a313bSMark Brown 411c48a9d74SLars-Peter Clausen WARN_ON(!regmap_volatile_range(map, reg, val_count) && 412c48a9d74SLars-Peter Clausen map->cache_type != REGCACHE_NONE); 41304e016adSMark Brown 414b83a313bSMark Brown mutex_lock(&map->lock); 415b83a313bSMark Brown 416b83a313bSMark Brown ret = _regmap_raw_write(map, reg, val, val_len); 417b83a313bSMark Brown 418b83a313bSMark Brown mutex_unlock(&map->lock); 419b83a313bSMark Brown 420b83a313bSMark Brown return ret; 421b83a313bSMark Brown } 422b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_write); 423b83a313bSMark Brown 424b83a313bSMark Brown static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, 425b83a313bSMark Brown unsigned int val_len) 426b83a313bSMark Brown { 427b83a313bSMark Brown u8 *u8 = map->work_buf; 428b83a313bSMark Brown int ret; 429b83a313bSMark Brown 430b83a313bSMark Brown map->format.format_reg(map->work_buf, reg); 431b83a313bSMark Brown 432b83a313bSMark Brown /* 4336f306441SLars-Peter Clausen * Some buses or devices flag reads by setting the high bits in the 434b83a313bSMark Brown * register addresss; since it's always the high bits for all 435b83a313bSMark Brown * current formats we can do this here rather than in 436b83a313bSMark Brown * formatting. This may break if we get interesting formats. 437b83a313bSMark Brown */ 4386f306441SLars-Peter Clausen u8[0] |= map->read_flag_mask; 439b83a313bSMark Brown 440fb2736bbSMark Brown trace_regmap_hw_read_start(map->dev, reg, 441fb2736bbSMark Brown val_len / map->format.val_bytes); 442fb2736bbSMark Brown 443b83a313bSMark Brown ret = map->bus->read(map->dev, map->work_buf, map->format.reg_bytes, 44440c5cc26SMark Brown val, val_len); 445b83a313bSMark Brown 446fb2736bbSMark Brown trace_regmap_hw_read_done(map->dev, reg, 447fb2736bbSMark Brown val_len / map->format.val_bytes); 448fb2736bbSMark Brown 449fb2736bbSMark Brown return ret; 450b83a313bSMark Brown } 451b83a313bSMark Brown 452b83a313bSMark Brown static int _regmap_read(struct regmap *map, unsigned int reg, 453b83a313bSMark Brown unsigned int *val) 454b83a313bSMark Brown { 455b83a313bSMark Brown int ret; 456b83a313bSMark Brown 4575d1729e7SDimitris Papastamos if (!map->cache_bypass) { 4585d1729e7SDimitris Papastamos ret = regcache_read(map, reg, val); 4595d1729e7SDimitris Papastamos if (ret == 0) 4605d1729e7SDimitris Papastamos return 0; 4615d1729e7SDimitris Papastamos } 4625d1729e7SDimitris Papastamos 46319254411SLars-Peter Clausen if (!map->format.parse_val) 46419254411SLars-Peter Clausen return -EINVAL; 46519254411SLars-Peter Clausen 4665d1729e7SDimitris Papastamos if (map->cache_only) 4675d1729e7SDimitris Papastamos return -EBUSY; 4685d1729e7SDimitris Papastamos 469b83a313bSMark Brown ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); 470fb2736bbSMark Brown if (ret == 0) { 471b83a313bSMark Brown *val = map->format.parse_val(map->work_buf); 472fb2736bbSMark Brown trace_regmap_reg_read(map->dev, reg, *val); 473fb2736bbSMark Brown } 474b83a313bSMark Brown 475b83a313bSMark Brown return ret; 476b83a313bSMark Brown } 477b83a313bSMark Brown 478b83a313bSMark Brown /** 479b83a313bSMark Brown * regmap_read(): Read a value from a single register 480b83a313bSMark Brown * 481b83a313bSMark Brown * @map: Register map to write to 482b83a313bSMark Brown * @reg: Register to be read from 483b83a313bSMark Brown * @val: Pointer to store read value 484b83a313bSMark Brown * 485b83a313bSMark Brown * A value of zero will be returned on success, a negative errno will 486b83a313bSMark Brown * be returned in error cases. 487b83a313bSMark Brown */ 488b83a313bSMark Brown int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) 489b83a313bSMark Brown { 490b83a313bSMark Brown int ret; 491b83a313bSMark Brown 492b83a313bSMark Brown mutex_lock(&map->lock); 493b83a313bSMark Brown 494b83a313bSMark Brown ret = _regmap_read(map, reg, val); 495b83a313bSMark Brown 496b83a313bSMark Brown mutex_unlock(&map->lock); 497b83a313bSMark Brown 498b83a313bSMark Brown return ret; 499b83a313bSMark Brown } 500b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_read); 501b83a313bSMark Brown 502b83a313bSMark Brown /** 503b83a313bSMark Brown * regmap_raw_read(): Read raw data from the device 504b83a313bSMark Brown * 505b83a313bSMark Brown * @map: Register map to write to 506b83a313bSMark Brown * @reg: First register to be read from 507b83a313bSMark Brown * @val: Pointer to store read value 508b83a313bSMark Brown * @val_len: Size of data to read 509b83a313bSMark Brown * 510b83a313bSMark Brown * A value of zero will be returned on success, a negative errno will 511b83a313bSMark Brown * be returned in error cases. 512b83a313bSMark Brown */ 513b83a313bSMark Brown int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, 514b83a313bSMark Brown size_t val_len) 515b83a313bSMark Brown { 51682cd9965SLars-Peter Clausen size_t val_count = val_len / map->format.val_bytes; 517b83a313bSMark Brown int ret; 518b83a313bSMark Brown 51982cd9965SLars-Peter Clausen WARN_ON(!regmap_volatile_range(map, reg, val_count) && 52082cd9965SLars-Peter Clausen map->cache_type != REGCACHE_NONE); 52104e016adSMark Brown 522b83a313bSMark Brown mutex_lock(&map->lock); 523b83a313bSMark Brown 524b83a313bSMark Brown ret = _regmap_raw_read(map, reg, val, val_len); 525b83a313bSMark Brown 526b83a313bSMark Brown mutex_unlock(&map->lock); 527b83a313bSMark Brown 528b83a313bSMark Brown return ret; 529b83a313bSMark Brown } 530b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_raw_read); 531b83a313bSMark Brown 532b83a313bSMark Brown /** 533b83a313bSMark Brown * regmap_bulk_read(): Read multiple registers from the device 534b83a313bSMark Brown * 535b83a313bSMark Brown * @map: Register map to write to 536b83a313bSMark Brown * @reg: First register to be read from 537b83a313bSMark Brown * @val: Pointer to store read value, in native register size for device 538b83a313bSMark Brown * @val_count: Number of registers to read 539b83a313bSMark Brown * 540b83a313bSMark Brown * A value of zero will be returned on success, a negative errno will 541b83a313bSMark Brown * be returned in error cases. 542b83a313bSMark Brown */ 543b83a313bSMark Brown int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, 544b83a313bSMark Brown size_t val_count) 545b83a313bSMark Brown { 546b83a313bSMark Brown int ret, i; 547b83a313bSMark Brown size_t val_bytes = map->format.val_bytes; 54882cd9965SLars-Peter Clausen bool vol = regmap_volatile_range(map, reg, val_count); 5495d1729e7SDimitris Papastamos 550b83a313bSMark Brown if (!map->format.parse_val) 551b83a313bSMark Brown return -EINVAL; 552b83a313bSMark Brown 553de2d808fSMark Brown if (vol || map->cache_type == REGCACHE_NONE) { 554b83a313bSMark Brown ret = regmap_raw_read(map, reg, val, val_bytes * val_count); 555b83a313bSMark Brown if (ret != 0) 556b83a313bSMark Brown return ret; 557b83a313bSMark Brown 558b83a313bSMark Brown for (i = 0; i < val_count * val_bytes; i += val_bytes) 559b83a313bSMark Brown map->format.parse_val(val + i); 560de2d808fSMark Brown } else { 561de2d808fSMark Brown for (i = 0; i < val_count; i++) { 562de2d808fSMark Brown ret = regmap_read(map, reg + i, val + (i * val_bytes)); 563de2d808fSMark Brown if (ret != 0) 564de2d808fSMark Brown return ret; 565de2d808fSMark Brown } 566de2d808fSMark Brown } 567b83a313bSMark Brown 568b83a313bSMark Brown return 0; 569b83a313bSMark Brown } 570b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_bulk_read); 571b83a313bSMark Brown 572b83a313bSMark Brown /** 573b973aa36SMark Brown * regmap_update_bits: Perform a read/modify/write cycle on the register map 574b83a313bSMark Brown * 575b83a313bSMark Brown * @map: Register map to update 576b83a313bSMark Brown * @reg: Register to update 577b83a313bSMark Brown * @mask: Bitmask to change 578b83a313bSMark Brown * @val: New value for bitmask 579b83a313bSMark Brown * 580b83a313bSMark Brown * Returns zero for success, a negative number on error. 581b83a313bSMark Brown */ 582b83a313bSMark Brown int regmap_update_bits(struct regmap *map, unsigned int reg, 583b83a313bSMark Brown unsigned int mask, unsigned int val) 584b83a313bSMark Brown { 585b83a313bSMark Brown int ret; 586d91e8db2SMark Brown unsigned int tmp, orig; 587b83a313bSMark Brown 588b83a313bSMark Brown mutex_lock(&map->lock); 589b83a313bSMark Brown 590d91e8db2SMark Brown ret = _regmap_read(map, reg, &orig); 591b83a313bSMark Brown if (ret != 0) 592b83a313bSMark Brown goto out; 593b83a313bSMark Brown 594d91e8db2SMark Brown tmp = orig & ~mask; 595b83a313bSMark Brown tmp |= val & mask; 596b83a313bSMark Brown 597d91e8db2SMark Brown if (tmp != orig) 598b83a313bSMark Brown ret = _regmap_write(map, reg, tmp); 599b83a313bSMark Brown 600b83a313bSMark Brown out: 601b83a313bSMark Brown mutex_unlock(&map->lock); 602b83a313bSMark Brown 603b83a313bSMark Brown return ret; 604b83a313bSMark Brown } 605b83a313bSMark Brown EXPORT_SYMBOL_GPL(regmap_update_bits); 60631244e39SMark Brown 60731244e39SMark Brown static int __init regmap_initcall(void) 60831244e39SMark Brown { 60931244e39SMark Brown regmap_debugfs_initcall(); 61031244e39SMark Brown 61131244e39SMark Brown return 0; 61231244e39SMark Brown } 61331244e39SMark Brown postcore_initcall(regmap_initcall); 614