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.
306 lines
6.7 KiB
306 lines
6.7 KiB
From 4d5621372f6e7ddbfd5879602f82073987bcc722 Mon Sep 17 00:00:00 2001
|
|
From: Russell King <rmk+kernel@arm.linux.org.uk>
|
|
Date: Sun, 20 Sep 2015 09:57:10 +0100
|
|
Subject: [PATCH 709/744] 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>
|
|
---
|
|
drivers/net/phy/Kconfig | 4 ++
|
|
drivers/net/phy/Makefile | 3 +-
|
|
drivers/net/phy/fixed_phy.c | 95 ++-------------------------------
|
|
drivers/net/phy/swphy.c | 126 ++++++++++++++++++++++++++++++++++++++++++++
|
|
drivers/net/phy/swphy.h | 8 +++
|
|
5 files changed, 143 insertions(+), 93 deletions(-)
|
|
create mode 100644 drivers/net/phy/swphy.c
|
|
create mode 100644 drivers/net/phy/swphy.h
|
|
|
|
--- a/drivers/net/phy/Kconfig
|
|
+++ b/drivers/net/phy/Kconfig
|
|
@@ -26,6 +26,9 @@ config SWCONFIG_LEDS
|
|
bool "Switch LED trigger support"
|
|
depends on (SWCONFIG && LEDS_TRIGGERS)
|
|
|
|
+config SWPHY
|
|
+ bool
|
|
+
|
|
comment "MII PHY device drivers"
|
|
|
|
config AQUANTIA_PHY
|
|
@@ -205,6 +208,7 @@ config RTL8306_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.
|
|
--- 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
|
|
+libphy-y := phy.o phy_device.o mdio_bus.o
|
|
+libphy-$(CONFIG_SWPHY) += swphy.o
|
|
|
|
obj-$(CONFIG_MDIO_BOARDINFO) += mdio-boardinfo.o
|
|
|
|
--- 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 {
|
|
@@ -49,101 +51,10 @@ static struct fixed_mdio_bus platform_fm
|
|
|
|
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)
|
|
--- /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);
|
|
--- /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
|
|
|