diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2016-06-23 14:50:05 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-27 10:40:57 -0400 |
commit | 5ae68b0ce134f9cadae2668da82d5f9a77523314 (patch) | |
tree | 84197594d3be3f377a2a14963a3968b6ec0631bf | |
parent | 5db15872c5370d9ae7b1d1c972a48b598b23b824 (diff) | |
download | linux-5ae68b0ce134f9cadae2668da82d5f9a77523314.tar.bz2 |
phy: move fixed_phy MII register generation to a library
Move the fixed_phy MII register generation to a library to allow other
software phy implementations to use this code.
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>
-rw-r--r-- | drivers/net/phy/Kconfig | 4 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/phy/fixed_phy.c | 95 | ||||
-rw-r--r-- | drivers/net/phy/swphy.c | 126 | ||||
-rw-r--r-- | drivers/net/phy/swphy.h | 8 |
5 files changed, 143 insertions, 93 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 8dac88abbc39..f96829415ce6 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -12,6 +12,9 @@ menuconfig PHYLIB if PHYLIB +config SWPHY + bool + comment "MII PHY device drivers" config AQUANTIA_PHY @@ -159,6 +162,7 @@ config MICROCHIP_PHY config FIXED_PHY tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" depends on PHYLIB + select SWPHY ---help--- Adds the platform "fixed" MDIO Bus to cover the boards that use PHYs that are not connected to the real MDIO bus. diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 4170642a2035..7158274327d0 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -1,6 +1,7 @@ # Makefile for Linux PHY drivers -libphy-objs := phy.o phy_device.o mdio_bus.o mdio_device.o +libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o +libphy-$(CONFIG_SWPHY) += swphy.o obj-$(CONFIG_PHYLIB) += libphy.o obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index 2d2e4339f0df..d98a0d90b5a5 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -24,6 +24,8 @@ #include <linux/of.h> #include <linux/gpio.h> +#include "swphy.h" + #define MII_REGS_NUM 29 struct fixed_mdio_bus { @@ -48,101 +50,10 @@ static struct fixed_mdio_bus platform_fmb = { static int fixed_phy_update_regs(struct fixed_phy *fp) { - u16 bmsr = BMSR_ANEGCAPABLE; - u16 bmcr = 0; - u16 lpagb = 0; - u16 lpa = 0; - if (gpio_is_valid(fp->link_gpio)) fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); - if (fp->status.duplex) { - switch (fp->status.speed) { - case 1000: - bmsr |= BMSR_ESTATEN; - break; - case 100: - bmsr |= BMSR_100FULL; - break; - case 10: - bmsr |= BMSR_10FULL; - break; - default: - break; - } - } else { - switch (fp->status.speed) { - case 1000: - bmsr |= BMSR_ESTATEN; - break; - case 100: - bmsr |= BMSR_100HALF; - break; - case 10: - bmsr |= BMSR_10HALF; - break; - default: - break; - } - } - - if (fp->status.link) { - bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; - - if (fp->status.duplex) { - bmcr |= BMCR_FULLDPLX; - - switch (fp->status.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("fixed phy: unknown speed\n"); - return -EINVAL; - } - } else { - switch (fp->status.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("fixed phy: unknown speed\n"); - return -EINVAL; - } - } - - if (fp->status.pause) - lpa |= LPA_PAUSE_CAP; - - if (fp->status.asym_pause) - lpa |= LPA_PAUSE_ASYM; - } - - fp->regs[MII_PHYSID1] = 0; - fp->regs[MII_PHYSID2] = 0; - - fp->regs[MII_BMSR] = bmsr; - fp->regs[MII_BMCR] = bmcr; - fp->regs[MII_LPA] = lpa; - fp->regs[MII_STAT1000] = lpagb; - - return 0; + return swphy_update_regs(fp->regs, &fp->status); } static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) diff --git a/drivers/net/phy/swphy.c b/drivers/net/phy/swphy.c new file mode 100644 index 000000000000..0551a79a2454 --- /dev/null +++ b/drivers/net/phy/swphy.c @@ -0,0 +1,126 @@ +/* + * Software PHY emulation + * + * Code taken from fixed_phy.c by Russell King <rmk+kernel@arm.linux.org.uk> + * + * Author: Vitaly Bordug <vbordug@ru.mvista.com> + * Anton Vorontsov <avorontsov@ru.mvista.com> + * + * Copyright (c) 2006-2007 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/export.h> +#include <linux/mii.h> +#include <linux/phy.h> +#include <linux/phy_fixed.h> + +#include "swphy.h" + +/** + * swphy_update_regs - update MII register array with fixed phy state + * @regs: array of 32 registers to update + * @state: fixed phy status + * + * Update the array of MII registers with the fixed phy link, speed, + * duplex and pause mode settings. + */ +int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state) +{ + 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; + } + } + + 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; + } + } + + if (state->pause) + lpa |= LPA_PAUSE_CAP; + + if (state->asym_pause) + lpa |= LPA_PAUSE_ASYM; + } + + regs[MII_PHYSID1] = 0; + regs[MII_PHYSID2] = 0; + + regs[MII_BMSR] = bmsr; + regs[MII_BMCR] = bmcr; + regs[MII_LPA] = lpa; + regs[MII_STAT1000] = lpagb; + + return 0; +} +EXPORT_SYMBOL_GPL(swphy_update_regs); diff --git a/drivers/net/phy/swphy.h b/drivers/net/phy/swphy.h new file mode 100644 index 000000000000..feaa38ff86a2 --- /dev/null +++ b/drivers/net/phy/swphy.h @@ -0,0 +1,8 @@ +#ifndef SWPHY_H +#define SWPHY_H + +struct fixed_phy_status; + +int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state); + +#endif |