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