*参照元 [#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, &reg, 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]


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS