Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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