static int regcache_default_sync(struct regmap *map, unsigned int min, unsigned int max) { unsigned int reg; for (reg = min; reg <= max; reg += map->reg_stride) { unsigned int val; int ret; if (regmap_volatile(map, reg) || !regmap_writeable(map, reg)) continue; ret = regcache_read(map, reg, &val); if (ret) return ret; if (!regcache_reg_needs_sync(map, reg, val)) continue; map->cache_bypass = true; ret = _regmap_write(map, reg, val); map->cache_bypass = false; if (ret) { dev_err(map->dev, "Unable to sync register %#x. %d\n", reg, ret); return ret; } dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val); } return 0; }
static int regcache_sync_block_single(struct regmap *map, void *block, unsigned long *cache_present, unsigned int block_base, unsigned int start, unsigned int end) { unsigned int i, regtmp, val; int ret; for (i = start; i < end; i++) { regtmp = block_base + (i * map->reg_stride); if (!regcache_reg_present(cache_present, i) || !regmap_writeable(map, regtmp)) continue; val = regcache_get_val(map, block, i); if (!regcache_reg_needs_sync(map, regtmp, val)) continue; map->cache_bypass = true; ret = _regmap_write(map, regtmp, val); map->cache_bypass = false; if (ret != 0) { dev_err(map->dev, "Unable to sync register %#x. %d\n", regtmp, ret); return ret; } dev_dbg(map->dev, "Synced register %#x, value %#x\n", regtmp, val); } return 0; }
static int regcache_default_sync(struct regmap *map, unsigned int min, unsigned int max) { unsigned int reg; for (reg = min; reg <= max; reg++) { unsigned int val; int ret; if (regmap_volatile(map, reg)) continue; ret = regcache_read(map, reg, &val); if (ret) return ret; if (!regcache_reg_needs_sync(map, reg, val)) continue; map->cache_bypass = 1; ret = _regmap_write(map, reg, val); map->cache_bypass = 0; if (ret) return ret; dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val); } return 0; }
static int regcache_sync_block_single(struct regmap *map, void *block, unsigned int block_base, unsigned int start, unsigned int end) { unsigned int i, regtmp, val; int ret; for (i = start; i < end; i++) { regtmp = block_base + (i * map->reg_stride); if (!regcache_reg_present(map, regtmp)) continue; val = regcache_get_val(map, block, i); /* Is this the hardware default? If so skip. */ ret = regcache_lookup_reg(map, regtmp); if (ret >= 0 && val == map->reg_defaults[ret].def) continue; map->cache_bypass = 1; ret = _regmap_write(map, regtmp, val); map->cache_bypass = 0; if (ret != 0) return ret; dev_dbg(map->dev, "Synced register %#x, value %#x\n", regtmp, val); } return 0; }
static int regcache_default_sync(struct regmap *map, unsigned int min, unsigned int max) { unsigned int reg; for (reg = min; reg <= max; reg += map->reg_stride) { unsigned int val; int ret; if (regmap_volatile(map, reg) || !regmap_writeable(map, reg)) continue; ret = regcache_read(map, reg, &val); if (ret) return ret; /* Is this the hardware default? If so skip. */ ret = regcache_lookup_reg(map, reg); if (ret >= 0 && val == map->reg_defaults[ret].def) continue; map->cache_bypass = 1; ret = _regmap_write(map, reg, val); map->cache_bypass = 0; if (ret) return ret; dev_dbg(map->dev, "Synced register %#x, value %#x\n", reg, val); } return 0; }
/** * regcache_sync: Sync the register cache with the hardware. * * @map: map to configure. * * Any registers that should not be synced should be marked as * volatile. In general drivers can choose not to use the provided * syncing functionality if they so require. * * Return a negative value on failure, 0 on success. */ int regcache_sync(struct regmap *map) { int ret = 0; unsigned int i; const char *name; unsigned int bypass; BUG_ON(!map->cache_ops); map->lock(map->lock_arg); /* Remember the initial bypass state */ bypass = map->cache_bypass; dev_dbg(map->dev, "Syncing %s cache\n", map->cache_ops->name); name = map->cache_ops->name; trace_regcache_sync(map->dev, name, "start"); if (!map->cache_dirty) goto out; map->async = true; /* Apply any patch first */ map->cache_bypass = 1; for (i = 0; i < map->patch_regs; i++) { if (map->patch[i].reg % map->reg_stride) { ret = -EINVAL; goto out; } ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); if (ret != 0) { dev_err(map->dev, "Failed to write %x = %x: %d\n", map->patch[i].reg, map->patch[i].def, ret); goto out; } } map->cache_bypass = 0; if (map->cache_ops->sync) ret = map->cache_ops->sync(map, 0, map->max_register); else ret = regcache_default_sync(map, 0, map->max_register); if (ret == 0) map->cache_dirty = false; out: /* Restore the bypass state */ map->async = false; map->cache_bypass = bypass; map->no_sync_defaults = false; map->unlock(map->lock_arg); regmap_async_complete(map); trace_regcache_sync(map->dev, name, "stop"); return ret; }
/** * regmap_write(): Write a value to a single register * * @map: Register map to write to * @reg: Register to write to * @val: Value to be written * * A value of zero will be returned on success, a negative errno will * be returned in error cases. */ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) { int ret; mutex_lock(&map->lock); ret = _regmap_write(map, reg, val); mutex_unlock(&map->lock); return ret; }
int regcache_sync(struct regmap *map) { int ret = 0; unsigned int i; const char *name; unsigned int bypass; BUG_ON(!map || !map->cache_ops || !map->cache_ops->sync); mutex_lock(&map->lock); bypass = map->cache_bypass; dev_dbg(map->dev, "Syncing %s cache\n", map->cache_ops->name); name = map->cache_ops->name; trace_regcache_sync(map->dev, name, "start"); if (!map->cache_dirty) goto out; map->cache_bypass = 1; for (i = 0; i < map->patch_regs; i++) { ret = _regmap_write(map, map->patch[i].reg, map->patch[i].def); if (ret != 0) { dev_err(map->dev, "Failed to write %x = %x: %d\n", map->patch[i].reg, map->patch[i].def, ret); goto out; } } map->cache_bypass = 0; ret = map->cache_ops->sync(map, 0, map->max_register); if (ret == 0) map->cache_dirty = false; out: trace_regcache_sync(map->dev, name, "stop"); map->cache_bypass = bypass; mutex_unlock(&map->lock); return ret; }
/** * regcache_sync: Sync the register cache with the hardware. * * @map: map to configure. * * Any registers that should not be synced should be marked as * volatile. In general drivers can choose not to use the provided * syncing functionality if they so require. * * Return a negative value on failure, 0 on success. */ int regcache_sync(struct regmap *map) { int ret = 0; unsigned int val; unsigned int i; const char *name; unsigned int bypass; BUG_ON(!map->cache_ops); mutex_lock(&map->lock); /* Remember the initial bypass state */ bypass = map->cache_bypass; dev_dbg(map->dev, "Syncing %s cache\n", map->cache_ops->name); name = map->cache_ops->name; trace_regcache_sync(map->dev, name, "start"); if (map->cache_ops->sync) { ret = map->cache_ops->sync(map); } else { for (i = 0; i < map->num_reg_defaults; i++) { ret = regcache_read(map, i, &val); if (ret < 0) goto out; map->cache_bypass = 1; ret = _regmap_write(map, i, val); map->cache_bypass = 0; if (ret < 0) goto out; dev_dbg(map->dev, "Synced register %#x, value %#x\n", map->reg_defaults[i].reg, map->reg_defaults[i].def); } } out: trace_regcache_sync(map->dev, name, "stop"); /* Restore the bypass state */ map->cache_bypass = bypass; mutex_unlock(&map->lock); return ret; }
/** * remap_update_bits: Perform a read/modify/write cycle on the register map * * @map: Register map to update * @reg: Register to update * @mask: Bitmask to change * @val: New value for bitmask * * Returns zero for success, a negative number on error. */ int regmap_update_bits(struct regmap *map, unsigned int reg, unsigned int mask, unsigned int val) { int ret; unsigned int tmp; mutex_lock(&map->lock); ret = _regmap_read(map, reg, &tmp); if (ret != 0) goto out; tmp &= ~mask; tmp |= val & mask; ret = _regmap_write(map, reg, tmp); out: mutex_unlock(&map->lock); return ret; }