19fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos/* 29fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Register cache access API 39fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 49fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Copyright 2011 Wolfson Microelectronics plc 59fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 69fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> 79fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 89fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * This program is free software; you can redistribute it and/or modify 99fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * it under the terms of the GNU General Public License version 2 as 109fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * published by the Free Software Foundation. 119fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos */ 129fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 139fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos#include <linux/slab.h> 141b6bc32f0a7380102499deb6aa99a59e789efb33Paul Gortmaker#include <linux/export.h> 1551990e825431089747f8896244b5c17d3a6423f1Paul Gortmaker#include <linux/device.h> 169fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos#include <trace/events/regmap.h> 17f094fea68f0575286c55c06141cc89ffd0049024Mark Brown#include <linux/bsearch.h> 18c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos#include <linux/sort.h> 199fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 209fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos#include "internal.h" 219fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 229fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosstatic const struct regcache_ops *cache_types[] = { 2328644c809f44498b8cd91d00b4cdb09e63b99843Dimitris Papastamos ®cache_rbtree_ops, 242cbbb579bcbe3e11baf1c59920dcd5a780b80447Dimitris Papastamos ®cache_lzo_ops, 259fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos}; 269fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 279fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosstatic int regcache_hw_init(struct regmap *map) 289fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 299fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos int i, j; 309fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos int ret; 319fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos int count; 329fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos unsigned int val; 339fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos void *tmp_buf; 349fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 359fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!map->num_reg_defaults_raw) 369fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 379fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 389fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!map->reg_defaults_raw) { 39df00c79f78d8b0ad788daf689ea461ace9d0811fLaxman Dewangan u32 cache_bypass = map->cache_bypass; 409fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos dev_warn(map->dev, "No cache defaults, reading back from HW\n"); 41df00c79f78d8b0ad788daf689ea461ace9d0811fLaxman Dewangan 42df00c79f78d8b0ad788daf689ea461ace9d0811fLaxman Dewangan /* Bypass the cache access till data read from HW*/ 43df00c79f78d8b0ad788daf689ea461ace9d0811fLaxman Dewangan map->cache_bypass = 1; 449fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); 459fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!tmp_buf) 469fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 479fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos ret = regmap_bulk_read(map, 0, tmp_buf, 489fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->num_reg_defaults_raw); 49df00c79f78d8b0ad788daf689ea461ace9d0811fLaxman Dewangan map->cache_bypass = cache_bypass; 509fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (ret < 0) { 519fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos kfree(tmp_buf); 529fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return ret; 539fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 549fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->reg_defaults_raw = tmp_buf; 559fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache_free = 1; 569fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 579fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 589fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos /* calculate the size of reg_defaults */ 599fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { 609fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos val = regcache_get_val(map->reg_defaults_raw, 619fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos i, map->cache_word_size); 6261cddc57dc14a5dffa0921d9a24fd68edbb374acLars-Peter Clausen if (regmap_volatile(map, i)) 639fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos continue; 649fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos count++; 659fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 669fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 679fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->reg_defaults = kmalloc(count * sizeof(struct reg_default), 689fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos GFP_KERNEL); 69021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen if (!map->reg_defaults) { 70021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen ret = -ENOMEM; 71021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen goto err_free; 72021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen } 739fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 749fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos /* fill the reg_defaults */ 759fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->num_reg_defaults = count; 769fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { 779fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos val = regcache_get_val(map->reg_defaults_raw, 789fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos i, map->cache_word_size); 7961cddc57dc14a5dffa0921d9a24fd68edbb374acLars-Peter Clausen if (regmap_volatile(map, i)) 809fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos continue; 819fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->reg_defaults[j].reg = i; 829fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->reg_defaults[j].def = val; 839fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos j++; 849fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 859fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 869fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return 0; 87021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen 88021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausenerr_free: 89021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen if (map->cache_free) 90021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen kfree(map->reg_defaults_raw); 91021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen 92021cd616decb4e8a4b31f1f8c466a847e8c04e67Lars-Peter Clausen return ret; 939fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 949fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 95e5e3b8abeda1cf45f5a079458dbc267952694c7aLars-Peter Clausenint regcache_init(struct regmap *map, const struct regmap_config *config) 969fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 979fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos int ret; 989fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos int i; 999fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos void *tmp_buf; 1009fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 101e7a6db30df42234bc0f7b9a0af402838e0f146b1Mark Brown if (map->cache_type == REGCACHE_NONE) { 102e7a6db30df42234bc0f7b9a0af402838e0f146b1Mark Brown map->cache_bypass = true; 1039fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return 0; 104e7a6db30df42234bc0f7b9a0af402838e0f146b1Mark Brown } 1059fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1069fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos for (i = 0; i < ARRAY_SIZE(cache_types); i++) 1079fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (cache_types[i]->type == map->cache_type) 1089fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos break; 1099fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1109fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (i == ARRAY_SIZE(cache_types)) { 1119fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos dev_err(map->dev, "Could not match compress type: %d\n", 1129fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache_type); 1139fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 1149fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 1159fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 116e5e3b8abeda1cf45f5a079458dbc267952694c7aLars-Peter Clausen map->num_reg_defaults = config->num_reg_defaults; 117e5e3b8abeda1cf45f5a079458dbc267952694c7aLars-Peter Clausen map->num_reg_defaults_raw = config->num_reg_defaults_raw; 118e5e3b8abeda1cf45f5a079458dbc267952694c7aLars-Peter Clausen map->reg_defaults_raw = config->reg_defaults_raw; 119064d4db11e23949c40b8a2f2f6be11c131b53932Lars-Peter Clausen map->cache_word_size = DIV_ROUND_UP(config->val_bits, 8); 120064d4db11e23949c40b8a2f2f6be11c131b53932Lars-Peter Clausen map->cache_size_raw = map->cache_word_size * config->num_reg_defaults_raw; 121e5e3b8abeda1cf45f5a079458dbc267952694c7aLars-Peter Clausen 1229fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache = NULL; 1239fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache_ops = cache_types[i]; 1249fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1259fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!map->cache_ops->read || 1269fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos !map->cache_ops->write || 1279fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos !map->cache_ops->name) 1289fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 1299fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1309fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos /* We still need to ensure that the reg_defaults 1319fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * won't vanish from under us. We'll need to make 1329fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * a copy of it. 1339fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos */ 134720e4616e8fd85284ef1addd8b8d93d8415e8dbcLars-Peter Clausen if (config->reg_defaults) { 1359fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!map->num_reg_defaults) 1369fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 137720e4616e8fd85284ef1addd8b8d93d8415e8dbcLars-Peter Clausen tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults * 1389fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos sizeof(struct reg_default), GFP_KERNEL); 1399fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!tmp_buf) 1409fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -ENOMEM; 1419fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->reg_defaults = tmp_buf; 1428528bdd450d34687b380c0f87992d105bdf54ca3Mark Brown } else if (map->num_reg_defaults_raw) { 1435fcd2560767cead8f0c741340e132c5417d9f73bMark Brown /* Some devices such as PMICs don't have cache defaults, 1449fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * we cope with this by reading back the HW registers and 1459fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * crafting the cache defaults by hand. 1469fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos */ 1479fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos ret = regcache_hw_init(map); 1489fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (ret < 0) 1499fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return ret; 1509fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 1519fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1529fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!map->max_register) 1539fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->max_register = map->num_reg_defaults_raw; 1549fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1559fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (map->cache_ops->init) { 1569fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos dev_dbg(map->dev, "Initializing %s cache\n", 1579fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache_ops->name); 158bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen ret = map->cache_ops->init(map); 159bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen if (ret) 160bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen goto err_free; 1619fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 1629fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return 0; 163bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen 164bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausenerr_free: 165bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen kfree(map->reg_defaults); 166bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen if (map->cache_free) 167bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen kfree(map->reg_defaults_raw); 168bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen 169bd061c78cabc28bb64ed79f784d24918b6bdb791Lars-Peter Clausen return ret; 1709fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 1719fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1729fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosvoid regcache_exit(struct regmap *map) 1739fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 1749fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (map->cache_type == REGCACHE_NONE) 1759fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return; 1769fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1779fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos BUG_ON(!map->cache_ops); 1789fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1799fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos kfree(map->reg_defaults); 1809fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (map->cache_free) 1819fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos kfree(map->reg_defaults_raw); 1829fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1839fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (map->cache_ops->exit) { 1849fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos dev_dbg(map->dev, "Destroying %s cache\n", 1859fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache_ops->name); 1869fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos map->cache_ops->exit(map); 1879fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 1889fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 1899fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 1909fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos/** 1919fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * regcache_read: Fetch the value of a given register from the cache. 1929fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 1939fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @map: map to configure. 1949fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @reg: The register index. 1959fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @value: The value to be returned. 1969fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 1979fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Return a negative value on failure, 0 on success. 1989fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos */ 1999fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosint regcache_read(struct regmap *map, 2009fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos unsigned int reg, unsigned int *value) 2019fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 202bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown int ret; 203bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown 2049fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (map->cache_type == REGCACHE_NONE) 2059fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -ENOSYS; 2069fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2079fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos BUG_ON(!map->cache_ops); 2089fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 209bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown if (!regmap_volatile(map, reg)) { 210bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown ret = map->cache_ops->read(map, reg, value); 211bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown 212bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown if (ret == 0) 213bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown trace_regmap_reg_read_cache(map->dev, reg, *value); 214bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown 215bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown return ret; 216bc7ee55633867909bb05e71f957a4d3c1aa1b488Mark Brown } 2179fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2189fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 2199fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 2209fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2219fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos/** 2229fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * regcache_write: Set the value of a given register in the cache. 2239fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 2249fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @map: map to configure. 2259fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @reg: The register index. 2269fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @value: The new register value. 2279fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 2289fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Return a negative value on failure, 0 on success. 2299fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos */ 2309fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosint regcache_write(struct regmap *map, 2319fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos unsigned int reg, unsigned int value) 2329fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 2339fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (map->cache_type == REGCACHE_NONE) 2349fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return 0; 2359fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2369fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos BUG_ON(!map->cache_ops); 2379fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2389fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!regmap_writeable(map, reg)) 2399fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EIO; 2409fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2419fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!regmap_volatile(map, reg)) 2429fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return map->cache_ops->write(map, reg, value); 2439fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2449fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return 0; 2459fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 2469fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 2479fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos/** 2489fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * regcache_sync: Sync the register cache with the hardware. 2499fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 2509fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * @map: map to configure. 2519fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 2529fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Any registers that should not be synced should be marked as 2539fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * volatile. In general drivers can choose not to use the provided 2549fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * syncing functionality if they so require. 2559fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * 2569fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos * Return a negative value on failure, 0 on success. 2579fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos */ 2589fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosint regcache_sync(struct regmap *map) 2599fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 260954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos int ret = 0; 261954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos unsigned int i; 262593600890110c02eb471cf844649dee213870416Dimitris Papastamos const char *name; 263beb1a10f219ce720c13168203bd5ebe4ce7879e0Dimitris Papastamos unsigned int bypass; 264593600890110c02eb471cf844649dee213870416Dimitris Papastamos 265c3ec23288a92e20e0aff84a4cb6fbc7cc9bcf567Mark Brown BUG_ON(!map->cache_ops || !map->cache_ops->sync); 2669fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 26713753a9088af23c61e2f5c10a8f3ea136d8ebab5Dimitris Papastamos mutex_lock(&map->lock); 268beb1a10f219ce720c13168203bd5ebe4ce7879e0Dimitris Papastamos /* Remember the initial bypass state */ 269beb1a10f219ce720c13168203bd5ebe4ce7879e0Dimitris Papastamos bypass = map->cache_bypass; 270954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos dev_dbg(map->dev, "Syncing %s cache\n", 271954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos map->cache_ops->name); 272954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos name = map->cache_ops->name; 273954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos trace_regcache_sync(map->dev, name, "start"); 27422f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown 2758ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown if (!map->cache_dirty) 2768ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown goto out; 277d9db762708e27c2892db9d8a54e735a8e506e16eMark Brown 27822f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown /* Apply any patch first */ 2798a892d6996b60c822f19ad1844eb15b96ce393c7Mark Brown map->cache_bypass = 1; 28022f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown for (i = 0; i < map->patch_regs; i++) { 28122f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); 28222f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown if (ret != 0) { 28322f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown dev_err(map->dev, "Failed to write %x = %x: %d\n", 28422f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown map->patch[i].reg, map->patch[i].def, ret); 28522f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown goto out; 28622f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown } 28722f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown } 2888a892d6996b60c822f19ad1844eb15b96ce393c7Mark Brown map->cache_bypass = 0; 28922f0d90a34827812413bb3fbeda6a2a79bb58423Mark Brown 290ac8d91c801905a061ca883dca427a5e19602a1e7Mark Brown ret = map->cache_ops->sync(map, 0, map->max_register); 291954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos 2926ff7373809a9b4eb644d83e2e299da297e1cbffaMark Brown if (ret == 0) 2936ff7373809a9b4eb644d83e2e299da297e1cbffaMark Brown map->cache_dirty = false; 294954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos 295954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamosout: 296954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos trace_regcache_sync(map->dev, name, "stop"); 297beb1a10f219ce720c13168203bd5ebe4ce7879e0Dimitris Papastamos /* Restore the bypass state */ 298beb1a10f219ce720c13168203bd5ebe4ce7879e0Dimitris Papastamos map->cache_bypass = bypass; 29913753a9088af23c61e2f5c10a8f3ea136d8ebab5Dimitris Papastamos mutex_unlock(&map->lock); 300954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos 301954757d767a78bc4b863fa9ea703bd7f814c8a55Dimitris Papastamos return ret; 3029fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 3039fabe24e9b1af84509b842731d2beaf85e66681eDimitris PapastamosEXPORT_SYMBOL_GPL(regcache_sync); 3049fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 30592afb286d744511f51a05f8acb6c111d05737617Mark Brown/** 3064d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * regcache_sync_region: Sync part of the register cache with the hardware. 3074d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * 3084d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * @map: map to sync. 3094d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * @min: first register to sync 3104d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * @max: last register to sync 3114d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * 3124d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * Write all non-default register values in the specified region to 3134d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * the hardware. 3144d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * 3154d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown * Return a negative value on failure, 0 on success. 3164d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown */ 3174d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brownint regcache_sync_region(struct regmap *map, unsigned int min, 3184d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown unsigned int max) 3194d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown{ 3204d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown int ret = 0; 3214d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown const char *name; 3224d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown unsigned int bypass; 3234d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3244d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown BUG_ON(!map->cache_ops || !map->cache_ops->sync); 3254d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3264d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown mutex_lock(&map->lock); 3274d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3284d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown /* Remember the initial bypass state */ 3294d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown bypass = map->cache_bypass; 3304d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3314d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown name = map->cache_ops->name; 3324d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown dev_dbg(map->dev, "Syncing %s cache from %d-%d\n", name, min, max); 3334d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3344d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown trace_regcache_sync(map->dev, name, "start region"); 3354d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3364d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown if (!map->cache_dirty) 3374d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown goto out; 3384d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3394d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown ret = map->cache_ops->sync(map, min, max); 3404d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3414d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brownout: 3424d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown trace_regcache_sync(map->dev, name, "stop region"); 3434d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown /* Restore the bypass state */ 3444d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown map->cache_bypass = bypass; 3454d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown mutex_unlock(&map->lock); 3464d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3474d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown return ret; 3484d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown} 349e466de05194b666114713b753e2f4be1d4200140Mark BrownEXPORT_SYMBOL_GPL(regcache_sync_region); 3504d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown 3514d4cfd1656b5f6c88eae51c40741a695b108b006Mark Brown/** 35292afb286d744511f51a05f8acb6c111d05737617Mark Brown * regcache_cache_only: Put a register map into cache only mode 35392afb286d744511f51a05f8acb6c111d05737617Mark Brown * 35492afb286d744511f51a05f8acb6c111d05737617Mark Brown * @map: map to configure 35592afb286d744511f51a05f8acb6c111d05737617Mark Brown * @cache_only: flag if changes should be written to the hardware 35692afb286d744511f51a05f8acb6c111d05737617Mark Brown * 35792afb286d744511f51a05f8acb6c111d05737617Mark Brown * When a register map is marked as cache only writes to the register 35892afb286d744511f51a05f8acb6c111d05737617Mark Brown * map API will only update the register cache, they will not cause 35992afb286d744511f51a05f8acb6c111d05737617Mark Brown * any hardware changes. This is useful for allowing portions of 36092afb286d744511f51a05f8acb6c111d05737617Mark Brown * drivers to act as though the device were functioning as normal when 36192afb286d744511f51a05f8acb6c111d05737617Mark Brown * it is disabled for power saving reasons. 36292afb286d744511f51a05f8acb6c111d05737617Mark Brown */ 36392afb286d744511f51a05f8acb6c111d05737617Mark Brownvoid regcache_cache_only(struct regmap *map, bool enable) 36492afb286d744511f51a05f8acb6c111d05737617Mark Brown{ 3652cd148f1599a425f0f3ac6753da96a1a1aa3ce76Mark Brown mutex_lock(&map->lock); 366ac77a765cb6e3b5aa41c186ad9f37db7fdad7dbeDimitris Papastamos WARN_ON(map->cache_bypass && enable); 36792afb286d744511f51a05f8acb6c111d05737617Mark Brown map->cache_only = enable; 3685d5b7d4f80ed6e861c1c220fd57e3dad0912526eMark Brown trace_regmap_cache_only(map->dev, enable); 3692cd148f1599a425f0f3ac6753da96a1a1aa3ce76Mark Brown mutex_unlock(&map->lock); 37092afb286d744511f51a05f8acb6c111d05737617Mark Brown} 37192afb286d744511f51a05f8acb6c111d05737617Mark BrownEXPORT_SYMBOL_GPL(regcache_cache_only); 37292afb286d744511f51a05f8acb6c111d05737617Mark Brown 3736eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos/** 3748ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * regcache_mark_dirty: Mark the register cache as dirty 3758ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * 3768ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * @map: map to mark 3778ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * 3788ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * Mark the register cache as dirty, for example due to the device 3798ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * having been powered down for suspend. If the cache is not marked 3808ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown * as dirty then the cache sync will be suppressed. 3818ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown */ 3828ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brownvoid regcache_mark_dirty(struct regmap *map) 3838ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown{ 3848ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown mutex_lock(&map->lock); 3858ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown map->cache_dirty = true; 3868ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown mutex_unlock(&map->lock); 3878ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown} 3888ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark BrownEXPORT_SYMBOL_GPL(regcache_mark_dirty); 3898ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown 3908ae0d7e8a918e9603748abe9b31984fc5d96abb3Mark Brown/** 3916eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * regcache_cache_bypass: Put a register map into cache bypass mode 3926eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * 3936eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * @map: map to configure 3940eef6b0415f58ed16aff95af8c92514ce5c01258Dimitris Papastamos * @cache_bypass: flag if changes should not be written to the hardware 3956eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * 3966eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * When a register map is marked with the cache bypass option, writes 3976eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * to the register map API will only update the hardware and not the 3986eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * the cache directly. This is useful when syncing the cache back to 3996eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos * the hardware. 4006eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos */ 4016eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamosvoid regcache_cache_bypass(struct regmap *map, bool enable) 4026eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos{ 4036eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos mutex_lock(&map->lock); 404ac77a765cb6e3b5aa41c186ad9f37db7fdad7dbeDimitris Papastamos WARN_ON(map->cache_only && enable); 4056eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos map->cache_bypass = enable; 4065d5b7d4f80ed6e861c1c220fd57e3dad0912526eMark Brown trace_regmap_cache_bypass(map->dev, enable); 4076eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos mutex_unlock(&map->lock); 4086eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos} 4096eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris PapastamosEXPORT_SYMBOL_GPL(regcache_cache_bypass); 4106eb0f5e0154facfe4f0acdb9f474cde773319efcDimitris Papastamos 4119fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosbool regcache_set_val(void *base, unsigned int idx, 4129fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos unsigned int val, unsigned int word_size) 4139fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 4149fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos switch (word_size) { 4159fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos case 1: { 4169fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos u8 *cache = base; 4179fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (cache[idx] == val) 4189fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return true; 4199fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos cache[idx] = val; 4209fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos break; 4219fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 4229fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos case 2: { 4239fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos u16 *cache = base; 4249fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (cache[idx] == val) 4259fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return true; 4269fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos cache[idx] = val; 4279fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos break; 4289fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 4297d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown case 4: { 4307d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown u32 *cache = base; 4317d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown if (cache[idx] == val) 4327d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown return true; 4337d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown cache[idx] = val; 4347d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown break; 4357d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown } 4369fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos default: 4379fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos BUG(); 4389fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 4399fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return false; 4409fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 4419fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 4429fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamosunsigned int regcache_get_val(const void *base, unsigned int idx, 4439fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos unsigned int word_size) 4449fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos{ 4459fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos if (!base) 4469fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -EINVAL; 4479fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 4489fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos switch (word_size) { 4499fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos case 1: { 4509fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos const u8 *cache = base; 4519fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return cache[idx]; 4529fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 4539fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos case 2: { 4549fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos const u16 *cache = base; 4559fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return cache[idx]; 4569fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 4577d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown case 4: { 4587d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown const u32 *cache = base; 4597d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown return cache[idx]; 4607d5e525b9ceda0e3b85da0acdaa2de19fea51edcMark Brown } 4619fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos default: 4629fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos BUG(); 4639fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos } 4649fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos /* unreachable */ 4659fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos return -1; 4669fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos} 4679fabe24e9b1af84509b842731d2beaf85e66681eDimitris Papastamos 468f094fea68f0575286c55c06141cc89ffd0049024Mark Brownstatic int regcache_default_cmp(const void *a, const void *b) 469c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos{ 470c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos const struct reg_default *_a = a; 471c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos const struct reg_default *_b = b; 472c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos 473c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos return _a->reg - _b->reg; 474c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos} 475c08604b8ae72b4fa1843a76fc7b403ddec49f8f4Dimitris Papastamos 476f094fea68f0575286c55c06141cc89ffd0049024Mark Brownint regcache_lookup_reg(struct regmap *map, unsigned int reg) 477f094fea68f0575286c55c06141cc89ffd0049024Mark Brown{ 478f094fea68f0575286c55c06141cc89ffd0049024Mark Brown struct reg_default key; 479f094fea68f0575286c55c06141cc89ffd0049024Mark Brown struct reg_default *r; 480f094fea68f0575286c55c06141cc89ffd0049024Mark Brown 481f094fea68f0575286c55c06141cc89ffd0049024Mark Brown key.reg = reg; 482f094fea68f0575286c55c06141cc89ffd0049024Mark Brown key.def = 0; 483f094fea68f0575286c55c06141cc89ffd0049024Mark Brown 484f094fea68f0575286c55c06141cc89ffd0049024Mark Brown r = bsearch(&key, map->reg_defaults, map->num_reg_defaults, 485f094fea68f0575286c55c06141cc89ffd0049024Mark Brown sizeof(struct reg_default), regcache_default_cmp); 486f094fea68f0575286c55c06141cc89ffd0049024Mark Brown 487f094fea68f0575286c55c06141cc89ffd0049024Mark Brown if (r) 488f094fea68f0575286c55c06141cc89ffd0049024Mark Brown return r - map->reg_defaults; 489f094fea68f0575286c55c06141cc89ffd0049024Mark Brown else 4906e6ace00a045251bd172b9b9c2379857bbff3dc7Mark Brown return -ENOENT; 491f094fea68f0575286c55c06141cc89ffd0049024Mark Brown} 492