Linux Audio

Check our new training course

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");