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; }
static bool regcache_reg_needs_sync(struct regmap *map, unsigned int reg, unsigned int val) { int ret; /* If we don't know the chip just got reset, then sync everything. */ if (!map->no_sync_defaults) return true; /* Is this the hardware default? If so skip. */ ret = regcache_lookup_reg(map, reg); if (ret >= 0 && val == map->reg_defaults[ret].def) return false; return true; }
static int regcache_sync_block_raw_multi_reg(struct regmap *map, void *block, unsigned long *cache_present, unsigned int block_base, unsigned int start, unsigned int end) { unsigned int i, val; unsigned int regtmp = 0; int ret = 0; struct reg_default *regs; size_t num_regs = ((end - start) + 1); regs = kcalloc(num_regs, sizeof(struct reg_default), GFP_KERNEL); if (!regs) return -ENOMEM; num_regs = 0; for (i = start; i < end; i++) { regtmp = block_base + (i * map->reg_stride); /* skip registers that are not defined/available */ if (!regcache_reg_present(cache_present, i)) 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; } else { regs[num_regs].reg = regtmp; regs[num_regs].def = val; num_regs += 1; } } ret = 0; if (num_regs) { dev_dbg(map->dev, "%s: start: 0x%x - end: 0x%x\n", __func__, regs[0].reg, regs[num_regs-1].reg); ret = _regmap_raw_multi_reg_write(map, regs, num_regs); } kfree(regs); return ret; }
static int regcache_sync_block_raw(struct regmap *map, void *block, unsigned long *cache_present, unsigned int block_base, unsigned int start, unsigned int end) { unsigned int i, val; unsigned int regtmp = 0; unsigned int base = 0; const void *data = NULL; 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)) { ret = regcache_sync_block_raw_flush(map, &data, base, regtmp); if (ret != 0) return ret; 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) { ret = regcache_sync_block_raw_flush(map, &data, base, regtmp); if (ret != 0) return ret; continue; } if (!data) { data = regcache_get_val_addr(map, block, i); base = regtmp; } } return regcache_sync_block_raw_flush(map, &data, base, regtmp + map->reg_stride); }