Loading drivers/reset/core.c +95 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ static DEFINE_MUTEX(reset_list_mutex); static LIST_HEAD(reset_controller_list); static DEFINE_MUTEX(reset_lookup_mutex); static LIST_HEAD(reset_lookup_list); /** * struct reset_control - a reset control * @rcdev: a pointer to the reset controller device Loading Loading @@ -148,6 +151,33 @@ int devm_reset_controller_register(struct device *dev, } EXPORT_SYMBOL_GPL(devm_reset_controller_register); /** * reset_controller_add_lookup - register a set of lookup entries * @lookup: array of reset lookup entries * @num_entries: number of entries in the lookup array */ void reset_controller_add_lookup(struct reset_control_lookup *lookup, unsigned int num_entries) { struct reset_control_lookup *entry; unsigned int i; mutex_lock(&reset_lookup_mutex); for (i = 0; i < num_entries; i++) { entry = &lookup[i]; if (!entry->dev_id || !entry->provider) { pr_warn("%s(): reset lookup entry badly specified, skipping\n", __func__); continue; } list_add_tail(&entry->list, &reset_lookup_list); } mutex_unlock(&reset_lookup_mutex); } EXPORT_SYMBOL_GPL(reset_controller_add_lookup); static inline struct reset_control_array * rstc_to_array(struct reset_control *rstc) { return container_of(rstc, struct reset_control_array, base); Loading Loading @@ -493,6 +523,70 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } EXPORT_SYMBOL_GPL(__of_reset_control_get); static struct reset_controller_dev * __reset_controller_by_name(const char *name) { struct reset_controller_dev *rcdev; lockdep_assert_held(&reset_list_mutex); list_for_each_entry(rcdev, &reset_controller_list, list) { if (!rcdev->dev) continue; if (!strcmp(name, dev_name(rcdev->dev))) return rcdev; } return NULL; } static struct reset_control * __reset_control_get_from_lookup(struct device *dev, const char *con_id, bool shared, bool optional) { const struct reset_control_lookup *lookup; struct reset_controller_dev *rcdev; const char *dev_id = dev_name(dev); struct reset_control *rstc = NULL; if (!dev) return ERR_PTR(-EINVAL); mutex_lock(&reset_lookup_mutex); list_for_each_entry(lookup, &reset_lookup_list, list) { if (strcmp(lookup->dev_id, dev_id)) continue; if ((!con_id && !lookup->con_id) || ((con_id && lookup->con_id) && !strcmp(con_id, lookup->con_id))) { mutex_lock(&reset_list_mutex); rcdev = __reset_controller_by_name(lookup->provider); if (!rcdev) { mutex_unlock(&reset_list_mutex); mutex_unlock(&reset_lookup_mutex); /* Reset provider may not be ready yet. */ return ERR_PTR(-EPROBE_DEFER); } rstc = __reset_control_get_internal(rcdev, lookup->index, shared); mutex_unlock(&reset_list_mutex); break; } } mutex_unlock(&reset_lookup_mutex); if (!rstc) return optional ? NULL : ERR_PTR(-ENOENT); return rstc; } struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) { Loading @@ -500,7 +594,7 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, return __of_reset_control_get(dev->of_node, id, index, shared, optional); return optional ? NULL : ERR_PTR(-EINVAL); return __reset_control_get_from_lookup(dev, id, shared, optional); } EXPORT_SYMBOL_GPL(__reset_control_get); Loading include/linux/reset-controller.h +30 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,31 @@ struct module; struct device_node; struct of_phandle_args; /** * struct reset_control_lookup - represents a single lookup entry * * @list: internal list of all reset lookup entries * @provider: name of the reset controller device controlling this reset line * @index: ID of the reset controller in the reset controller device * @dev_id: name of the device associated with this reset line * @con_id name of the reset line (can be NULL) */ struct reset_control_lookup { struct list_head list; const char *provider; unsigned int index; const char *dev_id; const char *con_id; }; #define RESET_LOOKUP(_provider, _index, _dev_id, _con_id) \ { \ .provider = _provider, \ .index = _index, \ .dev_id = _dev_id, \ .con_id = _con_id, \ } /** * struct reset_controller_dev - reset controller entity that might * provide multiple reset controls Loading @@ -33,6 +58,7 @@ struct of_phandle_args; * @owner: kernel module of the reset controller driver * @list: internal list of reset controller devices * @reset_control_head: head of internal list of requested reset controls * @dev: corresponding driver model device struct * @of_node: corresponding device tree node as phandle target * @of_reset_n_cells: number of cells in reset line specifiers * @of_xlate: translation function to translate from specifier as found in the Loading @@ -44,6 +70,7 @@ struct reset_controller_dev { struct module *owner; struct list_head list; struct list_head reset_control_head; struct device *dev; struct device_node *of_node; int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, Loading @@ -58,4 +85,7 @@ struct device; int devm_reset_controller_register(struct device *dev, struct reset_controller_dev *rcdev); void reset_controller_add_lookup(struct reset_control_lookup *lookup, unsigned int num_entries); #endif Loading
drivers/reset/core.c +95 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ static DEFINE_MUTEX(reset_list_mutex); static LIST_HEAD(reset_controller_list); static DEFINE_MUTEX(reset_lookup_mutex); static LIST_HEAD(reset_lookup_list); /** * struct reset_control - a reset control * @rcdev: a pointer to the reset controller device Loading Loading @@ -148,6 +151,33 @@ int devm_reset_controller_register(struct device *dev, } EXPORT_SYMBOL_GPL(devm_reset_controller_register); /** * reset_controller_add_lookup - register a set of lookup entries * @lookup: array of reset lookup entries * @num_entries: number of entries in the lookup array */ void reset_controller_add_lookup(struct reset_control_lookup *lookup, unsigned int num_entries) { struct reset_control_lookup *entry; unsigned int i; mutex_lock(&reset_lookup_mutex); for (i = 0; i < num_entries; i++) { entry = &lookup[i]; if (!entry->dev_id || !entry->provider) { pr_warn("%s(): reset lookup entry badly specified, skipping\n", __func__); continue; } list_add_tail(&entry->list, &reset_lookup_list); } mutex_unlock(&reset_lookup_mutex); } EXPORT_SYMBOL_GPL(reset_controller_add_lookup); static inline struct reset_control_array * rstc_to_array(struct reset_control *rstc) { return container_of(rstc, struct reset_control_array, base); Loading Loading @@ -493,6 +523,70 @@ struct reset_control *__of_reset_control_get(struct device_node *node, } EXPORT_SYMBOL_GPL(__of_reset_control_get); static struct reset_controller_dev * __reset_controller_by_name(const char *name) { struct reset_controller_dev *rcdev; lockdep_assert_held(&reset_list_mutex); list_for_each_entry(rcdev, &reset_controller_list, list) { if (!rcdev->dev) continue; if (!strcmp(name, dev_name(rcdev->dev))) return rcdev; } return NULL; } static struct reset_control * __reset_control_get_from_lookup(struct device *dev, const char *con_id, bool shared, bool optional) { const struct reset_control_lookup *lookup; struct reset_controller_dev *rcdev; const char *dev_id = dev_name(dev); struct reset_control *rstc = NULL; if (!dev) return ERR_PTR(-EINVAL); mutex_lock(&reset_lookup_mutex); list_for_each_entry(lookup, &reset_lookup_list, list) { if (strcmp(lookup->dev_id, dev_id)) continue; if ((!con_id && !lookup->con_id) || ((con_id && lookup->con_id) && !strcmp(con_id, lookup->con_id))) { mutex_lock(&reset_list_mutex); rcdev = __reset_controller_by_name(lookup->provider); if (!rcdev) { mutex_unlock(&reset_list_mutex); mutex_unlock(&reset_lookup_mutex); /* Reset provider may not be ready yet. */ return ERR_PTR(-EPROBE_DEFER); } rstc = __reset_control_get_internal(rcdev, lookup->index, shared); mutex_unlock(&reset_list_mutex); break; } } mutex_unlock(&reset_lookup_mutex); if (!rstc) return optional ? NULL : ERR_PTR(-ENOENT); return rstc; } struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional) { Loading @@ -500,7 +594,7 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, return __of_reset_control_get(dev->of_node, id, index, shared, optional); return optional ? NULL : ERR_PTR(-EINVAL); return __reset_control_get_from_lookup(dev, id, shared, optional); } EXPORT_SYMBOL_GPL(__reset_control_get); Loading
include/linux/reset-controller.h +30 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,31 @@ struct module; struct device_node; struct of_phandle_args; /** * struct reset_control_lookup - represents a single lookup entry * * @list: internal list of all reset lookup entries * @provider: name of the reset controller device controlling this reset line * @index: ID of the reset controller in the reset controller device * @dev_id: name of the device associated with this reset line * @con_id name of the reset line (can be NULL) */ struct reset_control_lookup { struct list_head list; const char *provider; unsigned int index; const char *dev_id; const char *con_id; }; #define RESET_LOOKUP(_provider, _index, _dev_id, _con_id) \ { \ .provider = _provider, \ .index = _index, \ .dev_id = _dev_id, \ .con_id = _con_id, \ } /** * struct reset_controller_dev - reset controller entity that might * provide multiple reset controls Loading @@ -33,6 +58,7 @@ struct of_phandle_args; * @owner: kernel module of the reset controller driver * @list: internal list of reset controller devices * @reset_control_head: head of internal list of requested reset controls * @dev: corresponding driver model device struct * @of_node: corresponding device tree node as phandle target * @of_reset_n_cells: number of cells in reset line specifiers * @of_xlate: translation function to translate from specifier as found in the Loading @@ -44,6 +70,7 @@ struct reset_controller_dev { struct module *owner; struct list_head list; struct list_head reset_control_head; struct device *dev; struct device_node *of_node; int of_reset_n_cells; int (*of_xlate)(struct reset_controller_dev *rcdev, Loading @@ -58,4 +85,7 @@ struct device; int devm_reset_controller_register(struct device *dev, struct reset_controller_dev *rcdev); void reset_controller_add_lookup(struct reset_control_lookup *lookup, unsigned int num_entries); #endif