Skip to content

Commit

Permalink
phy: move fixed_phy MII register generation to a library
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Russell King authored and David S. Miller committed Jun 27, 2016
1 parent 5db1587 commit 5ae68b0
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 93 deletions.
4 changes: 4 additions & 0 deletions drivers/net/phy/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ menuconfig PHYLIB

if PHYLIB

config SWPHY
bool

comment "MII PHY device drivers"

config AQUANTIA_PHY
Expand Down Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/phy/Makefile
Original file line number Diff line number Diff line change
@@ -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
Expand Down
95 changes: 3 additions & 92 deletions drivers/net/phy/fixed_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <linux/of.h>
#include <linux/gpio.h>

#include "swphy.h"

#define MII_REGS_NUM 29

struct fixed_mdio_bus {
Expand All @@ -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)
Expand Down
126 changes: 126 additions & 0 deletions drivers/net/phy/swphy.c
Original file line number Diff line number Diff line change
@@ -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 changes: 8 additions & 0 deletions drivers/net/phy/swphy.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 5ae68b0

Please sign in to comment.