Blame view

drivers/net/phy/mdio_bus.c 15.3 KB
02d320c3e   Sergei Shtylyov   mdio_bus: coding ...
1
  /* MDIO Bus interface
00db8189d   Andy Fleming   This patch adds a...
2
3
4
5
6
7
8
9
10
11
12
   *
   * Author: Andy Fleming
   *
   * Copyright (c) 2004 Freescale Semiconductor, Inc.
   *
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
   *
   */
8d242488c   Joe Perches   phy: Use pr_<level>
13
14
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
00db8189d   Andy Fleming   This patch adds a...
15
  #include <linux/kernel.h>
00db8189d   Andy Fleming   This patch adds a...
16
17
18
19
20
21
22
  #include <linux/string.h>
  #include <linux/errno.h>
  #include <linux/unistd.h>
  #include <linux/slab.h>
  #include <linux/interrupt.h>
  #include <linux/init.h>
  #include <linux/delay.h>
3d1e4db2b   Anton Vorontsov   phylib: Rework su...
23
  #include <linux/device.h>
a30e2c189   David Daney   netdev/phy/of: Ad...
24
  #include <linux/of_device.h>
4085a7f0a   Mark Brown   netdev/phy: Proto...
25
  #include <linux/of_mdio.h>
00db8189d   Andy Fleming   This patch adds a...
26
27
28
29
30
31
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/skbuff.h>
  #include <linux/spinlock.h>
  #include <linux/mm.h>
  #include <linux/module.h>
00db8189d   Andy Fleming   This patch adds a...
32
33
34
  #include <linux/mii.h>
  #include <linux/ethtool.h>
  #include <linux/phy.h>
02d320c3e   Sergei Shtylyov   mdio_bus: coding ...
35
36
  #include <linux/io.h>
  #include <linux/uaccess.h>
00db8189d   Andy Fleming   This patch adds a...
37

00db8189d   Andy Fleming   This patch adds a...
38
  #include <asm/irq.h>
00db8189d   Andy Fleming   This patch adds a...
39

7f854420f   Andrew Lunn   phy: Add API for ...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  int mdiobus_register_device(struct mdio_device *mdiodev)
  {
  	if (mdiodev->bus->mdio_map[mdiodev->addr])
  		return -EBUSY;
  
  	mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
  
  	return 0;
  }
  EXPORT_SYMBOL(mdiobus_register_device);
  
  int mdiobus_unregister_device(struct mdio_device *mdiodev)
  {
  	if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
  		return -EINVAL;
  
  	mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
  
  	return 0;
  }
  EXPORT_SYMBOL(mdiobus_unregister_device);
  
  struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
  {
  	struct mdio_device *mdiodev = bus->mdio_map[addr];
  
  	if (!mdiodev)
  		return NULL;
  
  	if (!(mdiodev->flags & MDIO_DEVICE_FLAG_PHY))
  		return NULL;
  
  	return container_of(mdiodev, struct phy_device, mdio);
  }
  EXPORT_SYMBOL(mdiobus_get_phy);
  
  bool mdiobus_is_registered_device(struct mii_bus *bus, int addr)
  {
  	return bus->mdio_map[addr];
  }
  EXPORT_SYMBOL(mdiobus_is_registered_device);
b3df0da88   Randy Dunlap   phy layer: add ke...
81
  /**
eb8a54a78   Timur Tabi   phylib: introduce...
82
   * mdiobus_alloc_size - allocate a mii_bus structure
af58f1d62   Randy Dunlap   kernel-doc: fix n...
83
84
   * @size: extra amount of memory to allocate for private storage.
   * If non-zero, then bus->priv is points to that memory.
298cf9beb   Lennert Buytenhek   phylib: move to d...
85
86
87
88
   *
   * Description: called by a bus driver to allocate an mii_bus
   * structure to fill in.
   */
eb8a54a78   Timur Tabi   phylib: introduce...
89
  struct mii_bus *mdiobus_alloc_size(size_t size)
