root/drivers/net/phy/swphy.c

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

DEFINITIONS

This source file includes following definitions.
  1. swphy_decode_speed
  2. swphy_validate_state
  3. swphy_read_reg

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Software PHY emulation
   4  *
   5  * Code taken from fixed_phy.c by Russell King <rmk+kernel@arm.linux.org.uk>
   6  *
   7  * Author: Vitaly Bordug <vbordug@ru.mvista.com>
   8  *         Anton Vorontsov <avorontsov@ru.mvista.com>
   9  *
  10  * Copyright (c) 2006-2007 MontaVista Software, Inc.
  11  */
  12 #include <linux/export.h>
  13 #include <linux/mii.h>
  14 #include <linux/phy.h>
  15 #include <linux/phy_fixed.h>
  16 
  17 #include "swphy.h"
  18 
  19 #define MII_REGS_NUM 29
  20 
  21 struct swmii_regs {
  22         u16 bmsr;
  23         u16 lpa;
  24         u16 lpagb;
  25         u16 estat;
  26 };
  27 
  28 enum {
  29         SWMII_SPEED_10 = 0,
  30         SWMII_SPEED_100,
  31         SWMII_SPEED_1000,
  32         SWMII_DUPLEX_HALF = 0,
  33         SWMII_DUPLEX_FULL,
  34 };
  35 
  36 /*
  37  * These two tables get bitwise-anded together to produce the final result.
  38  * This means the speed table must contain both duplex settings, and the
  39  * duplex table must contain all speed settings.
  40  */
  41 static const struct swmii_regs speed[] = {
  42         [SWMII_SPEED_10] = {
  43                 .lpa   = LPA_10FULL | LPA_10HALF,
  44         },
  45         [SWMII_SPEED_100] = {
  46                 .bmsr  = BMSR_100FULL | BMSR_100HALF,
  47                 .lpa   = LPA_100FULL | LPA_100HALF,
  48         },
  49         [SWMII_SPEED_1000] = {
  50                 .bmsr  = BMSR_ESTATEN,
  51                 .lpagb = LPA_1000FULL | LPA_1000HALF,
  52                 .estat = ESTATUS_1000_TFULL | ESTATUS_1000_THALF,
  53         },
  54 };
  55 
  56 static const struct swmii_regs duplex[] = {
  57         [SWMII_DUPLEX_HALF] = {
  58                 .bmsr  = BMSR_ESTATEN | BMSR_100HALF,
  59                 .lpa   = LPA_10HALF | LPA_100HALF,
  60                 .lpagb = LPA_1000HALF,
  61                 .estat = ESTATUS_1000_THALF,
  62         },
  63         [SWMII_DUPLEX_FULL] = {
  64                 .bmsr  = BMSR_ESTATEN | BMSR_100FULL,
  65                 .lpa   = LPA_10FULL | LPA_100FULL,
  66                 .lpagb = LPA_1000FULL,
  67                 .estat = ESTATUS_1000_TFULL,
  68         },
  69 };
  70 
  71 static int swphy_decode_speed(int speed)
  72 {
  73         switch (speed) {
  74         case 1000:
  75                 return SWMII_SPEED_1000;
  76         case 100:
  77                 return SWMII_SPEED_100;
  78         case 10:
  79                 return SWMII_SPEED_10;
  80         default:
  81                 return -EINVAL;
  82         }
  83 }
  84 
  85 /**
  86  * swphy_validate_state - validate the software phy status
  87  * @state: software phy status
  88  *
  89  * This checks that we can represent the state stored in @state can be
  90  * represented in the emulated MII registers.  Returns 0 if it can,
  91  * otherwise returns -EINVAL.
  92  */
  93 int swphy_validate_state(const struct fixed_phy_status *state)
  94 {
  95         int err;
  96 
  97         if (state->link) {
  98                 err = swphy_decode_speed(state->speed);
  99                 if (err < 0) {
 100                         pr_warn("swphy: unknown speed\n");
 101                         return -EINVAL;
 102                 }
 103         }
 104         return 0;
 105 }
 106 EXPORT_SYMBOL_GPL(swphy_validate_state);
 107 
 108 /**
 109  * swphy_read_reg - return a MII register from the fixed phy state
 110  * @reg: MII register
 111  * @state: fixed phy status
 112  *
 113  * Return the MII @reg register generated from the fixed phy state @state.
 114  */
 115 int swphy_read_reg(int reg, const struct fixed_phy_status *state)
 116 {
 117         int speed_index, duplex_index;
 118         u16 bmsr = BMSR_ANEGCAPABLE;
 119         u16 estat = 0;
 120         u16 lpagb = 0;
 121         u16 lpa = 0;
 122 
 123         if (reg > MII_REGS_NUM)
 124                 return -1;
 125 
 126         speed_index = swphy_decode_speed(state->speed);
 127         if (WARN_ON(speed_index < 0))
 128                 return 0;
 129 
 130         duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF;
 131 
 132         bmsr |= speed[speed_index].bmsr & duplex[duplex_index].bmsr;
 133         estat |= speed[speed_index].estat & duplex[duplex_index].estat;
 134 
 135         if (state->link) {
 136                 bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
 137 
 138                 lpa   |= speed[speed_index].lpa   & duplex[duplex_index].lpa;
 139                 lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb;
 140 
 141                 if (state->pause)
 142                         lpa |= LPA_PAUSE_CAP;
 143 
 144                 if (state->asym_pause)
 145                         lpa |= LPA_PAUSE_ASYM;
 146         }
 147 
 148         switch (reg) {
 149         case MII_BMCR:
 150                 return BMCR_ANENABLE;
 151         case MII_BMSR:
 152                 return bmsr;
 153         case MII_PHYSID1:
 154         case MII_PHYSID2:
 155                 return 0;
 156         case MII_LPA:
 157                 return lpa;
 158         case MII_STAT1000:
 159                 return lpagb;
 160         case MII_ESTATUS:
 161                 return estat;
 162 
 163         /*
 164          * We do not support emulating Clause 45 over Clause 22 register
 165          * reads.  Return an error instead of bogus data.
 166          */
 167         case MII_MMD_CTRL:
 168         case MII_MMD_DATA:
 169                 return -1;
 170 
 171         default:
 172                 return 0xffff;
 173         }
 174 }
 175 EXPORT_SYMBOL_GPL(swphy_read_reg);

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