root/drivers/net/phy/uPD60620.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. upd60620_config_init
  2. upd60620_read_status

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Driver for the Renesas PHY uPD60620.
   4  *
   5  * Copyright (C) 2015 Softing Industrial Automation GmbH
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/phy.h>
  11 
  12 #define UPD60620_PHY_ID    0xb8242824
  13 
  14 /* Extended Registers and values */
  15 /* PHY Special Control/Status    */
  16 #define PHY_PHYSCR         0x1F      /* PHY.31 */
  17 #define PHY_PHYSCR_10MB    0x0004    /* PHY speed = 10mb */
  18 #define PHY_PHYSCR_100MB   0x0008    /* PHY speed = 100mb */
  19 #define PHY_PHYSCR_DUPLEX  0x0010    /* PHY Duplex */
  20 
  21 /* PHY Special Modes */
  22 #define PHY_SPM            0x12      /* PHY.18 */
  23 
  24 /* Init PHY */
  25 
  26 static int upd60620_config_init(struct phy_device *phydev)
  27 {
  28         /* Enable support for passive HUBs (could be a strap option) */
  29         /* PHYMODE: All speeds, HD in parallel detect */
  30         return phy_write(phydev, PHY_SPM, 0x0180 | phydev->mdio.addr);
  31 }
  32 
  33 /* Get PHY status from common registers */
  34 
  35 static int upd60620_read_status(struct phy_device *phydev)
  36 {
  37         int phy_state;
  38 
  39         /* Read negotiated state */
  40         phy_state = phy_read(phydev, MII_BMSR);
  41         if (phy_state < 0)
  42                 return phy_state;
  43 
  44         phydev->link = 0;
  45         linkmode_zero(phydev->lp_advertising);
  46         phydev->pause = 0;
  47         phydev->asym_pause = 0;
  48 
  49         if (phy_state & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) {
  50                 phy_state = phy_read(phydev, PHY_PHYSCR);
  51                 if (phy_state < 0)
  52                         return phy_state;
  53 
  54                 if (phy_state & (PHY_PHYSCR_10MB | PHY_PHYSCR_100MB)) {
  55                         phydev->link = 1;
  56                         phydev->speed = SPEED_10;
  57                         phydev->duplex = DUPLEX_HALF;
  58 
  59                         if (phy_state & PHY_PHYSCR_100MB)
  60                                 phydev->speed = SPEED_100;
  61                         if (phy_state & PHY_PHYSCR_DUPLEX)
  62                                 phydev->duplex = DUPLEX_FULL;
  63 
  64                         phy_state = phy_read(phydev, MII_LPA);
  65                         if (phy_state < 0)
  66                                 return phy_state;
  67 
  68                         mii_lpa_to_linkmode_lpa_t(phydev->lp_advertising,
  69                                                   phy_state);
  70 
  71                         if (phydev->duplex == DUPLEX_FULL) {
  72                                 if (phy_state & LPA_PAUSE_CAP)
  73                                         phydev->pause = 1;
  74                                 if (phy_state & LPA_PAUSE_ASYM)
  75                                         phydev->asym_pause = 1;
  76                         }
  77                 }
  78         }
  79         return 0;
  80 }
  81 
  82 MODULE_DESCRIPTION("Renesas uPD60620 PHY driver");
  83 MODULE_AUTHOR("Bernd Edlinger <bernd.edlinger@hotmail.de>");
  84 MODULE_LICENSE("GPL");
  85 
  86 static struct phy_driver upd60620_driver[1] = { {
  87         .phy_id         = UPD60620_PHY_ID,
  88         .phy_id_mask    = 0xfffffffe,
  89         .name           = "Renesas uPD60620",
  90         /* PHY_BASIC_FEATURES */
  91         .flags          = 0,
  92         .config_init    = upd60620_config_init,
  93         .read_status    = upd60620_read_status,
  94 } };
  95 
  96 module_phy_driver(upd60620_driver);
  97 
  98 static struct mdio_device_id __maybe_unused upd60620_tbl[] = {
  99         { UPD60620_PHY_ID, 0xfffffffe },
 100         { }
 101 };
 102 
 103 MODULE_DEVICE_TABLE(mdio, upd60620_tbl);

/* [<][>][^][v][top][bottom][index][help] */