Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0629bf17 authored by Russell King's avatar Russell King Committed by David S. Miller
Browse files

phy: convert swphy register generation to tabular form



Convert the swphy register generation to tabular form which allows us
to eliminate multiple switch() statements.  This results in a smaller
object code size, more efficient, and easier to add support for faster
speeds.

Before:

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000164  00000000  00000000  00000034  2**2

   text    data     bss     dec     hex filename
    388       0       0     388     184 swphy.o

After:

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000fc  00000000  00000000  00000034  2**2
  5 .rodata       00000028  00000000  00000000  00000138  2**2

   text    data     bss     dec     hex filename
    324       0       0     324     144 swphy.o

Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5ae68b0c
Loading
Loading
Loading
Loading
+78 −65
Original line number Diff line number Diff line
@@ -20,6 +20,72 @@

#include "swphy.h"

struct swmii_regs {
	u16 bmcr;
	u16 bmsr;
	u16 lpa;
	u16 lpagb;
};

enum {
	SWMII_SPEED_10 = 0,
	SWMII_SPEED_100,
	SWMII_SPEED_1000,
	SWMII_DUPLEX_HALF = 0,
	SWMII_DUPLEX_FULL,
};

/*
 * These two tables get bitwise-anded together to produce the final result.
 * This means the speed table must contain both duplex settings, and the
 * duplex table must contain all speed settings.
 */
static const struct swmii_regs speed[] = {
	[SWMII_SPEED_10] = {
		.bmcr  = BMCR_FULLDPLX,
		.lpa   = LPA_10FULL | LPA_10HALF,
	},
	[SWMII_SPEED_100] = {
		.bmcr  = BMCR_FULLDPLX | BMCR_SPEED100,
		.bmsr  = BMSR_100FULL | BMSR_100HALF,
		.lpa   = LPA_100FULL | LPA_100HALF,
	},
	[SWMII_SPEED_1000] = {
		.bmcr  = BMCR_FULLDPLX | BMCR_SPEED1000,
		.bmsr  = BMSR_ESTATEN,
		.lpagb = LPA_1000FULL | LPA_1000HALF,
	},
};

static const struct swmii_regs duplex[] = {
	[SWMII_DUPLEX_HALF] = {
		.bmcr  = ~BMCR_FULLDPLX,
		.bmsr  = BMSR_ESTATEN | BMSR_100HALF,
		.lpa   = LPA_10HALF | LPA_100HALF,
		.lpagb = LPA_1000HALF,
	},
	[SWMII_DUPLEX_FULL] = {
		.bmcr  = ~0,
		.bmsr  = BMSR_ESTATEN | BMSR_100FULL,
		.lpa   = LPA_10FULL | LPA_100FULL,
		.lpagb = LPA_1000FULL,
	},
};

static int swphy_decode_speed(int speed)
{
	switch (speed) {
	case 1000:
		return SWMII_SPEED_1000;
	case 100:
		return SWMII_SPEED_100;
	case 10:
		return SWMII_SPEED_10;
	default:
		return -EINVAL;
	}
}

/**
 * swphy_update_regs - update MII register array with fixed phy state
 * @regs: array of 32 registers to update
@@ -30,81 +96,28 @@
 */
int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
{
	int speed_index, duplex_index;
	u16 bmsr = BMSR_ANEGCAPABLE;
	u16 bmcr = 0;
	u16 lpagb = 0;
	u16 lpa = 0;

	if (state->duplex) {
		switch (state->speed) {
		case 1000:
			bmsr |= BMSR_ESTATEN;
			break;
		case 100:
			bmsr |= BMSR_100FULL;
			break;
		case 10:
			bmsr |= BMSR_10FULL;
			break;
		default:
			break;
		}
	} else {
		switch (state->speed) {
		case 1000:
			bmsr |= BMSR_ESTATEN;
			break;
		case 100:
			bmsr |= BMSR_100HALF;
			break;
		case 10:
			bmsr |= BMSR_10HALF;
			break;
		default:
			break;
		}
	speed_index = swphy_decode_speed(state->speed);
	if (speed_index < 0) {
		pr_warn("swphy: unknown speed\n");
		return -EINVAL;
	}

	duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF;

	bmsr |= speed[speed_index].bmsr & duplex[duplex_index].bmsr;

	if (state->link) {
		bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;

		if (state->duplex) {
			bmcr |= BMCR_FULLDPLX;

			switch (state->speed) {
			case 1000:
				bmcr |= BMCR_SPEED1000;
				lpagb |= LPA_1000FULL;
				break;
			case 100:
				bmcr |= BMCR_SPEED100;
				lpa |= LPA_100FULL;
				break;
			case 10:
				lpa |= LPA_10FULL;
				break;
			default:
				pr_warn("swphy: unknown speed\n");
				return -EINVAL;
			}
		} else {
			switch (state->speed) {
			case 1000:
				bmcr |= BMCR_SPEED1000;
				lpagb |= LPA_1000HALF;
				break;
			case 100:
				bmcr |= BMCR_SPEED100;
				lpa |= LPA_100HALF;
				break;
			case 10:
				lpa |= LPA_10HALF;
				break;
			default:
				pr_warn("swphy: unknown speed\n");
				return -EINVAL;
			}
		}
		bmcr  |= speed[speed_index].bmcr  & duplex[duplex_index].bmcr;
		lpa   |= speed[speed_index].lpa   & duplex[duplex_index].lpa;
		lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb;

		if (state->pause)
			lpa |= LPA_PAUSE_CAP;