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_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_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; }
/** * regmap_bulk_read(): Read multiple registers from the device * * @map: Register map to write to * @reg: First register to be read from * @val: Pointer to store read value, in native register size for device * @val_count: Number of registers to read * * A value of zero will be returned on success, a negative errno will * be returned in error cases. */ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, size_t val_count) { int ret, i; size_t val_bytes = map->format.val_bytes; bool vol = true; if (!map->format.parse_val) return -EINVAL; /* Is this a block of volatile registers? */ for (i = 0; i < val_count; i++) if (!regmap_volatile(map, reg + i)) vol = false; if (vol || map->cache_type == REGCACHE_NONE) { ret = regmap_raw_read(map, reg, val, val_bytes * val_count); if (ret != 0) return ret; for (i = 0; i < val_count * val_bytes; i += val_bytes) map->format.parse_val(val + i); } else { for (i = 0; i < val_count; i++) { ret = regmap_read(map, reg + i, val + (i * val_bytes)); if (ret != 0) return ret; } } return 0; }
/** * regcache_write: Set the value of a given register in the cache. * * @map: map to configure. * @reg: The register index. * @value: The new register value. * * Return a negative value on failure, 0 on success. */ int regcache_write(struct regmap *map, unsigned int reg, unsigned int value) { if (map->cache_type == REGCACHE_NONE) return 0; BUG_ON(!map->cache_ops); if (!regmap_volatile(map, reg)) return map->cache_ops->write(map, reg, value); return 0; }
/** * regcache_read: Fetch the value of a given register from the cache. * * @map: map to configure. * @reg: The register index. * @value: The value to be returned. * * Return a negative value on failure, 0 on success. */ int regcache_read(struct regmap *map, unsigned int reg, unsigned int *value) { if (map->cache_type == REGCACHE_NONE) return -ENOSYS; BUG_ON(!map->cache_ops); if (!regmap_readable(map, reg)) return -EIO; if (!regmap_volatile(map, reg)) return map->cache_ops->read(map, reg, value); return -EINVAL; }
/** * regcache_read: Fetch the value of a given register from the cache. * * @map: map to configure. * @reg: The register index. * @value: The value to be returned. * * Return a negative value on failure, 0 on success. */ int regcache_read(struct regmap *map, unsigned int reg, unsigned int *value) { int ret; if (map->cache_type == REGCACHE_NONE) return -ENOSYS; BUG_ON(!map->cache_ops); if (!regmap_volatile(map, reg)) { ret = map->cache_ops->read(map, reg, value); if (ret == 0) trace_regmap_reg_read_cache(map->dev, reg, *value); return ret; } return -EINVAL; }
static int _regcache_volatile_set(struct regmap *map, unsigned int reg, bool is_volatile) { int ret; if (is_volatile == regmap_volatile(map, reg)) return 0; if (!map->reg_volatile_set) return -ENOSYS; if (!map->cache_present) return -ENOENT; ret = map->reg_volatile_set(map->dev, reg, is_volatile); if (ret) return ret; regcache_clear_reg_present(map, reg); return 0; }
/** * regmap_raw_read(): Read raw data from the device * * @map: Register map to write to * @reg: First register to be read from * @val: Pointer to store read value * @val_len: Size of data to read * * A value of zero will be returned on success, a negative errno will * be returned in error cases. */ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, size_t val_len) { int ret; int i; bool vol = true; for (i = 0; i < val_len / map->format.val_bytes; i++) if (!regmap_volatile(map, reg + i)) vol = false; WARN_ON(!vol && map->cache_type != REGCACHE_NONE); mutex_lock(&map->lock); ret = _regmap_raw_read(map, reg, val, val_len); mutex_unlock(&map->lock); return ret; }
static int regcache_hw_init(struct regmap *map) { int i, j; int ret; int count; unsigned int val; void *tmp_buf; if (!map->num_reg_defaults_raw) return -EINVAL; if (!map->reg_defaults_raw) { u32 cache_bypass = map->cache_bypass; dev_warn(map->dev, "No cache defaults, reading back from HW\n"); /* Bypass the cache access till data read from HW*/ map->cache_bypass = 1; tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); if (!tmp_buf) return -EINVAL; ret = regmap_bulk_read(map, 0, tmp_buf, map->num_reg_defaults_raw); map->cache_bypass = cache_bypass; if (ret < 0) { kfree(tmp_buf); return ret; } map->reg_defaults_raw = tmp_buf; map->cache_free = 1; } /* calculate the size of reg_defaults */ for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { val = regcache_get_val(map->reg_defaults_raw, i, map->cache_word_size); if (regmap_volatile(map, i * map->reg_stride)) continue; count++; } map->reg_defaults = kmalloc(count * sizeof(struct reg_default), GFP_KERNEL); if (!map->reg_defaults) { ret = -ENOMEM; goto err_free; } /* fill the reg_defaults */ map->num_reg_defaults = count; for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { val = regcache_get_val(map->reg_defaults_raw, i, map->cache_word_size); if (regmap_volatile(map, i * map->reg_stride)) continue; map->reg_defaults[j].reg = i * map->reg_stride; map->reg_defaults[j].def = val; j++; } return 0; err_free: if (map->cache_free) kfree(map->reg_defaults_raw); return ret; }
static ssize_t regmap_access_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { int reg_len, tot_len; size_t buf_pos = 0; loff_t p = 0; ssize_t ret; int i; struct regmap *map = file->private_data; char *buf; if (*ppos < 0 || !count) return -EINVAL; buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; /* Calculate the length of a fixed format */ reg_len = regmap_calc_reg_len(map->max_register, buf, count); tot_len = reg_len + 10; /* ': R W V P\n' */ for (i = 0; i < map->max_register + 1; i++) { /* Ignore registers which are neither readable nor writable */ if (!regmap_readable(map, i) && !regmap_writeable(map, i)) continue; /* If we're in the region the user is trying to read */ if (p >= *ppos) { /* ...but not beyond it */ if (buf_pos >= count - 1 - tot_len) break; /* Format the register */ snprintf(buf + buf_pos, count - buf_pos, "%.*x: %c %c %c %c\n", reg_len, i, regmap_readable(map, i) ? 'y' : 'n', regmap_writeable(map, i) ? 'y' : 'n', regmap_volatile(map, i) ? 'y' : 'n', regmap_precious(map, i) ? 'y' : 'n'); buf_pos += tot_len; } p += tot_len; } ret = buf_pos; if (copy_to_user(user_buf, buf, buf_pos)) { ret = -EFAULT; goto out; } *ppos += buf_pos; out: kfree(buf); return ret; }
static ssize_t regmap_access_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { int reg_len, tot_len; size_t buf_pos = 0; loff_t p = 0; ssize_t ret; int i; struct regmap *map = file->private_data; char *buf; if (*ppos < 0 || !count) return -EINVAL; buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; reg_len = regmap_calc_reg_len(map->max_register, buf, count); tot_len = reg_len + 10; for (i = 0; i < map->max_register + 1; i++) { if (!regmap_readable(map, i) && !regmap_writeable(map, i)) continue; if (p >= *ppos) { if (buf_pos >= count - 1 - tot_len) break; snprintf(buf + buf_pos, count - buf_pos, "%.*x: %c %c %c %c\n", reg_len, i, regmap_readable(map, i) ? 'y' : 'n', regmap_writeable(map, i) ? 'y' : 'n', regmap_volatile(map, i) ? 'y' : 'n', regmap_precious(map, i) ? 'y' : 'n'); buf_pos += tot_len; } p += tot_len; } ret = buf_pos; if (copy_to_user(user_buf, buf, buf_pos)) { ret = -EFAULT; goto out; } *ppos += buf_pos; out: kfree(buf); return ret; }
static int regcache_hw_init(struct regmap *map) { int i, j; int ret; int count; unsigned int reg, val; void *tmp_buf; if (!map->num_reg_defaults_raw) return -EINVAL; /* calculate the size of reg_defaults */ for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) if (regmap_readable(map, i * map->reg_stride) && !regmap_volatile(map, i * map->reg_stride)) count++; /* all registers are unreadable or volatile, so just bypass */ if (!count) { map->cache_bypass = true; return 0; } map->num_reg_defaults = count; map->reg_defaults = kmalloc_array(count, sizeof(struct reg_default), GFP_KERNEL); if (!map->reg_defaults) return -ENOMEM; if (!map->reg_defaults_raw) { bool cache_bypass = map->cache_bypass; dev_warn(map->dev, "No cache defaults, reading back from HW\n"); /* Bypass the cache access till data read from HW */ map->cache_bypass = true; tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); if (!tmp_buf) { ret = -ENOMEM; goto err_free; } ret = regmap_raw_read(map, 0, tmp_buf, map->cache_size_raw); map->cache_bypass = cache_bypass; if (ret == 0) { map->reg_defaults_raw = tmp_buf; map->cache_free = 1; } else { kfree(tmp_buf); } } /* fill the reg_defaults */ for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { reg = i * map->reg_stride; if (!regmap_readable(map, reg)) continue; if (regmap_volatile(map, reg)) continue; if (map->reg_defaults_raw) { val = regcache_get_val(map, map->reg_defaults_raw, i); } else { bool cache_bypass = map->cache_bypass; map->cache_bypass = true; ret = regmap_read(map, reg, &val); map->cache_bypass = cache_bypass; if (ret != 0) { dev_err(map->dev, "Failed to read %d: %d\n", reg, ret); goto err_free; } } map->reg_defaults[j].reg = reg; map->reg_defaults[j].def = val; j++; } return 0; err_free: kfree(map->reg_defaults); return ret; }