298cf9beb   Lennert Buytenhek   phylib: move to d...
90
  {
46abc0217   Lennert Buytenhek   phylib: give mdio...
91
  	struct mii_bus *bus;
eb8a54a78   Timur Tabi   phylib: introduce...
92
93
  	size_t aligned_size = ALIGN(sizeof(*bus), NETDEV_ALIGN);
  	size_t alloc_size;
e7f4dc353   Andrew Lunn   mdio: Move alloca...
94
  	int i;
eb8a54a78   Timur Tabi   phylib: introduce...
95
96
97
98
99
100
  
  	/* If we alloc extra space, it should be aligned */
  	if (size)
  		alloc_size = aligned_size + size;
  	else
  		alloc_size = sizeof(*bus);
46abc0217   Lennert Buytenhek   phylib: give mdio...
101

eb8a54a78   Timur Tabi   phylib: introduce...
102
  	bus = kzalloc(alloc_size, GFP_KERNEL);
db9107b49   Dan Carpenter   mdio_bus: NULL de...
103
104
105
106
107
108
  	if (!bus)
  		return NULL;
  
  	bus->state = MDIOBUS_ALLOCATED;
  	if (size)
  		bus->priv = (void *)bus + aligned_size;
46abc0217   Lennert Buytenhek   phylib: give mdio...
109

e7f4dc353   Andrew Lunn   mdio: Move alloca...
110
111
112
  	/* Initialise the interrupts to polling */
  	for (i = 0; i < PHY_MAX_ADDR; i++)
  		bus->irq[i] = PHY_POLL;
46abc0217   Lennert Buytenhek   phylib: give mdio...
113
  	return bus;
298cf9beb   Lennert Buytenhek   phylib: move to d...
114
  }
eb8a54a78   Timur Tabi   phylib: introduce...
115
  EXPORT_SYMBOL(mdiobus_alloc_size);
298cf9beb   Lennert Buytenhek   phylib: move to d...
116

6d48f44b7   Grygorii Strashko   mdio_bus: impleme...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  static void _devm_mdiobus_free(struct device *dev, void *res)
  {
  	mdiobus_free(*(struct mii_bus **)res);
  }
  
  static int devm_mdiobus_match(struct device *dev, void *res, void *data)
  {
  	struct mii_bus **r = res;
  
  	if (WARN_ON(!r || !*r))
  		return 0;
  
  	return *r == data;
  }
  
  /**
   * devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
   * @dev:		Device to allocate mii_bus for
   * @sizeof_priv:	Space to allocate for private structure.
   *
   * Managed mdiobus_alloc_size. mii_bus allocated with this function is
   * automatically freed on driver detach.
   *
   * If an mii_bus allocated with this function needs to be freed separately,
   * devm_mdiobus_free() must be used.
   *
   * RETURNS:
   * Pointer to allocated mii_bus on success, NULL on failure.
   */
  struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
  {
  	struct mii_bus **ptr, *bus;
  
  	ptr = devres_alloc(_devm_mdiobus_free, sizeof(*ptr), GFP_KERNEL);
  	if (!ptr)
  		return NULL;
  
  	/* use raw alloc_dr for kmalloc caller tracing */
  	bus = mdiobus_alloc_size(sizeof_priv);
  	if (bus) {
  		*ptr = bus;
  		devres_add(dev, ptr);
  	} else {
  		devres_free(ptr);
  	}
  
  	return bus;
  }
93dccc591   Arnd Bergmann   mdio_bus: fix dev...
165
  EXPORT_SYMBOL_GPL(devm_mdiobus_alloc_size);
6d48f44b7   Grygorii Strashko   mdio_bus: impleme...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  
  /**
   * devm_mdiobus_free - Resource-managed mdiobus_free()
   * @dev:		Device this mii_bus belongs to
   * @bus:		the mii_bus associated with the device
   *
   * Free mii_bus allocated with devm_mdiobus_alloc_size().
   */
  void devm_mdiobus_free(struct device *dev, struct mii_bus *bus)
  {
  	int rc;
  
  	rc = devres_release(dev, _devm_mdiobus_free,
  			    devm_mdiobus_match, bus);
  	WARN_ON(rc);
  }
  EXPORT_SYMBOL_GPL(devm_mdiobus_free);
