Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Greybus Bridged-Phy Bus driver
4 *
5 * Copyright 2014 Google Inc.
6 * Copyright 2014 Linaro Ltd.
7 */
8
9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11#include <linux/types.h>
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/slab.h>
15#include <linux/device.h>
16
17#include "greybus.h"
18#include "gbphy.h"
19
20#define GB_GBPHY_AUTOSUSPEND_MS 3000
21
22struct gbphy_host {
23 struct gb_bundle *bundle;
24 struct list_head devices;
25};
26
27static DEFINE_IDA(gbphy_id);
28
29static ssize_t protocol_id_show(struct device *dev,
30 struct device_attribute *attr, char *buf)
31{
32 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
33
34 return sprintf(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id);
35}
36static DEVICE_ATTR_RO(protocol_id);
37
38static struct attribute *gbphy_dev_attrs[] = {
39 &dev_attr_protocol_id.attr,
40 NULL,
41};
42
43ATTRIBUTE_GROUPS(gbphy_dev);
44
45static void gbphy_dev_release(struct device *dev)
46{
47 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
48
49 ida_simple_remove(&gbphy_id, gbphy_dev->id);
50 kfree(gbphy_dev);
51}
52
53#ifdef CONFIG_PM
54static int gb_gbphy_idle(struct device *dev)
55{
56 pm_runtime_mark_last_busy(dev);
57 pm_request_autosuspend(dev);
58 return 0;
59}
60#endif
61
62static const struct dev_pm_ops gb_gbphy_pm_ops = {
63 SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend,
64 pm_generic_runtime_resume,
65 gb_gbphy_idle)
66};
67
68static const struct device_type greybus_gbphy_dev_type = {
69 .name = "gbphy_device",
70 .release = gbphy_dev_release,
71 .pm = &gb_gbphy_pm_ops,
72};
73
74static int gbphy_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
75{
76 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
77 struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc;
78 struct gb_bundle *bundle = gbphy_dev->bundle;
79 struct gb_interface *intf = bundle->intf;
80 struct gb_module *module = intf->module;
81 struct gb_host_device *hd = intf->hd;
82
83 if (add_uevent_var(env, "BUS=%u", hd->bus_id))
84 return -ENOMEM;
85 if (add_uevent_var(env, "MODULE=%u", module->module_id))
86 return -ENOMEM;
87 if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id))
88 return -ENOMEM;
89 if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x",
90 intf->vendor_id, intf->product_id))
91 return -ENOMEM;
92 if (add_uevent_var(env, "BUNDLE=%u", gbphy_dev->bundle->id))
93 return -ENOMEM;
94 if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class))
95 return -ENOMEM;
96 if (add_uevent_var(env, "GBPHY=%u", gbphy_dev->id))
97 return -ENOMEM;
98 if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id))
99 return -ENOMEM;
100
101 return 0;
102}
103
104static const struct gbphy_device_id *
105gbphy_dev_match_id(struct gbphy_device *gbphy_dev,
106 struct gbphy_driver *gbphy_drv)
107{
108 const struct gbphy_device_id *id = gbphy_drv->id_table;
109
110 if (!id)
111 return NULL;
112
113 for (; id->protocol_id; id++)
114 if (id->protocol_id == gbphy_dev->cport_desc->protocol_id)
115 return id;
116
117 return NULL;
118}
119
120static int gbphy_dev_match(struct device *dev, struct device_driver *drv)
121{
122 struct gbphy_driver *gbphy_drv = to_gbphy_driver(drv);
123 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
124 const struct gbphy_device_id *id;
125
126 id = gbphy_dev_match_id(gbphy_dev, gbphy_drv);
127 if (id)
128 return 1;
129
130 return 0;
131}
132
133static int gbphy_dev_probe(struct device *dev)
134{
135 struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver);
136 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
137 const struct gbphy_device_id *id;
138 int ret;
139
140 id = gbphy_dev_match_id(gbphy_dev, gbphy_drv);
141 if (!id)
142 return -ENODEV;
143
144 /* for old kernels we need get_sync to resume parent devices */
145 ret = gb_pm_runtime_get_sync(gbphy_dev->bundle);
146 if (ret < 0)
147 return ret;
148
149 pm_runtime_set_autosuspend_delay(dev, GB_GBPHY_AUTOSUSPEND_MS);
150 pm_runtime_use_autosuspend(dev);
151 pm_runtime_get_noresume(dev);
152 pm_runtime_set_active(dev);
153 pm_runtime_enable(dev);
154
155 /*
156 * Drivers should call put on the gbphy dev before returning
157 * from probe if they support runtime pm.
158 */
159 ret = gbphy_drv->probe(gbphy_dev, id);
160 if (ret) {
161 pm_runtime_disable(dev);
162 pm_runtime_set_suspended(dev);
163 pm_runtime_put_noidle(dev);
164 pm_runtime_dont_use_autosuspend(dev);
165 }
166
167 gb_pm_runtime_put_autosuspend(gbphy_dev->bundle);
168
169 return ret;
170}
171
172static int gbphy_dev_remove(struct device *dev)
173{
174 struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver);
175 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
176
177 gbphy_drv->remove(gbphy_dev);
178
179 pm_runtime_disable(dev);
180 pm_runtime_set_suspended(dev);
181 pm_runtime_put_noidle(dev);
182 pm_runtime_dont_use_autosuspend(dev);
183
184 return 0;
185}
186
187static struct bus_type gbphy_bus_type = {
188 .name = "gbphy",
189 .match = gbphy_dev_match,
190 .probe = gbphy_dev_probe,
191 .remove = gbphy_dev_remove,
192 .uevent = gbphy_dev_uevent,
193};
194
195int gb_gbphy_register_driver(struct gbphy_driver *driver,
196 struct module *owner, const char *mod_name)
197{
198 int retval;
199
200 if (greybus_disabled())
201 return -ENODEV;
202
203 driver->driver.bus = &gbphy_bus_type;
204 driver->driver.name = driver->name;
205 driver->driver.owner = owner;
206 driver->driver.mod_name = mod_name;
207
208 retval = driver_register(&driver->driver);
209 if (retval)
210 return retval;
211
212 pr_info("registered new driver %s\n", driver->name);
213 return 0;
214}
215EXPORT_SYMBOL_GPL(gb_gbphy_register_driver);
216
217void gb_gbphy_deregister_driver(struct gbphy_driver *driver)
218{
219 driver_unregister(&driver->driver);
220}
221EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver);
222
223static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle,
224 struct greybus_descriptor_cport *cport_desc)
225{
226 struct gbphy_device *gbphy_dev;
227 int retval;
228 int id;
229
230 id = ida_simple_get(&gbphy_id, 1, 0, GFP_KERNEL);
231 if (id < 0)
232 return ERR_PTR(id);
233
234 gbphy_dev = kzalloc(sizeof(*gbphy_dev), GFP_KERNEL);
235 if (!gbphy_dev) {
236 ida_simple_remove(&gbphy_id, id);
237 return ERR_PTR(-ENOMEM);
238 }
239
240 gbphy_dev->id = id;
241 gbphy_dev->bundle = bundle;
242 gbphy_dev->cport_desc = cport_desc;
243 gbphy_dev->dev.parent = &bundle->dev;
244 gbphy_dev->dev.bus = &gbphy_bus_type;
245 gbphy_dev->dev.type = &greybus_gbphy_dev_type;
246 gbphy_dev->dev.groups = gbphy_dev_groups;
247 gbphy_dev->dev.dma_mask = bundle->dev.dma_mask;
248 dev_set_name(&gbphy_dev->dev, "gbphy%d", id);
249
250 retval = device_register(&gbphy_dev->dev);
251 if (retval) {
252 put_device(&gbphy_dev->dev);
253 return ERR_PTR(retval);
254 }
255
256 return gbphy_dev;
257}
258
259static void gb_gbphy_disconnect(struct gb_bundle *bundle)
260{
261 struct gbphy_host *gbphy_host = greybus_get_drvdata(bundle);
262 struct gbphy_device *gbphy_dev, *temp;
263 int ret;
264
265 ret = gb_pm_runtime_get_sync(bundle);
266 if (ret < 0)
267 gb_pm_runtime_get_noresume(bundle);
268
269 list_for_each_entry_safe(gbphy_dev, temp, &gbphy_host->devices, list) {
270 list_del(&gbphy_dev->list);
271 device_unregister(&gbphy_dev->dev);
272 }
273
274 kfree(gbphy_host);
275}
276
277static int gb_gbphy_probe(struct gb_bundle *bundle,
278 const struct greybus_bundle_id *id)
279{
280 struct gbphy_host *gbphy_host;
281 struct gbphy_device *gbphy_dev;
282 int i;
283
284 if (bundle->num_cports == 0)
285 return -ENODEV;
286
287 gbphy_host = kzalloc(sizeof(*gbphy_host), GFP_KERNEL);
288 if (!gbphy_host)
289 return -ENOMEM;
290
291 gbphy_host->bundle = bundle;
292 INIT_LIST_HEAD(&gbphy_host->devices);
293 greybus_set_drvdata(bundle, gbphy_host);
294
295 /*
296 * Create a bunch of children devices, one per cport, and bind the
297 * bridged phy drivers to them.
298 */
299 for (i = 0; i < bundle->num_cports; ++i) {
300 gbphy_dev = gb_gbphy_create_dev(bundle, &bundle->cport_desc[i]);
301 if (IS_ERR(gbphy_dev)) {
302 gb_gbphy_disconnect(bundle);
303 return PTR_ERR(gbphy_dev);
304 }
305 list_add(&gbphy_dev->list, &gbphy_host->devices);
306 }
307
308 gb_pm_runtime_put_autosuspend(bundle);
309
310 return 0;
311}
312
313static const struct greybus_bundle_id gb_gbphy_id_table[] = {
314 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) },
315 { },
316};
317MODULE_DEVICE_TABLE(greybus, gb_gbphy_id_table);
318
319static struct greybus_driver gb_gbphy_driver = {
320 .name = "gbphy",
321 .probe = gb_gbphy_probe,
322 .disconnect = gb_gbphy_disconnect,
323 .id_table = gb_gbphy_id_table,
324};
325
326static int __init gbphy_init(void)
327{
328 int retval;
329
330 retval = bus_register(&gbphy_bus_type);
331 if (retval) {
332 pr_err("gbphy bus register failed (%d)\n", retval);
333 return retval;
334 }
335
336 retval = greybus_register(&gb_gbphy_driver);
337 if (retval) {
338 pr_err("error registering greybus driver\n");
339 goto error_gbphy;
340 }
341
342 return 0;
343
344error_gbphy:
345 bus_unregister(&gbphy_bus_type);
346 ida_destroy(&gbphy_id);
347 return retval;
348}
349module_init(gbphy_init);
350
351static void __exit gbphy_exit(void)
352{
353 greybus_deregister(&gb_gbphy_driver);
354 bus_unregister(&gbphy_bus_type);
355 ida_destroy(&gbphy_id);
356}
357module_exit(gbphy_exit);
358
359MODULE_LICENSE("GPL v2");