*参照元 [#yf831632] #backlinks *説明 [#t7f628f2] -パス: [[linux-4.4.1/drivers/base/regmap/regmap.c]] -FIXME: これは何? --説明 **引数 [#ud2689cd] -struct regmap *map -- --[[linux-4.4.1/regmap]] -unsigned int reg -- -const void *val -- -size_t val_len -- **返り値 [#ncf98cf3] -int -- **参考 [#qb798f22] *実装 [#eec8c2db] int _regmap_raw_write(struct regmap *map, unsigned int reg, const void *val, size_t val_len) { struct regmap_range_node *range; unsigned long flags; u8 *u8 = map->work_buf; void *work_val = map->work_buf + map->format.reg_bytes + map->format.pad_bytes; void *buf; int ret = -ENOTSUPP; size_t len; int i; - --[[linux-4.4.1/regmap_range_node]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] WARN_ON(!map->bus); - --[[linux-4.4.1/WARN_ON()]] /* Check for unwritable registers before we start */ if (map->writeable_reg) for (i = 0; i < val_len / map->format.val_bytes; i++) if (!map->writeable_reg(map->dev, reg + (i * map->reg_stride))) return -EINVAL; if (!map->cache_bypass && map->format.parse_val) { unsigned int ival; int val_bytes = map->format.val_bytes; for (i = 0; i < val_len / val_bytes; i++) { ival = map->format.parse_val(val + (i * val_bytes)); ret = regcache_write(map, reg + (i * map->reg_stride), ival); if (ret) { dev_err(map->dev, "Error in caching of register: %x ret: %d\n", reg + i, ret); return ret; } - --[[linux-4.4.1/regcache_write()]] --[[linux-4.4.1/dev_err()]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] } if (map->cache_only) { map->cache_dirty = true; return 0; } } range = _regmap_range_lookup(map, reg); - --[[linux-4.4.1/_regmap_range_lookup()]] if (range) { int val_num = val_len / map->format.val_bytes; int win_offset = (reg - range->range_min) % range->window_len; int win_residue = range->window_len - win_offset; /* If the write goes beyond the end of the window split it */ while (val_num > win_residue) { dev_dbg(map->dev, "Writing window %d/%zu\n", win_residue, val_len / map->format.val_bytes); ret = _regmap_raw_write(map, reg, val, win_residue * map->format.val_bytes); if (ret != 0) return ret; - --[[linux-4.4.1/dev_dbg()]] --[[linux-4.4.1/_regmap_raw_write()]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] reg += win_residue; val_num -= win_residue; val += win_residue * map->format.val_bytes; val_len -= win_residue * map->format.val_bytes; win_offset = (reg - range->range_min) % range->window_len; win_residue = range->window_len - win_offset; } ret = _regmap_select_page(map, ®, range, val_num); if (ret != 0) return ret; - --[[linux-4.4.1/_regmap_select_page()]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] } map->format.format_reg(map->work_buf, reg, map->reg_shift); u8[0] |= map->write_flag_mask; /* * Essentially all I/O mechanisms will be faster with a single * buffer to write. Since register syncs often generate raw * writes of single registers optimise that case. */ if (val != work_val && val_len == map->format.val_bytes) { memcpy(work_val, val, map->format.val_bytes); val = work_val; } - --[[linux-4.4.1/memcpy()]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] if (map->async && map->bus->async_write) { struct regmap_async *async; trace_regmap_async_write_start(map, reg, val_len); spin_lock_irqsave(&map->async_lock, flags); async = list_first_entry_or_null(&map->async_free, struct regmap_async, list); if (async) list_del(&async->list); spin_unlock_irqrestore(&map->async_lock, flags); - --[[linux-4.4.1/regmap_async]] --[[linux-4.4.1/trace_regmap_async_write_start()]] --[[linux-4.4.1/spin_lock_irqsave()]] --[[linux-4.4.1/list_first_entry_or_null()]] --[[linux-4.4.1/list_del()]] --[[linux-4.4.1/spin_unlock_irqrestore()]] if (!async) { async = map->bus->async_alloc(); if (!async) return -ENOMEM; async->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL | GFP_DMA); if (!async->work_buf) { kfree(async); return -ENOMEM; } } - --map->bus は regmap_bus *型 --[[linux-4.4.1/regmap_bus]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] --[[linux-4.4.1/kzalloc()]] --[[linux-4.4.1/kfree()]] async->map = map; /* If the caller supplied the value we can use it safely. */ memcpy(async->work_buf, map->work_buf, map->format.pad_bytes + map->format.reg_bytes + map->format.val_bytes); - --[[linux-4.4.1/memcpy()]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] spin_lock_irqsave(&map->async_lock, flags); list_add_tail(&async->list, &map->async_list); spin_unlock_irqrestore(&map->async_lock, flags); - --[[linux-4.4.1/spin_lock_irqsave()]] --[[linux-4.4.1/list_add_tail()]] --[[linux-4.4.1/spin_unlock_irqrestore()]] if (val != work_val) ret = map->bus->async_write(map->bus_context, async->work_buf, map->format.reg_bytes + map->format.pad_bytes, val, val_len, async); else ret = map->bus->async_write(map->bus_context, async->work_buf, map->format.reg_bytes + map->format.pad_bytes + val_len, NULL, 0, async); - --map->bus は regmap_bus *型 --[[linux-4.4.1/regmap_bus]] if (ret != 0) { dev_err(map->dev, "Failed to schedule write: %d\n", ret); spin_lock_irqsave(&map->async_lock, flags); list_move(&async->list, &map->async_free); spin_unlock_irqrestore(&map->async_lock, flags); } - --[[linux-4.4.1/spin_lock_irqsave()]] --[[linux-4.4.1/list_move()]] --[[linux-4.4.1/spin_unlock_irqrestore()]] return ret; } trace_regmap_hw_write_start(map, reg, val_len / map->format.val_bytes); - --[[linux-4.4.1/trace_regmap_hw_write_start()]] /* If we're doing a single register write we can probably just * send the work_buf directly, otherwise try to do a gather * write. */ if (val == work_val) ret = map->bus->write(map->bus_context, map->work_buf, map->format.reg_bytes + map->format.pad_bytes + val_len); else if (map->bus->gather_write) ret = map->bus->gather_write(map->bus_context, map->work_buf, map->format.reg_bytes + map->format.pad_bytes, val, val_len); - --map->bus は regmap_bus *型 --[[linux-4.4.1/regmap_bus]] /* If that didn't work fall back on linearising by hand. */ if (ret == -ENOTSUPP) { len = map->format.reg_bytes + map->format.pad_bytes + val_len; buf = kzalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM; memcpy(buf, map->work_buf, map->format.reg_bytes); memcpy(buf + map->format.reg_bytes + map->format.pad_bytes, val, val_len); ret = map->bus->write(map->bus_context, buf, len); kfree(buf); - --[[linux-4.4.1/kzalloc()]] --[[linux-4.4.1/memcpy()]] --map->format は regmap_format 型 --[[linux-4.4.1/regmap_format]] --[[linux-4.4.1/kfree()]] } trace_regmap_hw_write_done(map, reg, val_len / map->format.val_bytes); - --[[linux-4.4.1/trace_regmap_hw_write_done()]] return ret; } *コメント [#q899ac6c]