diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2016-06-23 14:50:10 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-27 10:40:57 -0400 |
commit | 0629bf17eaab9330bef427bdf4a3985c2d8972af (patch) | |
tree | 014542deacd2013dd7322d803a4ea121b72a8de4 /drivers/net/phy/swphy.c | |
parent | 5ae68b0ce134f9cadae2668da82d5f9a77523314 (diff) | |
download | linux-0629bf17eaab9330bef427bdf4a3985c2d8972af.tar.bz2 |
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy/swphy.c')
-rw-r--r-- | drivers/net/phy/swphy.c | 143 |
1 files changed, 78 insertions, 65 deletions
diff --git a/drivers/net/phy/swphy.c b/drivers/net/phy/swphy.c index 0551a79a2454..c88a194b4cb6 100644 --- 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; |