@@ -348,3 +348,160 @@ int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
348
348
return ret ;
349
349
}
350
350
EXPORT_SYMBOL_GPL (__phy_modify );
351
+
352
+ static int __phy_read_page (struct phy_device * phydev )
353
+ {
354
+ return phydev -> drv -> read_page (phydev );
355
+ }
356
+
357
+ static int __phy_write_page (struct phy_device * phydev , int page )
358
+ {
359
+ return phydev -> drv -> write_page (phydev , page );
360
+ }
361
+
362
+ /**
363
+ * phy_save_page() - take the bus lock and save the current page
364
+ * @phydev: a pointer to a &struct phy_device
365
+ *
366
+ * Take the MDIO bus lock, and return the current page number. On error,
367
+ * returns a negative errno. phy_restore_page() must always be called
368
+ * after this, irrespective of success or failure of this call.
369
+ */
370
+ int phy_save_page (struct phy_device * phydev )
371
+ {
372
+ mutex_lock (& phydev -> mdio .bus -> mdio_lock );
373
+ return __phy_read_page (phydev );
374
+ }
375
+ EXPORT_SYMBOL_GPL (phy_save_page );
376
+
377
+ /**
378
+ * phy_select_page() - take the bus lock, save the current page, and set a page
379
+ * @phydev: a pointer to a &struct phy_device
380
+ * @page: desired page
381
+ *
382
+ * Take the MDIO bus lock to protect against concurrent access, save the
383
+ * current PHY page, and set the current page. On error, returns a
384
+ * negative errno, otherwise returns the previous page number.
385
+ * phy_restore_page() must always be called after this, irrespective
386
+ * of success or failure of this call.
387
+ */
388
+ int phy_select_page (struct phy_device * phydev , int page )
389
+ {
390
+ int ret , oldpage ;
391
+
392
+ oldpage = ret = phy_save_page (phydev );
393
+ if (ret < 0 )
394
+ return ret ;
395
+
396
+ if (oldpage != page ) {
397
+ ret = __phy_write_page (phydev , page );
398
+ if (ret < 0 )
399
+ return ret ;
400
+ }
401
+
402
+ return oldpage ;
403
+ }
404
+ EXPORT_SYMBOL_GPL (phy_select_page );
405
+
406
+ /**
407
+ * phy_restore_page() - restore the page register and release the bus lock
408
+ * @phydev: a pointer to a &struct phy_device
409
+ * @oldpage: the old page, return value from phy_save_page() or phy_select_page()
410
+ * @ret: operation's return code
411
+ *
412
+ * Release the MDIO bus lock, restoring @oldpage if it is a valid page.
413
+ * This function propagates the earliest error code from the group of
414
+ * operations.
415
+ *
416
+ * Returns:
417
+ * @oldpage if it was a negative value, otherwise
418
+ * @ret if it was a negative errno value, otherwise
419
+ * phy_write_page()'s negative value if it were in error, otherwise
420
+ * @ret.
421
+ */
422
+ int phy_restore_page (struct phy_device * phydev , int oldpage , int ret )
423
+ {
424
+ int r ;
425
+
426
+ if (oldpage >= 0 ) {
427
+ r = __phy_write_page (phydev , oldpage );
428
+
429
+ /* Propagate the operation return code if the page write
430
+ * was successful.
431
+ */
432
+ if (ret >= 0 && r < 0 )
433
+ ret = r ;
434
+ } else {
435
+ /* Propagate the phy page selection error code */
436
+ ret = oldpage ;
437
+ }
438
+
439
+ mutex_unlock (& phydev -> mdio .bus -> mdio_lock );
440
+
441
+ return ret ;
442
+ }
443
+ EXPORT_SYMBOL_GPL (phy_restore_page );
444
+
445
+ /**
446
+ * phy_read_paged() - Convenience function for reading a paged register
447
+ * @phydev: a pointer to a &struct phy_device
448
+ * @page: the page for the phy
449
+ * @regnum: register number
450
+ *
451
+ * Same rules as for phy_read().
452
+ */
453
+ int phy_read_paged (struct phy_device * phydev , int page , u32 regnum )
454
+ {
455
+ int ret = 0 , oldpage ;
456
+
457
+ oldpage = phy_select_page (phydev , page );
458
+ if (oldpage >= 0 )
459
+ ret = __phy_read (phydev , regnum );
460
+
461
+ return phy_restore_page (phydev , oldpage , ret );
462
+ }
463
+ EXPORT_SYMBOL (phy_read_paged );
464
+
465
+ /**
466
+ * phy_write_paged() - Convenience function for writing a paged register
467
+ * @phydev: a pointer to a &struct phy_device
468
+ * @page: the page for the phy
469
+ * @regnum: register number
470
+ * @val: value to write
471
+ *
472
+ * Same rules as for phy_write().
473
+ */
474
+ int phy_write_paged (struct phy_device * phydev , int page , u32 regnum , u16 val )
475
+ {
476
+ int ret = 0 , oldpage ;
477
+
478
+ oldpage = phy_select_page (phydev , page );
479
+ if (oldpage >= 0 )
480
+ ret = __phy_write (phydev , regnum , val );
481
+
482
+ return phy_restore_page (phydev , oldpage , ret );
483
+ }
484
+ EXPORT_SYMBOL (phy_write_paged );
485
+
486
+ /**
487
+ * phy_modify_paged() - Convenience function for modifying a paged register
488
+ * @phydev: a pointer to a &struct phy_device
489
+ * @page: the page for the phy
490
+ * @regnum: register number
491
+ * @mask: bit mask of bits to clear
492
+ * @set: bit mask of bits to set
493
+ *
494
+ * Same rules as for phy_read() and phy_write().
495
+ */
496
+ int phy_modify_paged (struct phy_device * phydev , int page , u32 regnum ,
497
+ u16 mask , u16 set )
498
+ {
499
+ int ret = 0 , oldpage ;
500
+
501
+ oldpage = phy_select_page (phydev , page );
502
+ if (oldpage >= 0 )
503
+ ret = __phy_modify (phydev , regnum , mask , set );
504
+
505
+ return phy_restore_page (phydev , oldpage , ret );
506
+ }
507
+ EXPORT_SYMBOL (phy_modify_paged );
0 commit comments