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