298cf9beb   Lennert Buytenhek   phylib: move to d...
183
  /**
46abc0217   Lennert Buytenhek   phylib: give mdio...
184
   * mdiobus_release - mii_bus device release callback
78c36b15a   Randy Dunlap   net/phy: add miss...
185
   * @d: the target struct device that contains the mii_bus
46abc0217   Lennert Buytenhek   phylib: give mdio...
186
187
188
189
190
191
192
   *
   * Description: called when the last reference to an mii_bus is
   * dropped, to free the underlying memory.
   */
  static void mdiobus_release(struct device *d)
  {
  	struct mii_bus *bus = to_mii_bus(d);
161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
193
194
195
  	BUG_ON(bus->state != MDIOBUS_RELEASED &&
  	       /* for compatibility with error handling in drivers */
  	       bus->state != MDIOBUS_ALLOCATED);
46abc0217   Lennert Buytenhek   phylib: give mdio...
196
197
198
199
200
201
202
  	kfree(bus);
  }
  
  static struct class mdio_bus_class = {
  	.name		= "mdio_bus",
  	.dev_release	= mdiobus_release,
  };
b943fbb09   Bjørn Mork   net: of/phy: fix ...
203
  #if IS_ENABLED(CONFIG_OF_MDIO)
251060220   David Daney   netdev/of/phy: Ne...
204
  /* Helper function for of_mdio_find_bus */
9f3b795a6   Michał Mirosław   driver-core: cons...
205
  static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np)
251060220   David Daney   netdev/of/phy: Ne...
206
207
208
209
210
  {
  	return dev->of_node == mdio_bus_np;
  }
  /**
   * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
f41ef2e7d   Randy Dunlap   netdev: fix drive...
211
   * @mdio_bus_np: Pointer to the mii_bus.
251060220   David Daney   netdev/of/phy: Ne...
212
   *
a13644213   Russell King   phy: fix of_mdio_...
213
214
215
   * Returns a reference to the mii_bus, or NULL if none found.  The
   * embedded struct device will have its reference count incremented,
   * and this must be put once the bus is finished with.
251060220   David Daney   netdev/of/phy: Ne...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
   *
   * Because the association of a device_node and mii_bus is made via
   * of_mdiobus_register(), the mii_bus cannot be found before it is
   * registered with of_mdiobus_register().
   *
   */
  struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np)
  {
  	struct device *d;
  
  	if (!mdio_bus_np)
  		return NULL;
  
  	d = class_find_device(&mdio_bus_class, NULL,  mdio_bus_np,
  			      of_mdio_bus_match);
  
  	return d ? to_mii_bus(d) : NULL;
  }
  EXPORT_SYMBOL(of_mdio_find_bus);
d9daa2472   Daniel Mack   net: fix circular...
235

f03bc4ae5   Andrew Lunn   mdio_bus: General...
236
237
238
239
240
  /* Walk the list of subnodes of a mdio bus and look for a node that
   * matches the mdio device's address with its 'reg' property. If
   * found, set the of_node pointer for the mdio device. This allows
   * auto-probed phy devices to be supplied with information passed in
   * via DT.
d9daa2472   Daniel Mack   net: fix circular...
241
   */
f03bc4ae5   Andrew Lunn   mdio_bus: General...
242
243
  static void of_mdiobus_link_mdiodev(struct mii_bus *bus,
  				    struct mdio_device *mdiodev)
d9daa2472   Daniel Mack   net: fix circular...
244
  {
f03bc4ae5   Andrew Lunn   mdio_bus: General...
245
  	struct device *dev = &mdiodev->dev;
d9daa2472   Daniel Mack   net: fix circular...
246
  	struct device_node *child;
e5a03bfd8   Andrew Lunn   phy: Add an mdio_...
247
  	if (dev->of_node || !bus->dev.of_node)
d9daa2472   Daniel Mack   net: fix circular...
248
  		return;
e5a03bfd8   Andrew Lunn   phy: Add an mdio_...
249
  	for_each_available_child_of_node(bus->dev.of_node, child) {
d9daa2472   Daniel Mack   net: fix circular...
250
251
252
253
254
  		int addr;
  		int ret;
  
  		ret = of_property_read_u32(child, "reg", &addr);
  		if (ret < 0) {
f03bc4ae5   Andrew Lunn   mdio_bus: General...
255
256
  			dev_err(dev, "%s has invalid MDIO address
  ",
d9daa2472   Daniel Mack   net: fix circular...
257
258
259
  				child->full_name);
  			continue;
  		}
f03bc4ae5   Andrew Lunn   mdio_bus: General...
260
  		/* A MDIO device must have a reg property in the range [0-31] */
d9daa2472   Daniel Mack   net: fix circular...
261
  		if (addr >= PHY_MAX_ADDR) {
f03bc4ae5   Andrew Lunn   mdio_bus: General...
262
263
  			dev_err(dev, "%s MDIO address %i is too large
  ",
d9daa2472   Daniel Mack   net: fix circular...
264
265
266
  				child->full_name, addr);
  			continue;
  		}
f03bc4ae5   Andrew Lunn   mdio_bus: General...
267
  		if (addr == mdiodev->addr) {
d9daa2472   Daniel Mack   net: fix circular...
268
269
270
271
272
273
  			dev->of_node = child;
  			return;
  		}
  	}
  }
  #else /* !IS_ENABLED(CONFIG_OF_MDIO) */
