diff options
author | Stephen Boyd <sboyd@kernel.org> | 2018-04-06 16:38:08 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2018-04-06 16:38:08 -0400 |
commit | b44c4ddf4a15c42a91a88aaa32b7d53cf43391cb (patch) | |
tree | 04dbcb069c73c3c1fd82d177c50f44fac75beff1 | |
parent | a339bdf64a7c41a6c88cc7da2eb432c876d5ce19 (diff) | |
parent | 5ced1923128470bda20d454cc6b07a8aa2f2e64d (diff) |
Merge branch 'clk-davinci' into clk-next
* clk-davinci:
clk: davinci: add a reset lookup table for psc0
reset: modify the way reset lookup works for board files
reset: add support for non-DT systems
-rw-r--r-- | drivers/clk/davinci/psc-da850.c | 7 | ||||
-rw-r--r-- | drivers/clk/davinci/psc.c | 1 | ||||
-rw-r--r-- | drivers/reset/core.c | 96 | ||||
-rw-r--r-- | include/linux/reset-controller.h | 30 |
4 files changed, 133 insertions, 1 deletions
diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c index ccc7eb17bf3a..d196dcbed560 100644 --- a/drivers/clk/davinci/psc-da850.c +++ b/drivers/clk/davinci/psc-da850.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/clk-provider.h> | 8 | #include <linux/clk-provider.h> |
9 | #include <linux/reset-controller.h> | ||
9 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
10 | #include <linux/clkdev.h> | 11 | #include <linux/clkdev.h> |
11 | #include <linux/init.h> | 12 | #include <linux/init.h> |
@@ -66,8 +67,14 @@ LPSC_CLKDEV3(ecap_clkdev, "fck", "ecap.0", | |||
66 | "fck", "ecap.1", | 67 | "fck", "ecap.1", |
67 | "fck", "ecap.2"); | 68 | "fck", "ecap.2"); |
68 | 69 | ||
70 | static struct reset_control_lookup da850_psc0_reset_lookup_table[] = { | ||
71 | RESET_LOOKUP("da850-psc0", 15, "davinci-rproc.0", NULL), | ||
72 | }; | ||
73 | |||
69 | static int da850_psc0_init(struct device *dev, void __iomem *base) | 74 | static int da850_psc0_init(struct device *dev, void __iomem *base) |
70 | { | 75 | { |
76 | reset_controller_add_lookup(da850_psc0_reset_lookup_table, | ||
77 | ARRAY_SIZE(da850_psc0_reset_lookup_table)); | ||
71 | return davinci_psc_register_clocks(dev, da850_psc0_info, 16, base); | 78 | return davinci_psc_register_clocks(dev, da850_psc0_info, 16, base); |
72 | } | 79 | } |
73 | 80 | ||
diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c index ff6f4a038e04..ce170e600f09 100644 --- a/drivers/clk/davinci/psc.c +++ b/drivers/clk/davinci/psc.c | |||
@@ -425,6 +425,7 @@ __davinci_psc_register_clocks(struct device *dev, | |||
425 | 425 | ||
426 | psc->rcdev.ops = &davinci_psc_reset_ops; | 426 | psc->rcdev.ops = &davinci_psc_reset_ops; |
427 | psc->rcdev.owner = THIS_MODULE; | 427 | psc->rcdev.owner = THIS_MODULE; |
428 | psc->rcdev.dev = dev; | ||
428 | psc->rcdev.of_node = dev->of_node; | 429 | psc->rcdev.of_node = dev->of_node; |
429 | psc->rcdev.of_reset_n_cells = 1; | 430 | psc->rcdev.of_reset_n_cells = 1; |
430 | psc->rcdev.of_xlate = davinci_psc_reset_of_xlate; | 431 | psc->rcdev.of_xlate = davinci_psc_reset_of_xlate; |
diff --git a/drivers/reset/core.c b/drivers/reset/core.c index da4292e9de97..6488292e129c 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c | |||
@@ -23,6 +23,9 @@ | |||
23 | static DEFINE_MUTEX(reset_list_mutex); | 23 | static DEFINE_MUTEX(reset_list_mutex); |
24 | static LIST_HEAD(reset_controller_list); | 24 | static LIST_HEAD(reset_controller_list); |
25 | 25 | ||
26 | static DEFINE_MUTEX(reset_lookup_mutex); | ||
27 | static LIST_HEAD(reset_lookup_list); | ||
28 | |||
26 | /** | 29 | /** |
27 | * struct reset_control - a reset control | 30 | * struct reset_control - a reset control |
28 | * @rcdev: a pointer to the reset controller device | 31 | * @rcdev: a pointer to the reset controller device |
@@ -148,6 +151,33 @@ int devm_reset_controller_register(struct device *dev, | |||
148 | } | 151 | } |
149 | EXPORT_SYMBOL_GPL(devm_reset_controller_register); | 152 | EXPORT_SYMBOL_GPL(devm_reset_controller_register); |
150 | 153 | ||
154 | /** | ||
155 | * reset_controller_add_lookup - register a set of lookup entries | ||
156 | * @lookup: array of reset lookup entries | ||
157 | * @num_entries: number of entries in the lookup array | ||
158 | */ | ||
159 | void reset_controller_add_lookup(struct reset_control_lookup *lookup, | ||
160 | unsigned int num_entries) | ||
161 | { | ||
162 | struct reset_control_lookup *entry; | ||
163 | unsigned int i; | ||
164 | |||
165 | mutex_lock(&reset_lookup_mutex); | ||
166 | for (i = 0; i < num_entries; i++) { | ||
167 | entry = &lookup[i]; | ||
168 | |||
169 | if (!entry->dev_id || !entry->provider) { | ||
170 | pr_warn("%s(): reset lookup entry badly specified, skipping\n", | ||
171 | __func__); | ||
172 | continue; | ||
173 | } | ||
174 | |||
175 | list_add_tail(&entry->list, &reset_lookup_list); | ||
176 | } | ||
177 | mutex_unlock(&reset_lookup_mutex); | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(reset_controller_add_lookup); | ||
180 | |||
151 | static inline struct reset_control_array * | 181 | static inline struct reset_control_array * |
152 | rstc_to_array(struct reset_control *rstc) { | 182 | rstc_to_array(struct reset_control *rstc) { |
153 | return container_of(rstc, struct reset_control_array, base); | 183 | return container_of(rstc, struct reset_control_array, base); |
@@ -493,6 +523,70 @@ struct reset_control *__of_reset_control_get(struct device_node *node, | |||
493 | } | 523 | } |
494 | EXPORT_SYMBOL_GPL(__of_reset_control_get); | 524 | EXPORT_SYMBOL_GPL(__of_reset_control_get); |
495 | 525 | ||
526 | static struct reset_controller_dev * | ||
527 | __reset_controller_by_name(const char *name) | ||
528 | { | ||
529 | struct reset_controller_dev *rcdev; | ||
530 | |||
531 | lockdep_assert_held(&reset_list_mutex); | ||
532 | |||
533 | list_for_each_entry(rcdev, &reset_controller_list, list) { | ||
534 | if (!rcdev->dev) | ||
535 | continue; | ||
536 | |||
537 | if (!strcmp(name, dev_name(rcdev->dev))) | ||
538 | return rcdev; | ||
539 | } | ||
540 | |||
541 | return NULL; | ||
542 | } | ||
543 | |||
544 | static struct reset_control * | ||
545 | __reset_control_get_from_lookup(struct device *dev, const char *con_id, | ||
546 | bool shared, bool optional) | ||
547 | { | ||
548 | const struct reset_control_lookup *lookup; | ||
549 | struct reset_controller_dev *rcdev; | ||
550 | const char *dev_id = dev_name(dev); | ||
551 | struct reset_control *rstc = NULL; | ||
552 | |||
553 | if (!dev) | ||
554 | return ERR_PTR(-EINVAL); | ||
555 | |||
556 | mutex_lock(&reset_lookup_mutex); | ||
557 | |||
558 | list_for_each_entry(lookup, &reset_lookup_list, list) { | ||
559 | if (strcmp(lookup->dev_id, dev_id)) | ||
560 | continue; | ||
561 | |||
562 | if ((!con_id && !lookup->con_id) || | ||
563 | ((con_id && lookup->con_id) && | ||
564 | !strcmp(con_id, lookup->con_id))) { | ||
565 | mutex_lock(&reset_list_mutex); | ||
566 | rcdev = __reset_controller_by_name(lookup->provider); | ||
567 | if (!rcdev) { | ||
568 | mutex_unlock(&reset_list_mutex); | ||
569 | mutex_unlock(&reset_lookup_mutex); | ||
570 | /* Reset provider may not be ready yet. */ | ||
571 | return ERR_PTR(-EPROBE_DEFER); | ||
572 | } | ||
573 | |||
574 | rstc = __reset_control_get_internal(rcdev, | ||
575 | lookup->index, | ||
576 | shared); | ||
577 | mutex_unlock(&reset_list_mutex); | ||
578 | break; | ||
579 | } | ||
580 | } | ||
581 | |||
582 | mutex_unlock(&reset_lookup_mutex); | ||
583 | |||
584 | if (!rstc) | ||
585 | return optional ? NULL : ERR_PTR(-ENOENT); | ||
586 | |||
587 | return rstc; | ||
588 | } | ||
589 | |||
496 | struct reset_control *__reset_control_get(struct device *dev, const char *id, | 590 | struct reset_control *__reset_control_get(struct device *dev, const char *id, |
497 | int index, bool shared, bool optional) | 591 | int index, bool shared, bool optional) |
498 | { | 592 | { |
@@ -500,7 +594,7 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, | |||
500 | return __of_reset_control_get(dev->of_node, id, index, shared, | 594 | return __of_reset_control_get(dev->of_node, id, index, shared, |
501 | optional); | 595 | optional); |
502 | 596 | ||
503 | return optional ? NULL : ERR_PTR(-EINVAL); | 597 | return __reset_control_get_from_lookup(dev, id, shared, optional); |
504 | } | 598 | } |
505 | EXPORT_SYMBOL_GPL(__reset_control_get); | 599 | EXPORT_SYMBOL_GPL(__reset_control_get); |
506 | 600 | ||
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index adb88f8cefbc..9326d671b6e6 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h | |||
@@ -27,12 +27,38 @@ struct device_node; | |||
27 | struct of_phandle_args; | 27 | struct of_phandle_args; |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * struct reset_control_lookup - represents a single lookup entry | ||
31 | * | ||
32 | * @list: internal list of all reset lookup entries | ||
33 | * @provider: name of the reset controller device controlling this reset line | ||
34 | * @index: ID of the reset controller in the reset controller device | ||
35 | * @dev_id: name of the device associated with this reset line | ||
36 | * @con_id name of the reset line (can be NULL) | ||
37 | */ | ||
38 | struct reset_control_lookup { | ||
39 | struct list_head list; | ||
40 | const char *provider; | ||
41 | unsigned int index; | ||
42 | const char *dev_id; | ||
43 | const char *con_id; | ||
44 | }; | ||
45 | |||
46 | #define RESET_LOOKUP(_provider, _index, _dev_id, _con_id) \ | ||
47 | { \ | ||
48 | .provider = _provider, \ | ||
49 | .index = _index, \ | ||
50 | .dev_id = _dev_id, \ | ||
51 | .con_id = _con_id, \ | ||
52 | } | ||
53 | |||
54 | /** | ||
30 | * struct reset_controller_dev - reset controller entity that might | 55 | * struct reset_controller_dev - reset controller entity that might |
31 | * provide multiple reset controls | 56 | * provide multiple reset controls |
32 | * @ops: a pointer to device specific struct reset_control_ops | 57 | * @ops: a pointer to device specific struct reset_control_ops |
33 | * @owner: kernel module of the reset controller driver | 58 | * @owner: kernel module of the reset controller driver |
34 | * @list: internal list of reset controller devices | 59 | * @list: internal list of reset controller devices |
35 | * @reset_control_head: head of internal list of requested reset controls | 60 | * @reset_control_head: head of internal list of requested reset controls |
61 | * @dev: corresponding driver model device struct | ||
36 | * @of_node: corresponding device tree node as phandle target | 62 | * @of_node: corresponding device tree node as phandle target |
37 | * @of_reset_n_cells: number of cells in reset line specifiers | 63 | * @of_reset_n_cells: number of cells in reset line specifiers |
38 | * @of_xlate: translation function to translate from specifier as found in the | 64 | * @of_xlate: translation function to translate from specifier as found in the |
@@ -44,6 +70,7 @@ struct reset_controller_dev { | |||
44 | struct module *owner; | 70 | struct module *owner; |
45 | struct list_head list; | 71 | struct list_head list; |
46 | struct list_head reset_control_head; | 72 | struct list_head reset_control_head; |
73 | struct device *dev; | ||
47 | struct device_node *of_node; | 74 | struct device_node *of_node; |
48 | int of_reset_n_cells; | 75 | int of_reset_n_cells; |
49 | int (*of_xlate)(struct reset_controller_dev *rcdev, | 76 | int (*of_xlate)(struct reset_controller_dev *rcdev, |
@@ -58,4 +85,7 @@ struct device; | |||
58 | int devm_reset_controller_register(struct device *dev, | 85 | int devm_reset_controller_register(struct device *dev, |
59 | struct reset_controller_dev *rcdev); | 86 | struct reset_controller_dev *rcdev); |
60 | 87 | ||
88 | void reset_controller_add_lookup(struct reset_control_lookup *lookup, | ||
89 | unsigned int num_entries); | ||
90 | |||
61 | #endif | 91 | #endif |