Based on driver from Linux kernel 4.18.0-rc4

Signed-off-by: Sam Ravnborg <s...@ravnborg.org>
---
 drivers/net/phy/Kconfig   |   5 ++
 drivers/net/phy/Makefile  |   1 +
 drivers/net/phy/davicom.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+)
 create mode 100644 drivers/net/phy/davicom.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index cda752b65..79fb917ee 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -18,6 +18,11 @@ config AT803X_PHY
        ---help---
          Currently supports the AT8030, AT8031 and AT8035 PHYs.
 
+config DAVICOM_PHY
+       bool "Driver for Davicom PHYs"
+       ---help---
+         Currently supports dm9161e and dm9131
+
 config LXT_PHY
        bool "Driver for the Intel LXT PHYs"
        ---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 30b20f8ee..4424054d9 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,6 +1,7 @@
 obj-y += phy.o mdio_bus.o
 obj-$(CONFIG_AR8327N_PHY)      += ar8327.o
 obj-$(CONFIG_AT803X_PHY)       += at803x.o
+obj-$(CONFIG_DAVICOM_PHY)      += davicom.o
 obj-$(CONFIG_LXT_PHY)          += lxt.o
 obj-$(CONFIG_MARVELL_PHY)      += marvell.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
new file mode 100644
index 000000000..8a784b1e5
--- /dev/null
+++ b/drivers/net/phy/davicom.c
@@ -0,0 +1,140 @@
+/*
+ * drivers/net/phy/davicom.c
+ *
+ * Driver for Davicom PHYs
+ *
+ * Author: Andy Fleming
+ *
+ * Copyright (c) 2004 Freescale Semiconductor, 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 <common.h>
+#include <init.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#define MII_DM9161_SCR         0x10
+#define MII_DM9161_SCR_INIT    0x0610
+#define MII_DM9161_SCR_RMII    0x0100
+
+/* DM9161 Interrupt Register */
+#define MII_DM9161_INTR        0x15
+#define MII_DM9161_INTR_PEND           0x8000
+#define MII_DM9161_INTR_DPLX_MASK      0x0800
+#define MII_DM9161_INTR_SPD_MASK       0x0400
+#define MII_DM9161_INTR_LINK_MASK      0x0200
+#define MII_DM9161_INTR_MASK           0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE    0x0010
+#define MII_DM9161_INTR_SPD_CHANGE     0x0008
+#define MII_DM9161_INTR_LINK_CHANGE    0x0004
+#define MII_DM9161_INTR_INIT           0x0000
+#define MII_DM9161_INTR_STOP   \
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
+
+/* DM9161 10BT Configuration/Status */
+#define MII_DM9161_10BTCSR     0x12
+#define MII_DM9161_10BTCSR_INIT        0x7800
+
+MODULE_DESCRIPTION("Davicom PHY driver");
+MODULE_AUTHOR("Andy Fleming");
+MODULE_LICENSE("GPL");
+
+
+static int dm9161_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       /* Isolate the PHY */
+       err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+       if (err < 0)
+               return err;
+
+       /* Configure the new settings */
+       err = genphy_config_aneg(phydev);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int dm9161_config_init(struct phy_device *phydev)
+{
+       int err, temp;
+
+       /* Isolate the PHY */
+       err = phy_write(phydev, MII_BMCR, BMCR_ISOLATE);
+
+       if (err < 0)
+               return err;
+
+       switch (phydev->interface) {
+       case PHY_INTERFACE_MODE_MII:
+               temp = MII_DM9161_SCR_INIT;
+               break;
+       case PHY_INTERFACE_MODE_RMII:
+               temp =  MII_DM9161_SCR_INIT | MII_DM9161_SCR_RMII;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Do not bypass the scrambler/descrambler */
+       err = phy_write(phydev, MII_DM9161_SCR, temp);
+       if (err < 0)
+               return err;
+
+       /* Clear 10BTCSR to default */
+       err = phy_write(phydev, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+       if (err < 0)
+               return err;
+
+       /* Reconnect the PHY, and enable Autonegotiation */
+       return phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
+}
+
+static struct phy_driver dm91xx_driver[] = {
+{
+       .phy_id         = 0x0181b880,
+       .drv.name       = "Davicom DM9161E",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .config_init    = dm9161_config_init,
+       .config_aneg    = dm9161_config_aneg,
+}, {
+       .phy_id         = 0x0181b8b0,
+       .drv.name       = "Davicom DM9161B/C",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .config_init    = dm9161_config_init,
+       .config_aneg    = dm9161_config_aneg,
+}, {
+       .phy_id         = 0x0181b8a0,
+       .drv.name       = "Davicom DM9161A",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_BASIC_FEATURES,
+       .config_init    = dm9161_config_init,
+       .config_aneg    = dm9161_config_aneg,
+}, {
+       .phy_id         = 0x00181b80,
+       .drv.name       = "Davicom DM9131",
+       .phy_id_mask    = 0x0ffffff0,
+       .features       = PHY_BASIC_FEATURES,
+} };
+
+static int dm9161_init(void)
+{
+       return phy_drivers_register(dm91xx_driver,
+               ARRAY_SIZE(dm91xx_driver));
+}
+fs_initcall(dm9161_init);
-- 
2.12.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to