f03bc4ae5   Andrew Lunn   mdio_bus: General...
274
275
  static inline void of_mdiobus_link_mdiodev(struct mii_bus *mdio,
  					   struct mdio_device *mdiodev)
d9daa2472   Daniel Mack   net: fix circular...
276
277
  {
  }
251060220   David Daney   netdev/of/phy: Ne...
278
  #endif
46abc0217   Lennert Buytenhek   phylib: give mdio...
279
  /**
59f069789   Russell King   net: update docbo...
280
   * __mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
b3df0da88   Randy Dunlap   phy layer: add ke...
281
   * @bus: target mii_bus
59f069789   Russell King   net: update docbo...
282
   * @owner: module containing bus accessor functions
e13934563   Andy Fleming   [PATCH] PHY Layer...
283
   *
b3df0da88   Randy Dunlap   phy layer: add ke...
284
   * Description: Called by a bus driver to bring up all the PHYs
59f069789   Russell King   net: update docbo...
285
286
   *   on a given bus, and attach them to the bus. Drivers should use
   *   mdiobus_register() rather than __mdiobus_register() unless they
f89df3f38   Andrew Lunn   mdio_bus: Add com...
287
288
289
   *   need to pass a specific owner module. MDIO devices which are not
   *   PHYs will not be brought up by this function. They are expected to
   *   to be explicitly listed in DT and instantiated by of_mdiobus_register().
b3df0da88   Randy Dunlap   phy layer: add ke...
290
291
   *
   * Returns 0 on success or < 0 on error.
e13934563   Andy Fleming   [PATCH] PHY Layer...
292
   */
3e3aaf649   Russell King   phy: fix mdiobus ...
293
  int __mdiobus_register(struct mii_bus *bus, struct module *owner)
e13934563   Andy Fleming   [PATCH] PHY Layer...
294
  {
711fdba37   Andrew Lunn   mdio: Abstract de...
295
  	struct mdio_device *mdiodev;
161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
296
  	int i, err;
e13934563   Andy Fleming   [PATCH] PHY Layer...
297

e13934563   Andy Fleming   [PATCH] PHY Layer...
298
  	if (NULL == bus || NULL == bus->name ||
02d320c3e   Sergei Shtylyov   mdio_bus: coding ...
299
  	    NULL == bus->read || NULL == bus->write)
e13934563   Andy Fleming   [PATCH] PHY Layer...
300
  		return -EINVAL;
46abc0217   Lennert Buytenhek   phylib: give mdio...
301
302
  	BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
  	       bus->state != MDIOBUS_UNREGISTERED);
3e3aaf649   Russell King   phy: fix mdiobus ...
303
  	bus->owner = owner;
46abc0217   Lennert Buytenhek   phylib: give mdio...
304
305
306
  	bus->dev.parent = bus->parent;
  	bus->dev.class = &mdio_bus_class;
  	bus->dev.groups = NULL;
036b66879   Stephen Hemminger   mdio: fix non-con...
307
  	dev_set_name(&bus->dev, "%s", bus->id);
