summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2012-11-18 13:49:45 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2012-11-20 09:38:33 +0100
commit34bcbaa2bab148e564272f0955cfd1e0f10862fb (patch)
treeaa7b68e8c03f403578d406e9206310edbbf0ce03
parent4a1e4d4b1da62a02f6ca32f44b709326bd764efc (diff)
downloadbarebox-34bcbaa2bab148e564272f0955cfd1e0f10862fb.tar.gz
barebox-34bcbaa2bab148e564272f0955cfd1e0f10862fb.tar.xz
phylib: add micrel support
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--drivers/net/phy/Kconfig5
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/micrel.c174
-rw-r--r--include/linux/micrel_phy.h30
4 files changed, 210 insertions, 0 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3f7c150a86..c75d73dd0b 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -8,6 +8,11 @@ if PHYLIB
comment "MII PHY device drivers"
+config MICREL_PHY
+ bool "Driver for Micrel PHYs"
+ ---help---
+ Supports the KSZ9021, VSC8201, KS8001 PHYs.
+
config SMSC_PHY
bool "Drivers for SMSC PHYs"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index dfc709a82e..5f8191d8a7 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -1,2 +1,3 @@
obj-y += phy.o mdio_bus.o
+obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
new file mode 100644
index 0000000000..0c6d43e613
--- /dev/null
+++ b/drivers/net/phy/micrel.c
@@ -0,0 +1,174 @@
+/*
+ * drivers/net/phy/micrel.c
+ *
+ * Driver for Micrel PHYs
+ *
+ * Author: David J. Choi
+ *
+ * Copyright (c) 2010 Micrel, 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.
+ *
+ * Support : ksz9021 1000/100/10 phy from Micrel
+ * ks8001, ks8737, ks8721, ks8041, ks8051 100/10 phy
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/micrel_phy.h>
+
+/* Operation Mode Strap Override */
+#define MII_KSZPHY_OMSO 0x16
+#define KSZPHY_OMSO_B_CAST_OFF (1 << 9)
+#define KSZPHY_OMSO_RMII_OVERRIDE (1 << 1)
+#define KSZPHY_OMSO_MII_OVERRIDE (1 << 0)
+
+/* general PHY control reg in vendor specific block. */
+#define MII_KSZPHY_CTRL 0x1F
+/* bitmap of PHY register to set interrupt mode */
+#define KSZPHY_CTRL_INT_ACTIVE_HIGH (1 << 9)
+#define KSZ9021_CTRL_INT_ACTIVE_HIGH (1 << 14)
+#define KS8737_CTRL_INT_ACTIVE_HIGH (1 << 14)
+#define KSZ8051_RMII_50MHZ_CLK (1 << 7)
+
+static int kszphy_config_init(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int ksz8021_config_init(struct phy_device *phydev)
+{
+ const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
+ phy_write(phydev, MII_KSZPHY_OMSO, val);
+ return 0;
+}
+
+static int ks8051_config_init(struct phy_device *phydev)
+{
+ int regval;
+
+ if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
+ regval = phy_read(phydev, MII_KSZPHY_CTRL);
+ regval |= KSZ8051_RMII_50MHZ_CLK;
+ phy_write(phydev, MII_KSZPHY_CTRL, regval);
+ }
+
+ return 0;
+}
+
+#define KSZ8873MLL_GLOBAL_CONTROL_4 0x06
+#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX (1 << 6)
+#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED (1 << 4)
+int ksz8873mll_read_status(struct phy_device *phydev)
+{
+ int regval;
+
+ /* dummy read */
+ regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+ regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+ if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
+ phydev->duplex = DUPLEX_HALF;
+ else
+ phydev->duplex = DUPLEX_FULL;
+
+ if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
+ phydev->speed = SPEED_10;
+ else
+ phydev->speed = SPEED_100;
+
+ phydev->link = 1;
+ phydev->pause = phydev->asym_pause = 0;
+
+ return 0;
+}
+
+static int ksz8873mll_config_aneg(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int ksz8873mll_config_init(struct phy_device *phydev)
+{
+ phydev->autoneg = AUTONEG_DISABLE;
+ phydev->link = 1;
+
+ return 0;
+}
+
+static struct phy_driver ksphy_driver[] = {
+{
+ .phy_id = PHY_ID_KS8737,
+ .phy_id_mask = 0x00fffff0,
+ .drv.name = "Micrel KS8737",
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .config_init = kszphy_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+}, {
+ .phy_id = PHY_ID_KSZ8021,
+ .phy_id_mask = 0x00ffffff,
+ .drv.name = "Micrel KSZ8021",
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause),
+ .config_init = ksz8021_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+}, {
+ .phy_id = PHY_ID_KSZ8041,
+ .phy_id_mask = 0x00fffff0,
+ .drv.name = "Micrel KSZ8041",
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+ .config_init = kszphy_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+}, {
+ .phy_id = PHY_ID_KSZ8051,
+ .phy_id_mask = 0x00fffff0,
+ .drv.name = "Micrel KSZ8051",
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+ .config_init = ks8051_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+}, {
+ .phy_id = PHY_ID_KSZ8001,
+ .drv.name = "Micrel KSZ8001 or KS8721",
+ .phy_id_mask = 0x00ffffff,
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
+ .config_init = kszphy_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+}, {
+ .phy_id = PHY_ID_KSZ9021,
+ .phy_id_mask = 0x000ffffe,
+ .drv.name = "Micrel KSZ9021 Gigabit PHY",
+ .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+ .config_init = kszphy_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+}, {
+ .phy_id = PHY_ID_KSZ8873MLL,
+ .phy_id_mask = 0x00fffff0,
+ .drv.name = "Micrel KSZ8873MLL Swithch",
+ .features = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
+ .config_init = ksz8873mll_config_init,
+ .config_aneg = ksz8873mll_config_aneg,
+ .read_status = ksz8873mll_read_status,
+} };
+
+static int ksphy_init(void)
+{
+ return phy_drivers_register(ksphy_driver,
+ ARRAY_SIZE(ksphy_driver));
+}
+fs_initcall(ksphy_init);
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
new file mode 100644
index 0000000000..adfe8c058f
--- /dev/null
+++ b/include/linux/micrel_phy.h
@@ -0,0 +1,30 @@
+/*
+ * include/linux/micrel_phy.h
+ *
+ * Micrel PHY IDs
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MICREL_PHY_H
+#define _MICREL_PHY_H
+
+#define MICREL_PHY_ID_MASK 0x00fffff0
+
+#define PHY_ID_KSZ8873MLL 0x000e7237
+#define PHY_ID_KSZ9021 0x00221610
+#define PHY_ID_KS8737 0x00221720
+#define PHY_ID_KSZ8021 0x00221555
+#define PHY_ID_KSZ8041 0x00221510
+#define PHY_ID_KSZ8051 0x00221550
+/* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
+#define PHY_ID_KSZ8001 0x0022161A
+
+/* struct phy_device dev_flags definitions */
+#define MICREL_PHY_50MHZ_CLK 0x00000001
+
+#endif /* _MICREL_PHY_H */