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.
203 lines
4.7 KiB
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;
|
|
|