46abc0217   Lennert Buytenhek   phylib: give mdio...
308
309
310
  
  	err = device_register(&bus->dev);
  	if (err) {
8d242488c   Joe Perches   phy: Use pr_<level>
311
312
  		pr_err("mii_bus %s failed to register
  ", bus->id);
0c692d078   Levente Kurusa   drivers/net/phy/m...
313
  		put_device(&bus->dev);
46abc0217   Lennert Buytenhek   phylib: give mdio...
314
315
  		return -EINVAL;
  	}
d1e7fe4d9   Adrian Bunk   net/phy/mdio_bus....
316
  	mutex_init(&bus->mdio_lock);
e13934563   Andy Fleming   [PATCH] PHY Layer...
317
318
319
320
  	if (bus->reset)
  		bus->reset(bus);
  
  	for (i = 0; i < PHY_MAX_ADDR; i++) {
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
321
322
  		if ((bus->phy_mask & (1 << i)) == 0) {
  			struct phy_device *phydev;
e13934563   Andy Fleming   [PATCH] PHY Layer...
323

4fd5f812c   Lennert Buytenhek   phylib: allow inc...
324
  			phydev = mdiobus_scan(bus, i);
70e927b98   Marek Vasut   mdio_bus: Fix MDI...
325
  			if (IS_ERR(phydev) && (PTR_ERR(phydev) != -ENODEV)) {
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
326
  				err = PTR_ERR(phydev);
161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
327
328
  				goto error;
  			}
64b1c2b42   Herbert Valerio Riedel   phy: mdiobus_regi...
329
  		}
e13934563   Andy Fleming   [PATCH] PHY Layer...
330
  	}
161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
331
  	bus->state = MDIOBUS_REGISTERED;
e13934563   Andy Fleming   [PATCH] PHY Layer...
332
333
  	pr_info("%s: probed
  ", bus->name);
161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
334
  	return 0;
e13934563   Andy Fleming   [PATCH] PHY Layer...
335

161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
336
337
  error:
  	while (--i >= 0) {
711fdba37   Andrew Lunn   mdio: Abstract de...
338
339
340
341
342
343
  		mdiodev = bus->mdio_map[i];
  		if (!mdiodev)
  			continue;
  
  		mdiodev->device_remove(mdiodev);
  		mdiodev->device_free(mdiodev);
161c8d2f5   Krzysztof Halasa   net: PHYLIB mdio ...
344
345
  	}
  	device_del(&bus->dev);
e13934563   Andy Fleming   [PATCH] PHY Layer...
346
347
  	return err;
  }
3e3aaf649   Russell King   phy: fix mdiobus ...
348
  EXPORT_SYMBOL(__mdiobus_register);
e13934563   Andy Fleming   [PATCH] PHY Layer...
349
350
351
  
  void mdiobus_unregister(struct mii_bus *bus)
  {
a9049e0c5   Andrew Lunn   mdio: Add support...
352
  	struct mdio_device *mdiodev;
e13934563   Andy Fleming   [PATCH] PHY Layer...
353
  	int i;
46abc0217   Lennert Buytenhek   phylib: give mdio...
354
355
  	BUG_ON(bus->state != MDIOBUS_REGISTERED);
  	bus->state = MDIOBUS_UNREGISTERED;
e13934563   Andy Fleming   [PATCH] PHY Layer...
356
  	for (i = 0; i < PHY_MAX_ADDR; i++) {
a9049e0c5   Andrew Lunn   mdio: Add support...
357
358
359
  		mdiodev = bus->mdio_map[i];
  		if (!mdiodev)
  			continue;
711fdba37   Andrew Lunn   mdio: Abstract de...
360
361
  		mdiodev->device_remove(mdiodev);
  		mdiodev->device_free(mdiodev);
e13934563   Andy Fleming   [PATCH] PHY Layer...
362
  	}
b6c6aedcb   Mark Salter   phylib: fix devic...
363
  	device_del(&bus->dev);
e13934563   Andy Fleming   [PATCH] PHY Layer...
364
365
  }
  EXPORT_SYMBOL(mdiobus_unregister);
298cf9beb   Lennert Buytenhek   phylib: move to d...
366
367
368
369
  /**
   * mdiobus_free - free a struct mii_bus
   * @bus: mii_bus to free
   *
46abc0217   Lennert Buytenhek   phylib: give mdio...
370
371
372
   * This function releases the reference to the underlying device
   * object in the mii_bus.  If this is the last reference, the mii_bus
   * will be freed.
298cf9beb   Lennert Buytenhek   phylib: move to d...
373
374
375
   */
  void mdiobus_free(struct mii_bus *bus)
  {
02d320c3e   Sergei Shtylyov   mdio_bus: coding ...
376
  	/* For compatibility with error handling in drivers. */
46abc0217   Lennert Buytenhek   phylib: give mdio...
377
378
379
380
381
382
383
384
385
  	if (bus->state == MDIOBUS_ALLOCATED) {
  		kfree(bus);
  		return;
  	}
  
  	BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
  	bus->state = MDIOBUS_RELEASED;
  
  	put_device(&bus->dev);
298cf9beb   Lennert Buytenhek   phylib: move to d...
386
387
  }
  EXPORT_SYMBOL(mdiobus_free);
f89df3f38   Andrew Lunn   mdio_bus: Add com...
388
389
390
391
392
393
394
395
396
397
398
399
  /**
   * mdiobus_scan - scan a bus for MDIO devices.
   * @bus: mii_bus to scan
   * @addr: address on bus to scan
   *
   * This function scans the MDIO bus, looking for devices which can be
   * identified using a vendor/product ID in registers 2 and 3. Not all
   * MDIO devices have such registers, but PHY devices typically
   * do. Hence this function assumes anything found is a PHY, or can be
   * treated as a PHY. Other MDIO devices, such as switches, will
   * probably not be found during the scan.
   */
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
400
401
402
403
  struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
  {
  	struct phy_device *phydev;
  	int err;
ac28b9f8c   David Daney   netdev/phy: Handl...
404
  	phydev = get_phy_device(bus, addr, false);
66c239e71   Sergei Shtylyov   mdio_bus: get_phy...
405
  	if (IS_ERR(phydev))
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
406
  		return phydev;
86f6cf412   Daniel Mack   net: of_mdio: add...
407
408
409
410
  	/*
  	 * For DT, see if the auto-probed phy has a correspoding child
  	 * in the bus node, and set the of_node pointer in this case.
  	 */
f03bc4ae5   Andrew Lunn   mdio_bus: General...
411
  	of_mdiobus_link_mdiodev(bus, &phydev->mdio);
86f6cf412   Daniel Mack   net: of_mdio: add...
412

4dea547fe   Grant Likely   phylib: rework to...
413
  	err = phy_device_register(phydev);
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
414
  	if (err) {
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
415
  		phy_device_free(phydev);
e98a3aabf   Sergei Shtylyov   mdio_bus: don't r...
416
  		return ERR_PTR(-ENODEV);
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
417
  	}
4fd5f812c   Lennert Buytenhek   phylib: allow inc...
418
419
420
  	return phydev;
  }
  EXPORT_SYMBOL(mdiobus_scan);
b3df0da88   Randy Dunlap   phy layer: add ke...
421
  /**
21dd19fed   Neil Armstrong   net: phy: Add nes...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
   * mdiobus_read_nested - Nested version of the mdiobus_read function
   * @bus: the mii_bus struct
   * @addr: the phy address
   * @regnum: register number to read
   *
   * In case of nested MDIO bus access avoid lockdep false positives by
   * using mutex_lock_nested().
   *
   * NOTE: MUST NOT be called from interrupt context,
   * because the bus read/write functions may wait for an interrupt
   * to conclude the operation.
   */
  int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
  {
  	int retval;
  
  	BUG_ON(in_interrupt());
9a6f2b011   Andrew Lunn   net: mdio: Fix lo...
439
  	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
21dd19fed   Neil Armstrong   net: phy: Add nes...
440
441
442
443
444
445
446
447
  	retval = bus->read(bus, addr, regnum);
  	mutex_unlock(&bus->mdio_lock);
  
  	return retval;
  }
  EXPORT_SYMBOL(mdiobus_read_nested);
  
  /**
2e8881032   Lennert Buytenhek   phylib: add mdiob...
448
449
450
451
452
453
454
455
456
   * mdiobus_read - Convenience function for reading a given MII mgmt register
   * @bus: the mii_bus struct
   * @addr: the phy address
   * @regnum: register number to read
   *
   * NOTE: MUST NOT be called from interrupt context,
   * because the bus read/write functions may wait for an interrupt
   * to conclude the operation.
   */
abf35df21   Jason Gunthorpe   NET: Support clau...
457
  int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
2e8881032   Lennert Buytenhek   phylib: add mdiob...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  {
  	int retval;
  
  	BUG_ON(in_interrupt());
  
  	mutex_lock(&bus->mdio_lock);
  	retval = bus->read(bus, addr, regnum);
  	mutex_unlock(&bus->mdio_lock);
  
  	return retval;
  }
  EXPORT_SYMBOL(mdiobus_read);
  
  /**
21dd19fed   Neil Armstrong   net: phy: Add nes...
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
   * mdiobus_write_nested - Nested version of the mdiobus_write function
   * @bus: the mii_bus struct
   * @addr: the phy address
   * @regnum: register number to write
   * @val: value to write to @regnum
   *
   * In case of nested MDIO bus access avoid lockdep false positives by
   * using mutex_lock_nested().
   *
   * NOTE: MUST NOT be called from interrupt context,
   * because the bus read/write functions may wait for an interrupt
   * to conclude the operation.
   */
  int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)
  {
  	int err;
  
  	BUG_ON(in_interrupt());
9a6f2b011   Andrew Lunn   net: mdio: Fix lo...
490
  	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
21dd19fed   Neil Armstrong   net: phy: Add nes...
491
492
493
494
495
496
497
498
  	err = bus->write(bus, addr, regnum, val);
  	mutex_unlock(&bus->mdio_lock);
  
  	return err;
  }
  EXPORT_SYMBOL(mdiobus_write_nested);
  
  /**
2e8881032   Lennert Buytenhek   phylib: add mdiob...
499
500
501
502
503
504
505
506
507
508
   * mdiobus_write - Convenience function for writing a given MII mgmt register
   * @bus: the mii_bus struct
   * @addr: the phy address
   * @regnum: register number to write
   * @val: value to write to @regnum
   *
   * NOTE: MUST NOT be called from interrupt context,
   * because the bus read/write functions may wait for an interrupt
   * to conclude the operation.
   */
