brintos

brintos / linux-shallow public Read only

0
0
Text · 3.7 KiB · 59f1ba4 Raw
176 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Software PHY emulation4 *5 * Code taken from fixed_phy.c by Russell King.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 2920 21struct swmii_regs {22	u16 bmsr;23	u16 lpa;24	u16 lpagb;25	u16 estat;26};27 28enum {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 the39 * duplex table must contain all speed settings.40 */41static 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 56static 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 71static 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 status87 * @state: software phy status88 *89 * This checks that we can represent the state stored in @state can be90 * represented in the emulated MII registers.  Returns 0 if it can,91 * otherwise returns -EINVAL.92 */93int 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}106EXPORT_SYMBOL_GPL(swphy_validate_state);107 108/**109 * swphy_read_reg - return a MII register from the fixed phy state110 * @reg: MII register111 * @state: fixed phy status112 *113 * Return the MII @reg register generated from the fixed phy state @state.114 */115int 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 register165	 * 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}175EXPORT_SYMBOL_GPL(swphy_read_reg);176