aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2013-09-27 02:23:25 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-09-27 20:35:41 -0400
commitff764963479a1b18721ab96e531404c50fefe8b1 (patch)
treee696248868cbb6ab2ac2159058c72631b620b136 /drivers/phy
parent6741448eb01a1844b78c83fa8faf0c95524fc09b (diff)
drivers: phy: add generic PHY framework
The PHY framework provides a set of APIs for the PHY drivers to create/destroy a PHY and APIs for the PHY users to obtain a reference to the PHY with or without using phandle. For dt-boot, the PHY drivers should also register *PHY provider* with the framework. PHY drivers should create the PHY by passing id and ops like init, exit, power_on and power_off. This framework is also pm runtime enabled. The documentation for the generic PHY framework is added in Documentation/phy.txt and the documentation for dt binding can be found at Documentation/devicetree/bindings/phy/phy-bindings.txt Cc: Tomasz Figa <t.figa@samsung.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Acked-by: Felipe Balbi <balbi@ti.com> Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/Kconfig18
-rw-r--r--drivers/phy/Makefile5
-rw-r--r--drivers/phy/phy-core.c698
3 files changed, 721 insertions, 0 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
new file mode 100644
index 000000000000..349bef2e6e4e
--- /dev/null
+++ b/drivers/phy/Kconfig
@@ -0,0 +1,18 @@
1#
2# PHY
3#
4
5menu "PHY Subsystem"
6
7config GENERIC_PHY
8 tristate "PHY Core"
9 help
10 Generic PHY support.
11
12 This framework is designed to provide a generic interface for PHY
13 devices present in the kernel. This layer will have the generic
14 API by which phy drivers can create PHY using the phy framework and
15 phy users can obtain reference to the PHY. All the users of this
16 framework should select this config.
17
18endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
new file mode 100644
index 000000000000..9e9560fbb14d
--- /dev/null
+++ b/drivers/phy/Makefile
@@ -0,0 +1,5 @@
1#
2# Makefile for the phy drivers.
3#
4
5obj-$(CONFIG_GENERIC_PHY) += phy-core.o
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
new file mode 100644
index 000000000000..03cf8fb81554
--- /dev/null
+++ b/drivers/phy/phy-core.c
@@ -0,0 +1,698 @@
1/*
2 * phy-core.c -- Generic Phy framework.
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/export.h>
16#include <linux/module.h>
17#include <linux/err.h>
18#include <linux/device.h>
19#include <linux/slab.h>
20#include <linux/of.h>
21#include <linux/phy/phy.h>
22#include <linux/idr.h>
23#include <linux/pm_runtime.h>
24
25static struct class *phy_class;
26static DEFINE_MUTEX(phy_provider_mutex);
27static LIST_HEAD(phy_provider_list);
28static DEFINE_IDA(phy_ida);
29
30static void devm_phy_release(struct device *dev, void *res)
31{
32 struct phy *phy = *(struct phy **)res;
33
34 phy_put(phy);
35}
36
37static void devm_phy_provider_release(struct device *dev, void *res)
38{
39 struct phy_provider *phy_provider = *(struct phy_provider **)res;
40
41 of_phy_provider_unregister(phy_provider);
42}
43
44static void devm_phy_consume(struct device *dev, void *res)
45{
46 struct phy *phy = *(struct phy **)res;
47
48 phy_destroy(phy);
49}
50
51static int devm_phy_match(struct device *dev, void *res, void *match_data)
52{
53 return res == match_data;
54}
55
56static struct phy *phy_lookup(struct device *device, const char *port)
57{
58 unsigned int count;
59 struct phy *phy;
60 struct device *dev;
61 struct phy_consumer *consumers;
62 struct class_dev_iter iter;
63
64 class_dev_iter_init(&iter, phy_class, NULL, NULL);
65 while ((dev = class_dev_iter_next(&iter))) {
66 phy = to_phy(dev);
67 count = phy->init_data->num_consumers;
68 consumers = phy->init_data->consumers;
69 while (count--) {
70 if (!strcmp(consumers->dev_name, dev_name(device)) &&
71 !strcmp(consumers->port, port)) {
72 class_dev_iter_exit(&iter);
73 return phy;
74 }
75 consumers++;
76 }
77 }
78
79 class_dev_iter_exit(&iter);
80 return ERR_PTR(-ENODEV);
81}
82
83static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
84{
85 struct phy_provider *phy_provider;
86
87 list_for_each_entry(phy_provider, &phy_provider_list, list) {
88 if (phy_provider->dev->of_node == node)
89 return phy_provider;
90 }
91
92 return ERR_PTR(-EPROBE_DEFER);
93}
94
95int phy_pm_runtime_get(struct phy *phy)
96{
97 if (!pm_runtime_enabled(&phy->dev))
98 return -ENOTSUPP;
99
100 return pm_runtime_get(&phy->dev);
101}
102EXPORT_SYMBOL_GPL(phy_pm_runtime_get);
103
104int phy_pm_runtime_get_sync(struct phy *phy)
105{
106 if (!pm_runtime_enabled(&phy->dev))
107 return -ENOTSUPP;
108
109 return pm_runtime_get_sync(&phy->dev);
110}
111EXPORT_SYMBOL_GPL(phy_pm_runtime_get_sync);
112
113int phy_pm_runtime_put(struct phy *phy)
114{
115 if (!pm_runtime_enabled(&phy->dev))
116 return -ENOTSUPP;
117
118 return pm_runtime_put(&phy->dev);
119}
120EXPORT_SYMBOL_GPL(phy_pm_runtime_put);
121
122int phy_pm_runtime_put_sync(struct phy *phy)
123{
124 if (!pm_runtime_enabled(&phy->dev))
125 return -ENOTSUPP;
126
127 return pm_runtime_put_sync(&phy->dev);
128}
129EXPORT_SYMBOL_GPL(phy_pm_runtime_put_sync);
130
131void phy_pm_runtime_allow(struct phy *phy)
132{
133 if (!pm_runtime_enabled(&phy->dev))
134 return;
135
136 pm_runtime_allow(&phy->dev);
137}
138EXPORT_SYMBOL_GPL(phy_pm_runtime_allow);
139
140void phy_pm_runtime_forbid(struct phy *phy)
141{
142 if (!pm_runtime_enabled(&phy->dev))
143 return;
144
145 pm_runtime_forbid(&phy->dev);
146}
147EXPORT_SYMBOL_GPL(phy_pm_runtime_forbid);
148
149int phy_init(struct phy *phy)
150{
151 int ret;
152
153 ret = phy_pm_runtime_get_sync(phy);
154 if (ret < 0 && ret != -ENOTSUPP)
155 return ret;
156
157 mutex_lock(&phy->mutex);
158 if (phy->init_count++ == 0 && phy->ops->init) {
159 ret = phy->ops->init(phy);
160 if (ret < 0) {
161 dev_err(&phy->dev, "phy init failed --> %d\n", ret);
162 goto out;
163 }
164 }
165
166out:
167 mutex_unlock(&phy->mutex);
168 phy_pm_runtime_put(phy);
169 return ret;
170}
171EXPORT_SYMBOL_GPL(phy_init);
172
173int phy_exit(struct phy *phy)
174{
175 int ret;
176
177 ret = phy_pm_runtime_get_sync(phy);
178 if (ret < 0 && ret != -ENOTSUPP)
179 return ret;
180
181 mutex_lock(&phy->mutex);
182 if (--phy->init_count == 0 && phy->ops->exit) {
183 ret = phy->ops->exit(phy);
184 if (ret < 0) {
185 dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
186 goto out;
187 }
188 }
189
190out:
191 mutex_unlock(&phy->mutex);
192 phy_pm_runtime_put(phy);
193 return ret;
194}
195EXPORT_SYMBOL_GPL(phy_exit);
196
197int phy_power_on(struct phy *phy)
198{
199 int ret = -ENOTSUPP;
200
201 ret = phy_pm_runtime_get_sync(phy);
202 if (ret < 0 && ret != -ENOTSUPP)
203 return ret;
204
205 mutex_lock(&phy->mutex);
206 if (phy->power_count++ == 0 && phy->ops->power_on) {
207 ret = phy->ops->power_on(phy);
208 if (ret < 0) {
209 dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
210 goto out;
211 }
212 }
213
214out:
215 mutex_unlock(&phy->mutex);
216
217 return ret;
218}
219EXPORT_SYMBOL_GPL(phy_power_on);
220
221int phy_power_off(struct phy *phy)
222{
223 int ret = -ENOTSUPP;
224
225 mutex_lock(&phy->mutex);
226 if (--phy->power_count == 0 && phy->ops->power_off) {
227 ret = phy->ops->power_off(phy);
228 if (ret < 0) {
229 dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
230 goto out;
231 }
232 }
233
234out:
235 mutex_unlock(&phy->mutex);
236 phy_pm_runtime_put(phy);
237
238 return ret;
239}
240EXPORT_SYMBOL_GPL(phy_power_off);
241
242/**
243 * of_phy_get() - lookup and obtain a reference to a phy by phandle
244 * @dev: device that requests this phy
245 * @index: the index of the phy
246 *
247 * Returns the phy associated with the given phandle value,
248 * after getting a refcount to it or -ENODEV if there is no such phy or
249 * -EPROBE_DEFER if there is a phandle to the phy, but the device is
250 * not yet loaded. This function uses of_xlate call back function provided
251 * while registering the phy_provider to find the phy instance.
252 */
253static struct phy *of_phy_get(struct device *dev, int index)
254{
255 int ret;
256 struct phy_provider *phy_provider;
257 struct phy *phy = NULL;
258 struct of_phandle_args args;
259
260 ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells",
261 index, &args);
262 if (ret) {
263 dev_dbg(dev, "failed to get phy in %s node\n",
264 dev->of_node->full_name);
265 return ERR_PTR(-ENODEV);
266 }
267
268 mutex_lock(&phy_provider_mutex);
269 phy_provider = of_phy_provider_lookup(args.np);
270 if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
271 phy = ERR_PTR(-EPROBE_DEFER);
272 goto err0;
273 }
274
275 phy = phy_provider->of_xlate(phy_provider->dev, &args);
276 module_put(phy_provider->owner);
277
278err0:
279 mutex_unlock(&phy_provider_mutex);
280 of_node_put(args.np);
281
282 return phy;
283}
284
285/**
286 * phy_put() - release the PHY
287 * @phy: the phy returned by phy_get()
288 *
289 * Releases a refcount the caller received from phy_get().
290 */
291void phy_put(struct phy *phy)
292{
293 if (IS_ERR(phy))
294 return;
295
296 module_put(phy->ops->owner);
297 put_device(&phy->dev);
298}
299EXPORT_SYMBOL_GPL(phy_put);
300
301/**
302 * devm_phy_put() - release the PHY
303 * @dev: device that wants to release this phy
304 * @phy: the phy returned by devm_phy_get()
305 *
306 * destroys the devres associated with this phy and invokes phy_put
307 * to release the phy.
308 */
309void devm_phy_put(struct device *dev, struct phy *phy)
310{
311 int r;
312
313 r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
314 dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
315}
316EXPORT_SYMBOL_GPL(devm_phy_put);
317
318/**
319 * of_phy_simple_xlate() - returns the phy instance from phy provider
320 * @dev: the PHY provider device
321 * @args: of_phandle_args (not used here)
322 *
323 * Intended to be used by phy provider for the common case where #phy-cells is
324 * 0. For other cases where #phy-cells is greater than '0', the phy provider
325 * should provide a custom of_xlate function that reads the *args* and returns
326 * the appropriate phy.
327 */
328struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
329 *args)
330{
331 struct phy *phy;
332 struct class_dev_iter iter;
333 struct device_node *node = dev->of_node;
334
335 class_dev_iter_init(&iter, phy_class, NULL, NULL);
336 while ((dev = class_dev_iter_next(&iter))) {
337 phy = to_phy(dev);
338 if (node != phy->dev.of_node)
339 continue;
340
341 class_dev_iter_exit(&iter);
342 return phy;
343 }
344
345 class_dev_iter_exit(&iter);
346 return ERR_PTR(-ENODEV);
347}
348EXPORT_SYMBOL_GPL(of_phy_simple_xlate);
349
350/**
351 * phy_get() - lookup and obtain a reference to a phy.
352 * @dev: device that requests this phy
353 * @string: the phy name as given in the dt data or the name of the controller
354 * port for non-dt case
355 *
356 * Returns the phy driver, after getting a refcount to it; or
357 * -ENODEV if there is no such phy. The caller is responsible for
358 * calling phy_put() to release that count.
359 */
360struct phy *phy_get(struct device *dev, const char *string)
361{
362 int index = 0;
363 struct phy *phy = NULL;
364
365 if (string == NULL) {
366 dev_WARN(dev, "missing string\n");
367 return ERR_PTR(-EINVAL);
368 }
369
370 if (dev->of_node) {
371 index = of_property_match_string(dev->of_node, "phy-names",
372 string);
373 phy = of_phy_get(dev, index);
374 if (IS_ERR(phy)) {
375 dev_err(dev, "unable to find phy\n");
376 return phy;
377 }
378 } else {
379 phy = phy_lookup(dev, string);
380 if (IS_ERR(phy)) {
381 dev_err(dev, "unable to find phy\n");
382 return phy;
383 }
384 }
385
386 if (!try_module_get(phy->ops->owner))
387 return ERR_PTR(-EPROBE_DEFER);
388
389 get_device(&phy->dev);
390
391 return phy;
392}
393EXPORT_SYMBOL_GPL(phy_get);
394
395/**
396 * devm_phy_get() - lookup and obtain a reference to a phy.
397 * @dev: device that requests this phy
398 * @string: the phy name as given in the dt data or phy device name
399 * for non-dt case
400 *
401 * Gets the phy using phy_get(), and associates a device with it using
402 * devres. On driver detach, release function is invoked on the devres data,
403 * then, devres data is freed.
404 */
405struct phy *devm_phy_get(struct device *dev, const char *string)
406{
407 struct phy **ptr, *phy;
408
409 ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
410 if (!ptr)
411 return ERR_PTR(-ENOMEM);
412
413 phy = phy_get(dev, string);
414 if (!IS_ERR(phy)) {
415 *ptr = phy;
416 devres_add(dev, ptr);
417 } else {
418 devres_free(ptr);
419 }
420
421 return phy;
422}
423EXPORT_SYMBOL_GPL(devm_phy_get);
424
425/**
426 * phy_create() - create a new phy
427 * @dev: device that is creating the new phy
428 * @ops: function pointers for performing phy operations
429 * @init_data: contains the list of PHY consumers or NULL
430 *
431 * Called to create a phy using phy framework.
432 */
433struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
434 struct phy_init_data *init_data)
435{
436 int ret;
437 int id;
438 struct phy *phy;
439
440 if (!dev) {
441 dev_WARN(dev, "no device provided for PHY\n");
442 ret = -EINVAL;
443 goto err0;
444 }
445
446 phy = kzalloc(sizeof(*phy), GFP_KERNEL);
447 if (!phy) {
448 ret = -ENOMEM;
449 goto err0;
450 }
451
452 id = ida_simple_get(&phy_ida, 0, 0, GFP_KERNEL);
453 if (id < 0) {
454 dev_err(dev, "unable to get id\n");
455 ret = id;
456 goto err0;
457 }
458
459 device_initialize(&phy->dev);
460 mutex_init(&phy->mutex);
461
462 phy->dev.class = phy_class;
463 phy->dev.parent = dev;
464 phy->dev.of_node = dev->of_node;
465 phy->id = id;
466 phy->ops = ops;
467 phy->init_data = init_data;
468
469 ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
470 if (ret)
471 goto err1;
472
473 ret = device_add(&phy->dev);
474 if (ret)
475 goto err1;
476
477 if (pm_runtime_enabled(dev)) {
478 pm_runtime_enable(&phy->dev);
479 pm_runtime_no_callbacks(&phy->dev);
480 }
481
482 return phy;
483
484err1:
485 ida_remove(&phy_ida, phy->id);
486 put_device(&phy->dev);
487 kfree(phy);
488
489err0:
490 return ERR_PTR(ret);
491}
492EXPORT_SYMBOL_GPL(phy_create);
493
494/**
495 * devm_phy_create() - create a new phy
496 * @dev: device that is creating the new phy
497 * @ops: function pointers for performing phy operations
498 * @init_data: contains the list of PHY consumers or NULL
499 *
500 * Creates a new PHY device adding it to the PHY class.
501 * While at that, it also associates the device with the phy using devres.
502 * On driver detach, release function is invoked on the devres data,
503 * then, devres data is freed.
504 */
505struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
506 struct phy_init_data *init_data)
507{
508 struct phy **ptr, *phy;
509
510 ptr = devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL);
511 if (!ptr)
512 return ERR_PTR(-ENOMEM);
513
514 phy = phy_create(dev, ops, init_data);
515 if (!IS_ERR(phy)) {
516 *ptr = phy;
517 devres_add(dev, ptr);
518 } else {
519 devres_free(ptr);
520 }
521
522 return phy;
523}
524EXPORT_SYMBOL_GPL(devm_phy_create);
525
526/**
527 * phy_destroy() - destroy the phy
528 * @phy: the phy to be destroyed
529 *
530 * Called to destroy the phy.
531 */
532void phy_destroy(struct phy *phy)
533{
534 pm_runtime_disable(&phy->dev);
535 device_unregister(&phy->dev);
536}
537EXPORT_SYMBOL_GPL(phy_destroy);
538
539/**
540 * devm_phy_destroy() - destroy the PHY
541 * @dev: device that wants to release this phy
542 * @phy: the phy returned by devm_phy_get()
543 *
544 * destroys the devres associated with this phy and invokes phy_destroy
545 * to destroy the phy.
546 */
547void devm_phy_destroy(struct device *dev, struct phy *phy)
548{
549 int r;
550
551 r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
552 dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
553}
554EXPORT_SYMBOL_GPL(devm_phy_destroy);
555
556/**
557 * __of_phy_provider_register() - create/register phy provider with the framework
558 * @dev: struct device of the phy provider
559 * @owner: the module owner containing of_xlate
560 * @of_xlate: function pointer to obtain phy instance from phy provider
561 *
562 * Creates struct phy_provider from dev and of_xlate function pointer.
563 * This is used in the case of dt boot for finding the phy instance from
564 * phy provider.
565 */
566struct phy_provider *__of_phy_provider_register(struct device *dev,
567 struct module *owner, struct phy * (*of_xlate)(struct device *dev,
568 struct of_phandle_args *args))
569{
570 struct phy_provider *phy_provider;
571
572 phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
573 if (!phy_provider)
574 return ERR_PTR(-ENOMEM);
575
576 phy_provider->dev = dev;
577 phy_provider->owner = owner;
578 phy_provider->of_xlate = of_xlate;
579
580 mutex_lock(&phy_provider_mutex);
581 list_add_tail(&phy_provider->list, &phy_provider_list);
582 mutex_unlock(&phy_provider_mutex);
583
584 return phy_provider;
585}
586EXPORT_SYMBOL_GPL(__of_phy_provider_register);
587
588/**
589 * __devm_of_phy_provider_register() - create/register phy provider with the
590 * framework
591 * @dev: struct device of the phy provider
592 * @owner: the module owner containing of_xlate
593 * @of_xlate: function pointer to obtain phy instance from phy provider
594 *
595 * Creates struct phy_provider from dev and of_xlate function pointer.
596 * This is used in the case of dt boot for finding the phy instance from
597 * phy provider. While at that, it also associates the device with the
598 * phy provider using devres. On driver detach, release function is invoked
599 * on the devres data, then, devres data is freed.
600 */
601struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
602 struct module *owner, struct phy * (*of_xlate)(struct device *dev,
603 struct of_phandle_args *args))
604{
605 struct phy_provider **ptr, *phy_provider;
606
607 ptr = devres_alloc(devm_phy_provider_release, sizeof(*ptr), GFP_KERNEL);
608 if (!ptr)
609 return ERR_PTR(-ENOMEM);
610
611 phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
612 if (!IS_ERR(phy_provider)) {
613 *ptr = phy_provider;
614 devres_add(dev, ptr);
615 } else {
616 devres_free(ptr);
617 }
618
619 return phy_provider;
620}
621EXPORT_SYMBOL_GPL(__devm_of_phy_provider_register);
622
623/**
624 * of_phy_provider_unregister() - unregister phy provider from the framework
625 * @phy_provider: phy provider returned by of_phy_provider_register()
626 *
627 * Removes the phy_provider created using of_phy_provider_register().
628 */
629void of_phy_provider_unregister(struct phy_provider *phy_provider)
630{
631 if (IS_ERR(phy_provider))
632 return;
633
634 mutex_lock(&phy_provider_mutex);
635 list_del(&phy_provider->list);
636 kfree(phy_provider);
637 mutex_unlock(&phy_provider_mutex);
638}
639EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
640
641/**
642 * devm_of_phy_provider_unregister() - remove phy provider from the framework
643 * @dev: struct device of the phy provider
644 *
645 * destroys the devres associated with this phy provider and invokes
646 * of_phy_provider_unregister to unregister the phy provider.
647 */
648void devm_of_phy_provider_unregister(struct device *dev,
649 struct phy_provider *phy_provider) {
650 int r;
651
652 r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
653 phy_provider);
654 dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
655}
656EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
657
658/**
659 * phy_release() - release the phy
660 * @dev: the dev member within phy
661 *
662 * When the last reference to the device is removed, it is called
663 * from the embedded kobject as release method.
664 */
665static void phy_release(struct device *dev)
666{
667 struct phy *phy;
668
669 phy = to_phy(dev);
670 dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
671 ida_remove(&phy_ida, phy->id);
672 kfree(phy);
673}
674
675static int __init phy_core_init(void)
676{
677 phy_class = class_create(THIS_MODULE, "phy");
678 if (IS_ERR(phy_class)) {
679 pr_err("failed to create phy class --> %ld\n",
680 PTR_ERR(phy_class));
681 return PTR_ERR(phy_class);
682 }
683
684 phy_class->dev_release = phy_release;
685
686 return 0;
687}
688module_init(phy_core_init);
689
690static void __exit phy_core_exit(void)
691{
692 class_destroy(phy_class);
693}
694module_exit(phy_core_exit);
695
696MODULE_DESCRIPTION("Generic PHY Framework");
697MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
698MODULE_LICENSE("GPL v2");