abf35df21   Jason Gunthorpe   NET: Support clau...
509
  int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
2e8881032   Lennert Buytenhek   phylib: add mdiob...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
  {
  	int err;
  
  	BUG_ON(in_interrupt());
  
  	mutex_lock(&bus->mdio_lock);
  	err = bus->write(bus, addr, regnum, val);
  	mutex_unlock(&bus->mdio_lock);
  
  	return err;
  }
  EXPORT_SYMBOL(mdiobus_write);
  
  /**
e76a4957c   Andrew Lunn   phy: Move phy spe...
524
525
526
527
   * mdio_bus_match - determine if given MDIO driver supports the given
   *		    MDIO device
   * @dev: target MDIO device
   * @drv: given MDIO driver
00db8189d   Andy Fleming   This patch adds a...
528
   *
e76a4957c   Andrew Lunn   phy: Move phy spe...
529
530
531
532
   * Description: Given a MDIO device, and a MDIO driver, return 1 if
   *   the driver supports the device.  Otherwise, return 0. This may
   *   require calling the devices own match function, since different classes
   *   of MDIO devices have different match criteria.
00db8189d   Andy Fleming   This patch adds a...
533
534
535
   */
  static int mdio_bus_match(struct device *dev, struct device_driver *drv)
  {
e76a4957c   Andrew Lunn   phy: Move phy spe...
536
  	struct mdio_device *mdio = to_mdio_device(dev);
00db8189d   Andy Fleming   This patch adds a...
537

a30e2c189   David Daney   netdev/phy/of: Ad...
538
539
  	if (of_driver_match_device(dev, drv))
  		return 1;
e76a4957c   Andrew Lunn   phy: Move phy spe...
540
541
  	if (mdio->bus_match)
  		return mdio->bus_match(dev, drv);
a30e2c189   David Daney   netdev/phy/of: Ad...
542

e76a4957c   Andrew Lunn   phy: Move phy spe...
543
  	return 0;
00db8189d   Andy Fleming   This patch adds a...
544
  }
