You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
freifunkist-firmware/target/linux/mvebu/patches-4.4/121-phy-convert-swphy-regis...

203 lines
4.7 KiB

From cd834fe430f030a63bfa9277bba194e8eef4dbd0 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@arm.linux.org.uk>
Date: Sun, 20 Sep 2015 10:18:59 +0100
Subject: [PATCH 710/744] 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: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
drivers/net/phy/swphy.c | 143 ++++++++++++++++++++++++++----------------------
1 file changed, 78 insertions(+), 65 deletions(-)
--- a/drivers/net/phy/swphy.c
+++ b/drivers/net/phy/swphy.c
@@ -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;