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>
This commit is contained in:
Russell King 2016-06-23 14:50:05 +01:00 committed by David S. Miller
parent 5db15872c5
commit 5ae68b0ce1
5 changed files with 143 additions and 93 deletions

View File

@ -12,6 +12,9 @@ menuconfig PHYLIB
if PHYLIB if PHYLIB
config SWPHY
bool
comment "MII PHY device drivers" comment "MII PHY device drivers"
config AQUANTIA_PHY config AQUANTIA_PHY
@ -159,6 +162,7 @@ config MICROCHIP_PHY
config FIXED_PHY config FIXED_PHY
tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB depends on PHYLIB
select SWPHY
---help--- ---help---
Adds the platform "fixed" MDIO Bus to cover the boards that use Adds the platform "fixed" MDIO Bus to cover the boards that use
PHYs that are not connected to the real MDIO bus. PHYs that are not connected to the real MDIO bus.

View File

@ -1,6 +1,7 @@
# Makefile for Linux PHY drivers # 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_PHYLIB) += libphy.o
obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o

View File

@ -24,6 +24,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include "swphy.h"
#define MII_REGS_NUM 29 #define MII_REGS_NUM 29
struct fixed_mdio_bus { 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) 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)) if (gpio_is_valid(fp->link_gpio))
fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio);
if (fp->status.duplex) { return swphy_update_regs(fp->regs, &fp->status);
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;
} }
static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num)

126
drivers/net/phy/swphy.c Normal file
View File

@ -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);

8
drivers/net/phy/swphy.h Normal file
View File

@ -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