2f5cb4340   Anton Vorontsov   phylib: Properly ...
545
  #ifdef CONFIG_PM
2f5cb4340   Anton Vorontsov   phylib: Properly ...
546
  static int mdio_bus_suspend(struct device *dev)
00db8189d   Andy Fleming   This patch adds a...
547
  {
bc87922ff   Andrew Lunn   phy: Move PHY PM ...
548
  	struct mdio_device *mdio = to_mdio_device(dev);
00db8189d   Andy Fleming   This patch adds a...
549

bc87922ff   Andrew Lunn   phy: Move PHY PM ...
550
551
  	if (mdio->pm_ops && mdio->pm_ops->suspend)
  		return mdio->pm_ops->suspend(dev);
541cd3ee0   Anton Vorontsov   phylib: Fix deadl...
552

bc87922ff   Andrew Lunn   phy: Move PHY PM ...
553
  	return 0;
00db8189d   Andy Fleming   This patch adds a...
554
  }
2f5cb4340   Anton Vorontsov   phylib: Properly ...
555
  static int mdio_bus_resume(struct device *dev)
00db8189d   Andy Fleming   This patch adds a...
556
  {
bc87922ff   Andrew Lunn   phy: Move PHY PM ...
557
  	struct mdio_device *mdio = to_mdio_device(dev);
541cd3ee0   Anton Vorontsov   phylib: Fix deadl...
558

bc87922ff   Andrew Lunn   phy: Move PHY PM ...
559
560
  	if (mdio->pm_ops && mdio->pm_ops->resume)
  		return mdio->pm_ops->resume(dev);
541cd3ee0   Anton Vorontsov   phylib: Fix deadl...
561
562
  
  	return 0;
00db8189d   Andy Fleming   This patch adds a...
563
  }
