[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <AM5PR0701MB26574EBBE4E7CACC9173B345E4670@AM5PR0701MB2657.eurprd07.prod.outlook.com>
Date: Fri, 22 Sep 2017 17:08:45 +0000
From: Bernd Edlinger <bernd.edlinger@...mail.de>
To: "netdev@...r.kernel.org" <netdev@...r.kernel.org>
CC: Andrew Lunn <andrew@...n.ch>,
Florian Fainelli <f.fainelli@...il.com>
Subject: [PATCH] Add a driver for Renesas uPD60620 and uPD60620A PHYs
Signed-off-by: Bernd Edlinger <bernd.edlinger@...mail.de>
---
drivers/net/phy/Kconfig | 5 +
drivers/net/phy/Makefile | 1 +
drivers/net/phy/uPD60620.c | 226
+++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 232 insertions(+)
create mode 100644 drivers/net/phy/uPD60620.c
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index a9d16a3..25089f0 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -287,6 +287,11 @@ config DP83867_PHY
---help---
Currently supports the DP83867 PHY.
+config RENESAS_PHY
+ tristate "Driver for Renesas PHYs"
+ ---help---
+ Supports the uPD60620 and uPD60620A PHYs.
+
config FIXED_PHY
tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 416df92..1404ad3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_MICROSEMI_PHY) += mscc.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
+obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
diff --git a/drivers/net/phy/uPD60620.c b/drivers/net/phy/uPD60620.c
new file mode 100644
index 0000000..b3d900c
--- /dev/null
+++ b/drivers/net/phy/uPD60620.c
@@ -0,0 +1,226 @@
+/*
+ * Driver for the Renesas PHY uPD60620.
+ *
+ * Copyright (C) 2015 Softing Industrial Automation GmbH
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define UPD60620_PHY_ID 0xb8242824
+
+/* Extended Registers and values */
+/* PHY Special Control/Status */
+#define PHY_PHYSCR 0x1F /* PHY.31 */
+#define PHY_PHYSCR_10MB 0x0004 /* PHY speed = 10mb */
+#define PHY_PHYSCR_100MB 0x0008 /* PHY speed = 100mb */
+#define PHY_PHYSCR_DUPLEX 0x0010 /* PHY Duplex */
+#define PHY_PHYSCR_RSVD5 0x0020 /* Reserved Bit 5 */
+#define PHY_PHYSCR_MIIMOD 0x0040 /* Enable 4B5B MII mode */
+#define PHY_PHYSCR_RSVD7 0x0080 /* Reserved Bit 7 */
+#define PHY_PHYSCR_RSVD8 0x0100 /* Reserved Bit 8 */
+#define PHY_PHYSCR_RSVD9 0x0200 /* Reserved Bit 9 */
+#define PHY_PHYSCR_RSVD10 0x0400 /* Reserved Bit 10 */
+#define PHY_PHYSCR_RSVD11 0x0800 /* Reserved Bit 11 */
+#define PHY_PHYSCR_ANDONE 0x1000 /* Auto negotiation done */
+#define PHY_PHYSCR_RSVD13 0x2000 /* Reserved Bit 13 */
+#define PHY_PHYSCR_RSVD14 0x4000 /* Reserved Bit 14 */
+#define PHY_PHYSCR_RSVD15 0x8000 /* Reserved Bit 15 */
+
+/* PHY Global Config Mapping */
+#define PHY_GLOBAL_CONFIG 0x07
+/* PHY GPIO Config Register 1 */
+#define PHY_GPIO_CONFIG1 0x01 /* PHY 7.1 */
+#define PHY_GPIO4_INT0 0x000d /* GPIO4 configuration */
+#define PHY_GPIO5_INT1 0x00d0 /* GPIO5 configuration */
+
+/* PHY Interrupt Control Register */
+#define PHY_ICR 0x1e /* PHY.30 */
+#define PHY_ICR_RSVD0 0x0001 /* Reserved bit 0 */
+#define PHY_ICR_ANCPRRN 0x0002 /* Auto negotiation paged received */
+#define PHY_ICR_PDFEN 0x0004 /* Parallel detection fault */
+#define PHY_ICR_ANCLPAEN 0x0008 /* Auto negotiation last page ack */
+#define PHY_ICR_LNKINTEN 0x0010 /* Link down */
+#define PHY_ICR_REMFD 0x0020 /* Remote fault detected */
+#define PHY_ICR_ANCINTEN 0x0040 /* Auto negotiation complete */
+#define PHY_ICR_EOEN 0x0080 /* Energy on generated */
+#define PHY_ICR_RSVD8 0x0100 /* Reserved bit 8 */
+#define PHY_ICR_FEQTRGEN 0x0200 /* FEQ Trigger */
+#define PHY_ICR_BERTRGEN 0x0400 /* BER Counter Trigger */
+#define PHY_ICR_MLINTEN 0x0800 /* Maxlvl */
+#define PHY_ICR_CLPINTEN 0x1000 /* Clipping */
+#define PHY_ICR_RSVD13 0x2000 /* Reserved bit 13 */
+#define PHY_ICR_RSVD14 0x4000 /* Reserved bit 14 */
+#define PHY_ICR_RSVD15 0x8000 /* Reserved bit 15 */
+
+/* PHY Interrupt Status Register */
+#define PHY_ISR 0x1d /* PHY.29 */
+#define PHY_ISR_DUPINT 0x0000 /* Placeholder for Duplex/Speed
intr */
+#define PHY_ISR_RSVD0 0x0001 /* Reserved bit 0 */
+#define PHY_ISR_ANCPR 0x0002 /* Auto negotiation paged received */
+#define PHY_ISR_PDF 0x0004 /* Parallel detection fault */
+#define PHY_ISR_ANCLPA 0x0008 /* Auto negotiation last page ack */
+#define PHY_ISR_LNKINT 0x0010 /* Link down */
+#define PHY_ISR_REMFD 0x0020 /* Remote fault detected */
+#define PHY_ISR_ANCINT 0x0040 /* Auto negotiation complete */
+#define PHY_ISR_EO 0x0080 /* Energy on generated */
+#define PHY_ISR_RSVD8 0x0100 /* Reserved bit 8 */
+#define PHY_ISR_FEQTRG 0x0200 /* FEQ Trigger */
+#define PHY_ISR_BERTRG 0x0400 /* BER Counter Trigger */
+#define PHY_ISR_MLINT 0x0800 /* Maxlvl */
+#define PHY_ISR_CLPINT 0x1000 /* Clipping */
+#define PHY_ISR_RSVD13 0x2000 /* Reserved bit 13 */
+#define PHY_ISR_RSVD14 0x4000 /* Reserved bit 14 */
+#define PHY_ISR_RSVD15 0x8000 /* Reserved bit 15 */
+
+/* PHY Diagnosis Control/Status Register*/
+#define PHY_DCS 0x19 /* PHY.25 */
+#define PHY_DCS_PWDIAG1 0x0001 /* Pulse Width Diagnosis -- 8ns */
+#define PHY_DCS_DIAGSEL 0x0020 /* Diagnosis select Tx or Rx */
+#define PHY_DCS_DIAGPOL 0x0040 /* Diagnosis stop polarity */
+#define PHY_DCS_DIAGDONE 0x0080 /* Diagnosis done */
+#define PHY_DCS_ADCTRIG05 0x0700 /* ADC Trigger level 0.5V for
cable len */
+#define PHY_DCS_ADCMAX 0x3F00 /* ADC Max value */
+#define PHY_DCS_DIAGINIT 0x4000 /* Init TDR test */
+
+/* PHY Diagnosis Counter Register */
+#define PHY_DCR 0x1a /* PHY.26 */
+#define PHY_DCR_DIGNCNT 0x00ff /* Diagnosis Count */
+#define PHY_DCR_CNTWIN 0xff00 /* Diagnosis Count Window */
+
+/* PHY Mode Control/Status Register */
+#define PHY_MCS 0x11 /* PHY.17 */
+#define PHY_MCS_RSVD0 0x0001 /* Reserved bit 0 */
+#define PHY_MCS_ENERGYON 0x0002 /* Energy on the Line status */
+#define PHY_MCS_FGLS 0x0004 /* Force Good Link Status */
+#define PHY_MCS_RSVD3 0x0008 /* Reserved bit 3 */
+#define PHY_MCS_DCDPATGEN 0x0010 /* DCD measuring pattern generation */
+#define PHY_MCS_RSVD5 0x0020 /* Reserved bit 5 */
+#define PHY_MCS_MDIMODE 0x0040 /* Force MDIX or MDI */
+#define PHY_MCS_AUTOMDIX 0x0080 /* Auto MDIX enable */
+#define PHY_MCS_FASTEST 0x0100 /* Auto negotiation test mode */
+#define PHY_MCS_FARLOOP 0x0200 /* Remote loopback enable */
+#define PHY_MCS_RSVD10 0x0400 /* Reserved bit 10 */
+#define PHY_MCS_LOWSQEN 0x0800 /* Squelch Threshold */
+#define PHY_MCS_RSVD12 0x1000 /* Reserved bit 12 */
+#define PHY_MCS_EPWRDOWN 0x2000 /* Power down mode enable */
+#define PHY_MCS_FASTRIP 0x4000 /* 10Base-T Fast mode */
+#define PHY_MCS_RSVD15 0x8000 /* Reserved bit 15 */
+
+/* PHY Special Modes */
+#define PHY_SPM 0x12 /* PHY.18 */
+#define PHY_SPM_FX_MODE 0x400 /* Enable 100BASE-FX mode */
+#define PHY_SPM_PHYMODE 0x1E0 /* PHY mode of operation */
+#define PHY_SPM_PHYADD 0x01F /* PHY address of device */
+
+/* PHY BER Counter Register */
+#define PHY_BER 0x17 /* PHY.23 */
+#define PHY_BER_COUNT 0x007f /* BER Count Bits 6-0 */
+#define PHY_BER_WINDOW 0x0780 /* BER Window Bits 10-7 */
+#define PHY_BER_CNT_TRIG 0x3800 /* BER count trigger bits 13-11 */
+#define PHY_BER_CNT_LNK_EN 0x4000 /* BER count link enable */
+#define PHY_BER_LNK_OK 0x8000 /* BER link OK */
+
+/* Init PHY */
+
+static int upd60620_config_init(struct phy_device *phydev)
+{
+ /* Enable support for passive HUBs (could be a strap option) */
+ /* PHYMODE: All speeds, HD in parallel detect */
+ return phy_write(phydev, PHY_SPM, 0x0180 | phydev->mdio.addr);
+}
+
+/* Get PHY status from common registers */
+
+static int upd60620_read_status(struct phy_device *phydev)
+{
+ int phy_state;
+
+ /* Read negotiated state */
+ phy_state = phy_read(phydev, MII_BMSR);
+ if (phy_state < 0)
+ return phy_state;
+
+ phydev->link = 0;
+ phydev->lp_advertising = 0;
+ phydev->pause = 0;
+ phydev->asym_pause = 0;
+
+ if (phy_state & BMSR_ANEGCOMPLETE) {
+ phy_state = phy_read(phydev, PHY_PHYSCR);
+ if (phy_state < 0)
+ return phy_state;
+
+ if (phy_state & (PHY_PHYSCR_10MB | PHY_PHYSCR_100MB)) {
+ phydev->link = 1;
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_HALF;
+
+ if (phy_state & PHY_PHYSCR_100MB)
+ phydev->speed = SPEED_100;
+ if (phy_state & PHY_PHYSCR_DUPLEX)
+ phydev->duplex = DUPLEX_FULL;
+
+ phy_state = phy_read(phydev, MII_LPA);
+ if (phy_state < 0)
+ return phy_state;
+
+ phydev->lp_advertising
+ = mii_lpa_to_ethtool_lpa_t(phy_state);
+
+ if (phydev->duplex == DUPLEX_FULL) {
+ if (phy_state & LPA_PAUSE_CAP)
+ phydev->pause = 1;
+ if (phy_state & LPA_PAUSE_ASYM)
+ phydev->asym_pause = 1;
+ }
+ }
+ } else if (phy_state & BMSR_LSTATUS) {
+ phy_state = phy_read(phydev, MII_BMCR);
+ if (phy_state < 0)
+ return phy_state;
+
+ if (!(phy_state & BMCR_ANENABLE)) {
+ phydev->link = 1;
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_HALF;
+
+ if (phy_state & BMCR_SPEED100)
+ phydev->speed = SPEED_100;
+ if (phy_state & BMCR_FULLDPLX)
+ phydev->duplex = DUPLEX_FULL;
+ }
+ }
+ return 0;
+}
+
+MODULE_DESCRIPTION("Renesas uPD60620 PHY driver");
+MODULE_AUTHOR("Bernd Edlinger <bernd.edlinger@...mail.de>");
+MODULE_LICENSE("GPL");
+
+static struct phy_driver upd60620_driver[1] = { {
+ .phy_id = UPD60620_PHY_ID,
+ .phy_id_mask = 0xfffffffe,
+ .name = "Renesas uPD60620",
+ .features = PHY_BASIC_FEATURES,
+ .flags = 0,
+ .config_init = upd60620_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = upd60620_read_status,
+} };
+
+module_phy_driver(upd60620_driver);
+
+static struct mdio_device_id __maybe_unused upd60620_tbl[] = {
+ { UPD60620_PHY_ID, 0xfffffffe },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, upd60620_tbl);
--
2.7.4
Powered by blists - more mailing lists