diff options
author | Heikki Krogerus <heikki.krogerus@linux.intel.com> | 2014-11-19 10:28:18 -0500 |
---|---|---|
committer | Kishon Vijay Abraham I <kishon@ti.com> | 2014-11-21 09:18:50 -0500 |
commit | b7bc15b98e843926d01eb03b9c0e196d8ddbadeb (patch) | |
tree | 1ad10eb0f6e27ec06b17bbeed233b31d4cde66d3 | |
parent | d451057464a7ea2fe400e56c8a7e004c875f2a84 (diff) |
phy: improved lookup method
Separates registration of the phy and the lookup. The method
is copied from clkdev.c,
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r-- | Documentation/phy.txt | 60 | ||||
-rw-r--r-- | drivers/phy/phy-core.c | 84 | ||||
-rw-r--r-- | include/linux/phy/phy.h | 16 |
3 files changed, 115 insertions, 45 deletions
diff --git a/Documentation/phy.txt b/Documentation/phy.txt index c6594af94d25..371361c69a4b 100644 --- a/Documentation/phy.txt +++ b/Documentation/phy.txt | |||
@@ -54,18 +54,14 @@ The PHY driver should create the PHY in order for other peripheral controllers | |||
54 | to make use of it. The PHY framework provides 2 APIs to create the PHY. | 54 | to make use of it. The PHY framework provides 2 APIs to create the PHY. |
55 | 55 | ||
56 | struct phy *phy_create(struct device *dev, struct device_node *node, | 56 | struct phy *phy_create(struct device *dev, struct device_node *node, |
57 | const struct phy_ops *ops, | 57 | const struct phy_ops *ops); |
58 | struct phy_init_data *init_data); | ||
59 | struct phy *devm_phy_create(struct device *dev, struct device_node *node, | 58 | struct phy *devm_phy_create(struct device *dev, struct device_node *node, |
60 | const struct phy_ops *ops, | 59 | const struct phy_ops *ops); |
61 | struct phy_init_data *init_data); | ||
62 | 60 | ||
63 | The PHY drivers can use one of the above 2 APIs to create the PHY by passing | 61 | The PHY drivers can use one of the above 2 APIs to create the PHY by passing |
64 | the device pointer, phy ops and init_data. | 62 | the device pointer and phy ops. |
65 | phy_ops is a set of function pointers for performing PHY operations such as | 63 | phy_ops is a set of function pointers for performing PHY operations such as |
66 | init, exit, power_on and power_off. *init_data* is mandatory to get a reference | 64 | init, exit, power_on and power_off. |
67 | to the PHY in the case of non-dt boot. See section *Board File Initialization* | ||
68 | on how init_data should be used. | ||
69 | 65 | ||
70 | Inorder to dereference the private data (in phy_ops), the phy provider driver | 66 | Inorder to dereference the private data (in phy_ops), the phy provider driver |
71 | can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in | 67 | can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in |
@@ -137,42 +133,18 @@ There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync, | |||
137 | phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and | 133 | phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and |
138 | phy_pm_runtime_forbid for performing PM operations. | 134 | phy_pm_runtime_forbid for performing PM operations. |
139 | 135 | ||
140 | 8. Board File Initialization | 136 | 8. PHY Mappings |
141 | 137 | ||
142 | Certain board file initialization is necessary in order to get a reference | 138 | In order to get reference to a PHY without help from DeviceTree, the framework |
143 | to the PHY in the case of non-dt boot. | 139 | offers lookups which can be compared to clkdev that allow clk structures to be |
144 | Say we have a single device that implements 3 PHYs that of USB, SATA and PCIe, | 140 | bound to devices. A lookup can be made be made during runtime when a handle to |
145 | then in the board file the following initialization should be done. | 141 | the struct phy already exists. |
146 | 142 | ||
147 | struct phy_consumer consumers[] = { | 143 | The framework offers the following API for registering and unregistering the |
148 | PHY_CONSUMER("dwc3.0", "usb"), | 144 | lookups. |
149 | PHY_CONSUMER("pcie.0", "pcie"), | 145 | |
150 | PHY_CONSUMER("sata.0", "sata"), | 146 | int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id); |
151 | }; | 147 | void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id); |
152 | PHY_CONSUMER takes 2 parameters, first is the device name of the controller | ||
153 | (PHY consumer) and second is the port name. | ||
154 | |||
155 | struct phy_init_data init_data = { | ||
156 | .consumers = consumers, | ||
157 | .num_consumers = ARRAY_SIZE(consumers), | ||
158 | }; | ||
159 | |||
160 | static const struct platform_device pipe3_phy_dev = { | ||
161 | .name = "pipe3-phy", | ||
162 | .id = -1, | ||
163 | .dev = { | ||
164 | .platform_data = { | ||
165 | .init_data = &init_data, | ||
166 | }, | ||
167 | }, | ||
168 | }; | ||
169 | |||
170 | then, while doing phy_create, the PHY driver should pass this init_data | ||
171 | phy_create(dev, ops, pdata->init_data); | ||
172 | |||
173 | and the controller driver (phy consumer) should pass the port name along with | ||
174 | the device to get a reference to the PHY | ||
175 | phy_get(dev, "pcie"); | ||
176 | 148 | ||
177 | 9. DeviceTree Binding | 149 | 9. DeviceTree Binding |
178 | 150 | ||
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 1606ce9805d0..bc830773fe05 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | static struct class *phy_class; | 26 | static struct class *phy_class; |
27 | static DEFINE_MUTEX(phy_provider_mutex); | 27 | static DEFINE_MUTEX(phy_provider_mutex); |
28 | static LIST_HEAD(phy_provider_list); | 28 | static LIST_HEAD(phy_provider_list); |
29 | static LIST_HEAD(phys); | ||
29 | static DEFINE_IDA(phy_ida); | 30 | static DEFINE_IDA(phy_ida); |
30 | 31 | ||
31 | static void devm_phy_release(struct device *dev, void *res) | 32 | static void devm_phy_release(struct device *dev, void *res) |
@@ -84,6 +85,87 @@ static struct phy *phy_lookup(struct device *device, const char *port) | |||
84 | return ERR_PTR(-ENODEV); | 85 | return ERR_PTR(-ENODEV); |
85 | } | 86 | } |
86 | 87 | ||
88 | /** | ||
89 | * phy_create_lookup() - allocate and register PHY/device association | ||
90 | * @phy: the phy of the association | ||
91 | * @con_id: connection ID string on device | ||
92 | * @dev_id: the device of the association | ||
93 | * | ||
94 | * Creates and registers phy_lookup entry. | ||
95 | */ | ||
96 | int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id) | ||
97 | { | ||
98 | struct phy_lookup *pl; | ||
99 | |||
100 | if (!phy || !dev_id || !con_id) | ||
101 | return -EINVAL; | ||
102 | |||
103 | pl = kzalloc(sizeof(*pl), GFP_KERNEL); | ||
104 | if (!pl) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | pl->dev_id = dev_id; | ||
108 | pl->con_id = con_id; | ||
109 | pl->phy = phy; | ||
110 | |||
111 | mutex_lock(&phy_provider_mutex); | ||
112 | list_add_tail(&pl->node, &phys); | ||
113 | mutex_unlock(&phy_provider_mutex); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(phy_create_lookup); | ||
118 | |||
119 | /** | ||
120 | * phy_remove_lookup() - find and remove PHY/device association | ||
121 | * @phy: the phy of the association | ||
122 | * @con_id: connection ID string on device | ||
123 | * @dev_id: the device of the association | ||
124 | * | ||
125 | * Finds and unregisters phy_lookup entry that was created with | ||
126 | * phy_create_lookup(). | ||
127 | */ | ||
128 | void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id) | ||
129 | { | ||
130 | struct phy_lookup *pl; | ||
131 | |||
132 | if (!phy || !dev_id || !con_id) | ||
133 | return; | ||
134 | |||
135 | mutex_lock(&phy_provider_mutex); | ||
136 | list_for_each_entry(pl, &phys, node) | ||
137 | if (pl->phy == phy && !strcmp(pl->dev_id, dev_id) && | ||
138 | !strcmp(pl->con_id, con_id)) { | ||
139 | list_del(&pl->node); | ||
140 | kfree(pl); | ||
141 | break; | ||
142 | } | ||
143 | mutex_unlock(&phy_provider_mutex); | ||
144 | } | ||
145 | EXPORT_SYMBOL_GPL(phy_remove_lookup); | ||
146 | |||
147 | static struct phy *phy_find(struct device *dev, const char *con_id) | ||
148 | { | ||
149 | const char *dev_id = dev_name(dev); | ||
150 | struct phy_lookup *p, *pl = NULL; | ||
151 | struct phy *phy; | ||
152 | |||
153 | mutex_lock(&phy_provider_mutex); | ||
154 | list_for_each_entry(p, &phys, node) | ||
155 | if (!strcmp(p->dev_id, dev_id) && !strcmp(p->con_id, con_id)) { | ||
156 | pl = p; | ||
157 | break; | ||
158 | } | ||
159 | mutex_unlock(&phy_provider_mutex); | ||
160 | |||
161 | phy = pl ? pl->phy : ERR_PTR(-ENODEV); | ||
162 | |||
163 | /* fall-back to the old lookup method for now */ | ||
164 | if (IS_ERR(phy)) | ||
165 | phy = phy_lookup(dev, con_id); | ||
166 | return phy; | ||
167 | } | ||
168 | |||
87 | static struct phy_provider *of_phy_provider_lookup(struct device_node *node) | 169 | static struct phy_provider *of_phy_provider_lookup(struct device_node *node) |
88 | { | 170 | { |
89 | struct phy_provider *phy_provider; | 171 | struct phy_provider *phy_provider; |
@@ -455,7 +537,7 @@ struct phy *phy_get(struct device *dev, const char *string) | |||
455 | string); | 537 | string); |
456 | phy = _of_phy_get(dev->of_node, index); | 538 | phy = _of_phy_get(dev->of_node, index); |
457 | } else { | 539 | } else { |
458 | phy = phy_lookup(dev, string); | 540 | phy = phy_find(dev, string); |
459 | } | 541 | } |
460 | if (IS_ERR(phy)) | 542 | if (IS_ERR(phy)) |
461 | return phy; | 543 | return phy; |
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 9fda68324298..849284e5873f 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
@@ -110,6 +110,13 @@ struct phy_init_data { | |||
110 | .port = _port, \ | 110 | .port = _port, \ |
111 | } | 111 | } |
112 | 112 | ||
113 | struct phy_lookup { | ||
114 | struct list_head node; | ||
115 | const char *dev_id; | ||
116 | const char *con_id; | ||
117 | struct phy *phy; | ||
118 | }; | ||
119 | |||
113 | #define to_phy(a) (container_of((a), struct phy, dev)) | 120 | #define to_phy(a) (container_of((a), struct phy, dev)) |
114 | 121 | ||
115 | #define of_phy_provider_register(dev, xlate) \ | 122 | #define of_phy_provider_register(dev, xlate) \ |
@@ -174,6 +181,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev, | |||
174 | void of_phy_provider_unregister(struct phy_provider *phy_provider); | 181 | void of_phy_provider_unregister(struct phy_provider *phy_provider); |
175 | void devm_of_phy_provider_unregister(struct device *dev, | 182 | void devm_of_phy_provider_unregister(struct device *dev, |
176 | struct phy_provider *phy_provider); | 183 | struct phy_provider *phy_provider); |
184 | int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id); | ||
185 | void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id); | ||
177 | #else | 186 | #else |
178 | static inline int phy_pm_runtime_get(struct phy *phy) | 187 | static inline int phy_pm_runtime_get(struct phy *phy) |
179 | { | 188 | { |
@@ -345,6 +354,13 @@ static inline void devm_of_phy_provider_unregister(struct device *dev, | |||
345 | struct phy_provider *phy_provider) | 354 | struct phy_provider *phy_provider) |
346 | { | 355 | { |
347 | } | 356 | } |
357 | static inline int | ||
358 | phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id) | ||
359 | { | ||
360 | return 0; | ||
361 | } | ||
362 | static inline void phy_remove_lookup(struct phy *phy, const char *con_id, | ||
363 | const char *dev_id) { } | ||
348 | #endif | 364 | #endif |
349 | 365 | ||
350 | #endif /* __DRIVERS_PHY_H */ | 366 | #endif /* __DRIVERS_PHY_H */ |