2f5cb4340   Anton Vorontsov   phylib: Properly ...
564
565
  static int mdio_bus_restore(struct device *dev)
  {
bc87922ff   Andrew Lunn   phy: Move PHY PM ...
566
  	struct mdio_device *mdio = to_mdio_device(dev);
2f5cb4340   Anton Vorontsov   phylib: Properly ...
567

bc87922ff   Andrew Lunn   phy: Move PHY PM ...
568
569
  	if (mdio->pm_ops && mdio->pm_ops->restore)
  		return mdio->pm_ops->restore(dev);
2f5cb4340   Anton Vorontsov   phylib: Properly ...
570
571
572
  
  	return 0;
  }
02d320c3e   Sergei Shtylyov   mdio_bus: coding ...
573
  static const struct dev_pm_ops mdio_bus_pm_ops = {
2f5cb4340   Anton Vorontsov   phylib: Properly ...
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  	.suspend = mdio_bus_suspend,
  	.resume = mdio_bus_resume,
  	.freeze = mdio_bus_suspend,
  	.thaw = mdio_bus_resume,
  	.restore = mdio_bus_restore,
  };
  
  #define MDIO_BUS_PM_OPS (&mdio_bus_pm_ops)
  
  #else
  
  #define MDIO_BUS_PM_OPS NULL
  
  #endif /* CONFIG_PM */
00db8189d   Andy Fleming   This patch adds a...
588
589
590
  struct bus_type mdio_bus_type = {
  	.name		= "mdio_bus",
  	.match		= mdio_bus_match,
2f5cb4340   Anton Vorontsov   phylib: Properly ...
591
  	.pm		= MDIO_BUS_PM_OPS,
00db8189d   Andy Fleming   This patch adds a...
592
  };
11b0bacd7   Vitaly Bordug   [PATCH] PAL: Supp...
593
  EXPORT_SYMBOL(mdio_bus_type);
00db8189d   Andy Fleming   This patch adds a...
594

67c4f3fa2   Jeff Garzik   Fix numerous mino...
595
  int __init mdio_bus_init(void)
00db8189d   Andy Fleming   This patch adds a...
596
  {
46abc0217   Lennert Buytenhek   phylib: give mdio...
597
598
599
600
601
602
603
604
605
606
  	int ret;
  
  	ret = class_register(&mdio_bus_class);
  	if (!ret) {
  		ret = bus_register(&mdio_bus_type);
  		if (ret)
  			class_unregister(&mdio_bus_class);
  	}
  
  	return ret;
00db8189d   Andy Fleming   This patch adds a...
607
  }
dc85dec68   Peter Chubb   [PATCH] 'mdio_bus...
608
  void mdio_bus_exit(void)
e13934563   Andy Fleming   [PATCH] PHY Layer...
609
  {
46abc0217   Lennert Buytenhek   phylib: give mdio...
610
  	class_unregister(&mdio_bus_class);
e13934563   Andy Fleming   [PATCH] PHY Layer...
611
612
  	bus_unregister(&mdio_bus_type);
  }