*参照元 [#o1cfe50a]
#backlinks

*説明 [#zc9e359e]
-パス: [[linux-4.4.1/drivers/base/regmap/regmap.c]]

-FIXME: これは何?
--説明


**引数 [#g88475c7]
-struct device *dev
--
--[[linux-4.4.1/device]]
-const struct regmap_bus *bus
--
--[[linux-4.4.1/regmap_bus]]
-void *bus_context
--
-const struct regmap_config *config
--
--[[linux-4.4.1/regmap_config]]
-struct lock_class_key *lock_key
--
--[[linux-4.4.1/lock_class_key]]
-const char *lock_name
--


**返り値 [#ub55c3aa]
-struct regmap *
--
--[[linux-4.4.1/regmap]]


**参考 [#m26fa42e]


*実装 [#o61988bc]
 struct regmap *__regmap_init(struct device *dev,
                              const struct regmap_bus *bus,
                              void *bus_context,
                              const struct regmap_config *config,
                              struct lock_class_key *lock_key,
                              const char *lock_name)
 {
         struct regmap *map;
         int ret = -EINVAL;
         enum regmap_endian reg_endian, val_endian;
         int i, j;
 
-
--[[linux-4.4.1/regmap]]
--[[linux-4.4.1/regmap_endian]]

         if (!config)
                 goto err;
 
         map = kzalloc(sizeof(*map), GFP_KERNEL);
         if (map == NULL) {
                 ret = -ENOMEM;
                 goto err;
         }
 
-
--[[linux-4.4.1/kzalloc()]]

         if (config->lock && config->unlock) {
                 map->lock = config->lock;
                 map->unlock = config->unlock;
                 map->lock_arg = config->lock_arg;
         } else {
                 if ((bus && bus->fast_io) ||
                     config->fast_io) {
                         spin_lock_init(&map->spinlock);
                         map->lock = regmap_lock_spinlock;
                         map->unlock = regmap_unlock_spinlock;
                         lockdep_set_class_and_name(&map->spinlock,
                                                    lock_key, lock_name);
                 } else {
                         mutex_init(&map->mutex);
                         map->lock = regmap_lock_mutex;
                         map->unlock = regmap_unlock_mutex;
                         lockdep_set_class_and_name(&map->mutex,
                                                    lock_key, lock_name);
                 }
                 map->lock_arg = map;
         }
 
-
--[[linux-4.4.1/spin_lock_init()]]
--[[linux-4.4.1/regmap_lock_spinlock()]]
--[[linux-4.4.1/regmap_unlock_spinlock()]]
--[[linux-4.4.1/regmap_lock_mutex()]]
--[[linux-4.4.1/regmap_unlock_mutex()]]
--[[linux-4.4.1/lockdep_set_class_and_name()]]

         /*
          * When we write in fast-paths with regmap_bulk_write() don't allocate
          * scratch buffers with sleeping allocations.
          */
         if ((bus && bus->fast_io) || config->fast_io)
                 map->alloc_flags = GFP_ATOMIC;
         else
                 map->alloc_flags = GFP_KERNEL;
 
         map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
         map->format.pad_bytes = config->pad_bits / 8;
         map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
         map->format.buf_size = DIV_ROUND_UP(config->reg_bits +
                         config->val_bits + config->pad_bits, 8);
         map->reg_shift = config->pad_bits % 8;
-
--map->format は struct regmap_format 型
--[[linux-4.4.1/regmap_format]]
--[[linux-4.4.1/DIV_ROUND_UP()]]

         if (config->reg_stride)
                 map->reg_stride = config->reg_stride;
         else
                 map->reg_stride = 1;
         map->use_single_read = config->use_single_rw || !bus || !bus->read;
         map->use_single_write = config->use_single_rw || !bus || !bus->write;
         map->can_multi_write = config->can_multi_write && bus && bus->write;
         if (bus) {
                 map->max_raw_read = bus->max_raw_read;
                 map->max_raw_write = bus->max_raw_write;
         }
         map->dev = dev;
         map->bus = bus;
         map->bus_context = bus_context;
         map->max_register = config->max_register;
         map->wr_table = config->wr_table;
         map->rd_table = config->rd_table;
         map->volatile_table = config->volatile_table;
         map->precious_table = config->precious_table;
         map->writeable_reg = config->writeable_reg;
         map->readable_reg = config->readable_reg;
         map->volatile_reg = config->volatile_reg;
         map->precious_reg = config->precious_reg;
         map->cache_type = config->cache_type;
         map->name = config->name;
 
         spin_lock_init(&map->async_lock);
         INIT_LIST_HEAD(&map->async_list);
         INIT_LIST_HEAD(&map->async_free);
         init_waitqueue_head(&map->async_waitq);
 
-
--[[linux-4.4.1/spin_lock_init()]]
--[[linux-4.4.1/INIT_LIST_HEAD()]]
--[[linux-4.4.1/init_waitqueue_head()]]

         if (config->read_flag_mask || config->write_flag_mask) {
                 map->read_flag_mask = config->read_flag_mask;
                 map->write_flag_mask = config->write_flag_mask;
         } else if (bus) {
                 map->read_flag_mask = bus->read_flag_mask;
         }
 
         if (!bus) {
                 map->reg_read  = config->reg_read;
                 map->reg_write = config->reg_write;
 
                 map->defer_caching = false;
                 goto skip_format_initialization;
         } else if (!bus->read || !bus->write) {
                 map->reg_read = _regmap_bus_reg_read;
                 map->reg_write = _regmap_bus_reg_write;
 
                 map->defer_caching = false;
                 goto skip_format_initialization;
         } else {
                 map->reg_read  = _regmap_bus_read;
                 map->reg_update_bits = bus->reg_update_bits;
         }
 
         reg_endian = regmap_get_reg_endian(bus, config);
         val_endian = regmap_get_val_endian(dev, bus, config);
 
-
--[[linux-4.4.1/regmap_get_reg_endian()]]
--[[linux-4.4.1/regmap_get_val_endian()]]

         switch (config->reg_bits + map->reg_shift) {
         case 2:
                 switch (config->val_bits) {
                 case 6:
                         map->format.format_write = regmap_format_2_6_write;
                         break;
                 default:
                         goto err_map;
                 }
                 break;
 
-
--map->format は struct regmap_format 型
--[[linux-4.4.1/regmap_format]]
--[[linux-4.4.1/regmap_format_2_6_write()]]

         case 4:
                 switch (config->val_bits) {
                 case 12:
                         map->format.format_write = regmap_format_4_12_write;
                         break;
                 default:
                         goto err_map;
                 }
                 break;
 
-
--[[linux-4.4.1/regmap_format_4_12_write()]]

         case 7:
                 switch (config->val_bits) {
                 case 9:
                         map->format.format_write = regmap_format_7_9_write;
                         break;
                 default:
                         goto err_map;
                 }
                 break;
 
-
--[[linux-4.4.1/regmap_format_7_9_write()]]

         case 10:
                 switch (config->val_bits) {
                 case 14:
                         map->format.format_write = regmap_format_10_14_write;
                         break;
                 default:
                         goto err_map;
                 }
                 break;
 
-
--[[linux-4.4.1/regmap_format_10_14_write()]]

         case 8:
                 map->format.format_reg = regmap_format_8;
                 break;
 
-
--[[linux-4.4.1/regmap_format_8()]]

         case 16:
                 switch (reg_endian) {
                 case REGMAP_ENDIAN_BIG:
                         map->format.format_reg = regmap_format_16_be;
                         break;
                 case REGMAP_ENDIAN_NATIVE:
                         map->format.format_reg = regmap_format_16_native;
                         break;
                 default:
                         goto err_map;
                 }
                 break;
 
-
--[[linux-4.4.1/regmap_format_16_be()]]
--[[linux-4.4.1/regmap_format_16_native()]]

         case 24:
                 if (reg_endian != REGMAP_ENDIAN_BIG)
                         goto err_map;
                 map->format.format_reg = regmap_format_24;
                 break;
 
-
--[[linux-4.4.1/regmap_format_24()]]

         case 32:
                 switch (reg_endian) {
                 case REGMAP_ENDIAN_BIG:
                         map->format.format_reg = regmap_format_32_be;
                         break;
                 case REGMAP_ENDIAN_NATIVE:
                         map->format.format_reg = regmap_format_32_native;
                         break;
                 default:
                         goto err_map;
                 }
                 break;
 
-
--[[linux-4.4.1/regmap_format_32_be()]]
--[[linux-4.4.1/regmap_format_32_native()]]

         default:
                 goto err_map;
         }
 
         if (val_endian == REGMAP_ENDIAN_NATIVE)
                 map->format.parse_inplace = regmap_parse_inplace_noop;
 
-
--map->format は struct regmap_format 型
--[[linux-4.4.1/regmap_format]]
--[[linux-4.4.1/regmap_parse_inplace_noop()]]

         switch (config->val_bits) {
         case 8:
                 map->format.format_val = regmap_format_8;
                 map->format.parse_val = regmap_parse_8;
                 map->format.parse_inplace = regmap_parse_inplace_noop;
                 break;
-
--[[linux-4.4.1/regmap_format_8()]]
--[[linux-4.4.1/regmap_parse_8()]]
--[[linux-4.4.1/regmap_parse_inplace_noop()]]

         case 16:
                 switch (val_endian) {
                 case REGMAP_ENDIAN_BIG:
                         map->format.format_val = regmap_format_16_be;
                         map->format.parse_val = regmap_parse_16_be;
                         map->format.parse_inplace = regmap_parse_16_be_inplace;
                         break;
-
--[[linux-4.4.1/regmap_format_16_be()]]
--[[linux-4.4.1/regmap_parse_16_be()]]
--[[linux-4.4.1/regmap_parse_16_be_inplace()]]

                 case REGMAP_ENDIAN_LITTLE:
                         map->format.format_val = regmap_format_16_le;
                         map->format.parse_val = regmap_parse_16_le;
                         map->format.parse_inplace = regmap_parse_16_le_inplace;
                         break;
-
--[[linux-4.4.1/regmap_format_16_le()]]
--[[linux-4.4.1/regmap_parse_16_le()]]
--[[linux-4.4.1/regmap_parse_16_le_inplace()]]

                 case REGMAP_ENDIAN_NATIVE:
                         map->format.format_val = regmap_format_16_native;
                         map->format.parse_val = regmap_parse_16_native;
                         break;
-
--[[linux-4.4.1/regmap_format_16_native()]]
--[[linux-4.4.1/regmap_parse_16_native()]]

                 default:
                         goto err_map;
                 }
                 break;
         case 24:
                 if (val_endian != REGMAP_ENDIAN_BIG)
                         goto err_map;
                 map->format.format_val = regmap_format_24;
                 map->format.parse_val = regmap_parse_24;
                 break;
-
--[[linux-4.4.1/regmap_format_16_le()]]
--[[linux-4.4.1/regmap_parse_16_le()]]
--[[linux-4.4.1/regmap_parse_16_le_inplace()]]

         case 32:
                 switch (val_endian) {
                 case REGMAP_ENDIAN_BIG:
                         map->format.format_val = regmap_format_32_be;
                         map->format.parse_val = regmap_parse_32_be;
                         map->format.parse_inplace = regmap_parse_32_be_inplace;
-
--[[linux-4.4.1/regmap_format_32_be()]]
--[[linux-4.4.1/regmap_parse_32_be()]]
--[[linux-4.4.1/regmap_parse_32_be_inplace()]]

                         break;
                 case REGMAP_ENDIAN_LITTLE:
                         map->format.format_val = regmap_format_32_le;
                         map->format.parse_val = regmap_parse_32_le;
                         map->format.parse_inplace = regmap_parse_32_le_inplace;
                         break;
-
--[[linux-4.4.1/regmap_format_32_le()]]
--[[linux-4.4.1/regmap_parse_32_le()]]
--[[linux-4.4.1/regmap_parse_32_le_inplace()]]

                 case REGMAP_ENDIAN_NATIVE:
                         map->format.format_val = regmap_format_32_native;
                         map->format.parse_val = regmap_parse_32_native;
                         break;
-
--[[linux-4.4.1/regmap_format_32_native()]]
--[[linux-4.4.1/regmap_parse_32_native()]]

                 default:
                         goto err_map;
                 }
                 break;
         }
 
         if (map->format.format_write) {
                 if ((reg_endian != REGMAP_ENDIAN_BIG) ||
                     (val_endian != REGMAP_ENDIAN_BIG))
                         goto err_map;
                 map->use_single_write = true;
         }
 
         if (!map->format.format_write &&
             !(map->format.format_reg && map->format.format_val))
                 goto err_map;
 
         map->work_buf = kzalloc(map->format.buf_size, GFP_KERNEL);
         if (map->work_buf == NULL) {
                 ret = -ENOMEM;
                 goto err_map;
         }
 
-
--[[linux-4.4.1/kzalloc()]]

         if (map->format.format_write) {
                 map->defer_caching = false;
                 map->reg_write = _regmap_bus_formatted_write;
         } else if (map->format.format_val) {
                 map->defer_caching = true;
                 map->reg_write = _regmap_bus_raw_write;
         }
 
-
--[[linux-4.4.1/_regmap_bus_formatted_write()]]
--[[linux-4.4.1/_regmap_bus_raw_write()]]

 skip_format_initialization:
 
         map->range_tree = RB_ROOT;
         for (i = 0; i < config->num_ranges; i++) {
                 const struct regmap_range_cfg *range_cfg = &config->ranges[i];
                 struct regmap_range_node *new;
 
-
--[[linux-4.4.1/regmap_range_cfg]]
--[[linux-4.4.1/regmap_range_node]]

                 /* Sanity check */
                 if (range_cfg->range_max < range_cfg->range_min) {
                         dev_err(map->dev, "Invalid range %d: %d < %d\n", i,
                                 range_cfg->range_max, range_cfg->range_min);
                         goto err_range;
                 }
 
-
--[[linux-4.4.1/dev_err()]]

                 if (range_cfg->range_max > map->max_register) {
                         dev_err(map->dev, "Invalid range %d: %d > %d\n", i,
                                 range_cfg->range_max, map->max_register);
                         goto err_range;
                 }
 
                 if (range_cfg->selector_reg > map->max_register) {
                         dev_err(map->dev,
                                 "Invalid range %d: selector out of map\n", i);
                         goto err_range;
                 }
 
                 if (range_cfg->window_len == 0) {
                         dev_err(map->dev, "Invalid range %d: window_len 0\n",
                                 i);
                         goto err_range;
                 }
 
                 /* Make sure, that this register range has no selector
                    or data window within its boundary */
                 for (j = 0; j < config->num_ranges; j++) {
                         unsigned sel_reg = config->ranges[j].selector_reg;
                         unsigned win_min = config->ranges[j].window_start;
                         unsigned win_max = win_min +
                                            config->ranges[j].window_len - 1;
 
                         /* Allow data window inside its own virtual range */
                         if (j == i)
                                 continue;
 
                         if (range_cfg->range_min <= sel_reg &&
                             sel_reg <= range_cfg->range_max) {
                                 dev_err(map->dev,
                                         "Range %d: selector for %d in window\n",
                                         i, j);
                                 goto err_range;
                         }
 
                         if (!(win_max < range_cfg->range_min ||
                               win_min > range_cfg->range_max)) {
                                 dev_err(map->dev,
                                         "Range %d: window for %d in window\n",
                                         i, j);
                                 goto err_range;
                         }
                 }
 
                 new = kzalloc(sizeof(*new), GFP_KERNEL);
                 if (new == NULL) {
                         ret = -ENOMEM;
                         goto err_range;
                 }
 
                 new->map = map;
                 new->name = range_cfg->name;
                 new->range_min = range_cfg->range_min;
                 new->range_max = range_cfg->range_max;
                 new->selector_reg = range_cfg->selector_reg;
                 new->selector_mask = range_cfg->selector_mask;
                 new->selector_shift = range_cfg->selector_shift;
                 new->window_start = range_cfg->window_start;
                 new->window_len = range_cfg->window_len;
 
                 if (!_regmap_range_add(map, new)) {
                         dev_err(map->dev, "Failed to add range %d\n", i);
                         kfree(new);
                         goto err_range;
                 }
 
-
--[[linux-4.4.1/_remap_range_add()]]
--[[linux-4.4.1/kfree()]]

                 if (map->selector_work_buf == NULL) {
                         map->selector_work_buf =
                                 kzalloc(map->format.buf_size, GFP_KERNEL);
                         if (map->selector_work_buf == NULL) {
                                 ret = -ENOMEM;
                                 goto err_range;
                         }
                 }
         }
 
         ret = regcache_init(map, config);
         if (ret != 0)
                 goto err_range;
 
-
--[[linux-4.4.1/regcache_init()]]

         if (dev) {
                 ret = regmap_attach_dev(dev, map, config);
                 if (ret != 0)
                         goto err_regcache;
         }
 
-
--[[linux-4.4.1/regmap_attach_dev()]]

         return map;
 
 err_regcache:
         regcache_exit(map);
-
--[[linux-4.4.1/regcache_exit()]]

 err_range:
         regmap_range_exit(map);
         kfree(map->work_buf);
-
--[[linux-4.4.1/regmap_range_exit()]]

 err_map:
         kfree(map);
 err:
         return ERR_PTR(ret);
-
--[[linux-4.4.1/ERR_PTR()]]

 }
 EXPORT_SYMBOL_GPL(__regmap_init);
-
--[[linux-4.4.1/EXPORT_SYMBOL_GPL()]]


*コメント [#a5052838]

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