summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMatt Porter <mporter@ti.com>2013-03-20 05:38:13 +0000
committerTom Rini <trini@ti.com>2013-05-10 08:25:54 -0400
commitf485c8a35b38356a473208bec5ed786792c1eafe (patch)
tree366d16978a400ddf626923c978694161bb403858 /drivers
parentf6f86a64ac00980ba6066417bb54f39e39d29703 (diff)
phy: add support for ET1011C phys
Adds an ET1011C PHY driver which is derived from the Linux kernel PHY driver (drivers/net/phy/et1011c.c) from the v3.9-rc2 tag. Note that an errata workaround config option is implemented to allow for TX_CLK to be enabled even when gigabit mode is negotiated. This workaround is used on the PG1.0 TI814X EVM. Signed-off-by: Matt Porter <mporter@ti.com> Reviewed-by: Tom Rini <trini@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/et1011c.c110
-rw-r--r--drivers/net/phy/phy.c3
3 files changed, 114 insertions, 0 deletions
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 5e90d7098d..af5f4b848c 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -34,6 +34,7 @@ COBJS-$(CONFIG_PHYLIB_10G) += generic_10g.o
COBJS-$(CONFIG_PHY_ATHEROS) += atheros.o
COBJS-$(CONFIG_PHY_BROADCOM) += broadcom.o
COBJS-$(CONFIG_PHY_DAVICOM) += davicom.o
+COBJS-$(CONFIG_PHY_ET1011C) += et1011c.o
COBJS-$(CONFIG_PHY_LXT) += lxt.o
COBJS-$(CONFIG_PHY_MARVELL) += marvell.o
COBJS-$(CONFIG_PHY_MICREL) += micrel.o
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
new file mode 100644
index 0000000000..5e22399af1
--- /dev/null
+++ b/drivers/net/phy/et1011c.c
@@ -0,0 +1,110 @@
+/*
+ * ET1011C PHY driver
+ *
+ * Derived from Linux kernel driver by Chaithrika U S
+ * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <config.h>
+#include <phy.h>
+
+#define ET1011C_CONFIG_REG (0x16)
+#define ET1011C_TX_FIFO_MASK (0x3 << 12)
+#define ET1011C_TX_FIFO_DEPTH_8 (0x0 << 12)
+#define ET1011C_TX_FIFO_DEPTH_16 (0x1 << 12)
+#define ET1011C_INTERFACE_MASK (0x7 << 0)
+#define ET1011C_GMII_INTERFACE (0x2 << 0)
+#define ET1011C_SYS_CLK_EN (0x1 << 4)
+#define ET1011C_TX_CLK_EN (0x1 << 5)
+
+#define ET1011C_STATUS_REG (0x1A)
+#define ET1011C_DUPLEX_STATUS (0x1 << 7)
+#define ET1011C_SPEED_MASK (0x3 << 8)
+#define ET1011C_SPEED_1000 (0x2 << 8)
+#define ET1011C_SPEED_100 (0x1 << 8)
+#define ET1011C_SPEED_10 (0x0 << 8)
+
+static int et1011c_config(struct phy_device *phydev)
+{
+ int ctl = 0;
+ ctl = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
+ if (ctl < 0)
+ return ctl;
+ ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 |
+ BMCR_ANENABLE);
+ /* First clear the PHY */
+ phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, ctl | BMCR_RESET);
+
+ return genphy_config_aneg(phydev);
+}
+
+static int et1011c_parse_status(struct phy_device *phydev)
+{
+ int mii_reg;
+ int speed;
+
+ mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_STATUS_REG);
+
+ if (mii_reg & ET1011C_DUPLEX_STATUS)
+ phydev->duplex = DUPLEX_FULL;
+ else
+ phydev->duplex = DUPLEX_HALF;
+
+ speed = mii_reg & ET1011C_SPEED_MASK;
+ switch (speed) {
+ case ET1011C_SPEED_1000:
+ phydev->speed = SPEED_1000;
+ mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG);
+ mii_reg &= ~ET1011C_TX_FIFO_MASK;
+ phy_write(phydev, MDIO_DEVAD_NONE, ET1011C_CONFIG_REG,
+ mii_reg |
+ ET1011C_GMII_INTERFACE |
+ ET1011C_SYS_CLK_EN |
+#ifdef CONFIG_PHY_ET1011C_TX_CLK_FIX
+ ET1011C_TX_CLK_EN |
+#endif
+ ET1011C_TX_FIFO_DEPTH_16);
+ break;
+ case ET1011C_SPEED_100:
+ phydev->speed = SPEED_100;
+ break;
+ case ET1011C_SPEED_10:
+ phydev->speed = SPEED_10;
+ break;
+ }
+
+ return 0;
+}
+
+static int et1011c_startup(struct phy_device *phydev)
+{
+ genphy_update_link(phydev);
+ et1011c_parse_status(phydev);
+ return 0;
+}
+
+static struct phy_driver et1011c_driver = {
+ .name = "ET1011C",
+ .uid = 0x0282f014,
+ .mask = 0xfffffff0,
+ .features = PHY_GBIT_FEATURES,
+ .config = &et1011c_config,
+ .startup = &et1011c_startup,
+};
+
+int phy_et1011c_init(void)
+{
+ phy_register(&et1011c_driver);
+
+ return 0;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d0ed7666ed..f8c5481477 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -430,6 +430,9 @@ int phy_init(void)
#ifdef CONFIG_PHY_DAVICOM
phy_davicom_init();
#endif
+#ifdef CONFIG_PHY_ET1011C
+ phy_et1011c_init();
+#endif
#ifdef CONFIG_PHY_LXT
phy_lxt_init();
#endif