summaryrefslogtreecommitdiffstats
path: root/target/linux/mvebu/patches-4.4/121-phy-convert-swphy-register-generation-to-tabular-for.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mvebu/patches-4.4/121-phy-convert-swphy-register-generation-to-tabular-for.patch')
-rw-r--r--target/linux/mvebu/patches-4.4/121-phy-convert-swphy-register-generation-to-tabular-for.patch203
1 files changed, 203 insertions, 0 deletions
diff --git a/target/linux/mvebu/patches-4.4/121-phy-convert-swphy-register-generation-to-tabular-for.patch b/target/linux/mvebu/patches-4.4/121-phy-convert-swphy-register-generation-to-tabular-for.patch
new file mode 100644
index 0000000000..0d689f39a3
--- /dev/null
+++ b/target/linux/mvebu/patches-4.4/121-phy-convert-swphy-register-generation-to-tabular-for.patch
@@ -0,0 +1,203 @@
+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;